Merge branch 'master' into fix_108
This commit is contained in:
commit
88213f1c39
79 changed files with 1317 additions and 238 deletions
|
|
@ -100,11 +100,13 @@ class MainActivity : SimpleActivity() {
|
|||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
updateMenuItemColors(menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.search -> launchSearch()
|
||||
R.id.settings -> launchSettings()
|
||||
R.id.about -> launchAbout()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
|
|
@ -182,7 +184,7 @@ class MainActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun getNewConversations(cachedConversations: ArrayList<Conversation>) {
|
||||
val privateCursor = getMyContactsCursor()?.loadInBackground()
|
||||
val privateCursor = getMyContactsCursor(false, true)?.loadInBackground()
|
||||
ensureBackgroundThread {
|
||||
val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor)
|
||||
val conversations = getConversations(privateContacts = privateContacts)
|
||||
|
|
@ -245,6 +247,7 @@ class MainActivity : SimpleActivity() {
|
|||
conversations_list.adapter = this
|
||||
}
|
||||
|
||||
conversations_list.scheduleLayoutAnimation()
|
||||
conversations_fastscroller.setViews(conversations_list) {
|
||||
val listItem = (conversations_list.adapter as? ConversationsAdapter)?.conversations?.getOrNull(it)
|
||||
conversations_fastscroller.updateBubbleText(listItem?.title ?: "")
|
||||
|
|
@ -295,6 +298,10 @@ class MainActivity : SimpleActivity() {
|
|||
.build()
|
||||
}
|
||||
|
||||
private fun launchSearch() {
|
||||
startActivity(Intent(applicationContext, SearchActivity::class.java))
|
||||
}
|
||||
|
||||
private fun launchSettings() {
|
||||
startActivity(Intent(applicationContext, SettingsActivity::class.java))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@ import android.view.Menu
|
|||
import android.view.WindowManager
|
||||
import com.google.gson.Gson
|
||||
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.commons.models.SimpleContact
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.adapters.ContactsAdapter
|
||||
|
|
@ -62,7 +64,10 @@ class NewConversationActivity : SimpleActivity() {
|
|||
val searchString = it
|
||||
val filteredContacts = ArrayList<SimpleContact>()
|
||||
allContacts.forEach {
|
||||
if (it.phoneNumbers.any { it.contains(searchString, true) } || it.name.contains(searchString, true)) {
|
||||
if (it.phoneNumbers.any { it.contains(searchString, true) } ||
|
||||
it.name.contains(searchString, true) ||
|
||||
it.name.contains(searchString.normalizeString(), true) ||
|
||||
it.name.normalizeString().contains(searchString, true)) {
|
||||
filteredContacts.add(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -87,9 +92,12 @@ class NewConversationActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
val adjustedPrimaryColor = getAdjustedPrimaryColor()
|
||||
contacts_letter_fastscroller.textColor = config.textColor.getColorStateList()
|
||||
contacts_letter_fastscroller.pressedTextColor = adjustedPrimaryColor
|
||||
contacts_letter_fastscroller_thumb.setupWithFastScroller(contacts_letter_fastscroller)
|
||||
contacts_letter_fastscroller_thumb.textColor = config.primaryColor.getContrastColor()
|
||||
contacts_letter_fastscroller_thumb?.textColor = adjustedPrimaryColor.getContrastColor()
|
||||
contacts_letter_fastscroller_thumb?.thumbColor = adjustedPrimaryColor.getColorStateList()
|
||||
}
|
||||
|
||||
private fun isThirdPartyIntent(): Boolean {
|
||||
|
|
@ -130,18 +138,38 @@ class NewConversationActivity : SimpleActivity() {
|
|||
no_contacts_placeholder.text = getString(placeholderText)
|
||||
}
|
||||
|
||||
ContactsAdapter(this, contacts, contacts_list, null) {
|
||||
hideKeyboard()
|
||||
launchThreadActivity((it as SimpleContact).phoneNumbers.first(), it.name)
|
||||
}.apply {
|
||||
contacts_list.adapter = this
|
||||
val currAdapter = contacts_list.adapter
|
||||
if (currAdapter == null) {
|
||||
ContactsAdapter(this, contacts, contacts_list, null) {
|
||||
hideKeyboard()
|
||||
val contact = it as SimpleContact
|
||||
val phoneNumbers = contact.phoneNumbers
|
||||
if (phoneNumbers.size > 1) {
|
||||
val items = ArrayList<RadioItem>()
|
||||
phoneNumbers.forEachIndexed { index, phoneNumber ->
|
||||
items.add(RadioItem(index, phoneNumber, phoneNumber))
|
||||
}
|
||||
|
||||
RadioGroupDialog(this, items) {
|
||||
launchThreadActivity(it as String, contact.name)
|
||||
}
|
||||
} else {
|
||||
launchThreadActivity(phoneNumbers.first(), contact.name)
|
||||
}
|
||||
}.apply {
|
||||
contacts_list.adapter = this
|
||||
}
|
||||
|
||||
contacts_list.scheduleLayoutAnimation()
|
||||
} else {
|
||||
(currAdapter as ContactsAdapter).updateContacts(contacts)
|
||||
}
|
||||
|
||||
setupLetterFastscroller(contacts)
|
||||
}
|
||||
|
||||
private fun fillSuggestedContacts(callback: () -> Unit) {
|
||||
val privateCursor = getMyContactsCursor()?.loadInBackground()
|
||||
val privateCursor = getMyContactsCursor(false, true)?.loadInBackground()
|
||||
ensureBackgroundThread {
|
||||
privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor)
|
||||
val suggestions = getSuggestedContacts(privateContacts)
|
||||
|
|
@ -179,7 +207,7 @@ class NewConversationActivity : SimpleActivity() {
|
|||
try {
|
||||
val name = contacts[position].name
|
||||
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
|
||||
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()))
|
||||
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()).normalizeString())
|
||||
} catch (e: Exception) {
|
||||
FastScrollItemIndicator.Text("")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
package com.simplemobiletools.smsmessenger.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.SearchManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.util.TypedValue
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.view.MenuItemCompat
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.adapters.SearchResultsAdapter
|
||||
import com.simplemobiletools.smsmessenger.extensions.conversationsDB
|
||||
import com.simplemobiletools.smsmessenger.extensions.messagesDB
|
||||
import com.simplemobiletools.smsmessenger.helpers.SEARCHED_MESSAGE_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_TITLE
|
||||
import com.simplemobiletools.smsmessenger.models.Conversation
|
||||
import com.simplemobiletools.smsmessenger.models.Message
|
||||
import com.simplemobiletools.smsmessenger.models.SearchResult
|
||||
import kotlinx.android.synthetic.main.activity_search.*
|
||||
|
||||
class SearchActivity : SimpleActivity() {
|
||||
private var mIsSearchOpen = false
|
||||
private var mLastSearchedText = ""
|
||||
private var mSearchMenuItem: MenuItem? = null
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_search)
|
||||
updateTextColors(search_holder)
|
||||
search_placeholder.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize())
|
||||
search_placeholder_2.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize())
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_search, menu)
|
||||
setupSearch(menu)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun setupSearch(menu: Menu) {
|
||||
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
||||
mSearchMenuItem = menu.findItem(R.id.search)
|
||||
|
||||
MenuItemCompat.setOnActionExpandListener(mSearchMenuItem, object : MenuItemCompat.OnActionExpandListener {
|
||||
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
|
||||
mIsSearchOpen = true
|
||||
return true
|
||||
}
|
||||
|
||||
// this triggers on device rotation too, avoid doing anything
|
||||
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
|
||||
if (mIsSearchOpen) {
|
||||
mIsSearchOpen = false
|
||||
mLastSearchedText = ""
|
||||
finish()
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
mSearchMenuItem?.expandActionView()
|
||||
(mSearchMenuItem?.actionView as? SearchView)?.apply {
|
||||
setSearchableInfo(searchManager.getSearchableInfo(componentName))
|
||||
isSubmitButtonEnabled = false
|
||||
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String) = false
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
if (mIsSearchOpen) {
|
||||
mLastSearchedText = newText
|
||||
textChanged(newText)
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun textChanged(text: String) {
|
||||
search_placeholder_2.beGoneIf(text.length >= 2)
|
||||
if (text.length >= 2) {
|
||||
ensureBackgroundThread {
|
||||
val searchQuery = "%$text%"
|
||||
val messages = messagesDB.getMessagesWithText(searchQuery)
|
||||
val conversations = conversationsDB.getConversationsWithText(searchQuery)
|
||||
if (text == mLastSearchedText) {
|
||||
showSearchResults(messages, conversations, text)
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
search_placeholder.beVisible()
|
||||
search_results_list.beGone()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSearchResults(messages: List<Message>, conversations: List<Conversation>, searchedText: String) {
|
||||
val searchResults = ArrayList<SearchResult>()
|
||||
conversations.forEach { conversation ->
|
||||
val date = conversation.date.formatDateOrTime(this, true, true)
|
||||
val searchResult = SearchResult(-1, conversation.title, conversation.phoneNumber, date, conversation.threadId, conversation.photoUri)
|
||||
searchResults.add(searchResult)
|
||||
}
|
||||
|
||||
messages.forEach { message ->
|
||||
var recipient = message.senderName
|
||||
if (recipient.isEmpty() && message.participants.isNotEmpty()) {
|
||||
val participantNames = message.participants.map { it.name }
|
||||
recipient = TextUtils.join(", ", participantNames)
|
||||
}
|
||||
|
||||
val date = message.date.formatDateOrTime(this, true, true)
|
||||
val searchResult = SearchResult(message.id, recipient, message.body, date, message.threadId, message.senderPhotoUri)
|
||||
searchResults.add(searchResult)
|
||||
}
|
||||
|
||||
runOnUiThread {
|
||||
search_results_list.beVisibleIf(searchResults.isNotEmpty())
|
||||
search_placeholder.beVisibleIf(searchResults.isEmpty())
|
||||
|
||||
val currAdapter = search_results_list.adapter
|
||||
if (currAdapter == null) {
|
||||
SearchResultsAdapter(this, searchResults, search_results_list, searchedText) {
|
||||
Intent(this, ThreadActivity::class.java).apply {
|
||||
putExtra(THREAD_ID, (it as SearchResult).threadId)
|
||||
putExtra(THREAD_TITLE, it.title)
|
||||
putExtra(SEARCHED_MESSAGE_ID, it.messageId)
|
||||
startActivity(this)
|
||||
}
|
||||
}.apply {
|
||||
search_results_list.adapter = this
|
||||
}
|
||||
} else {
|
||||
(currAdapter as SearchResultsAdapter).updateItems(searchResults, searchedText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@ class SettingsActivity : SimpleActivity() {
|
|||
|
||||
setupPurchaseThankYou()
|
||||
setupCustomizeColors()
|
||||
setupCustomizeNotifications()
|
||||
setupUseEnglish()
|
||||
setupManageBlockedNumbers()
|
||||
setupChangeDateTimeFormat()
|
||||
|
|
@ -71,6 +72,13 @@ class SettingsActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupCustomizeNotifications() {
|
||||
settings_customize_notifications_holder.beVisibleIf(isOreoPlus())
|
||||
settings_customize_notifications_holder.setOnClickListener {
|
||||
launchCustomizeNotificationsIntent()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupUseEnglish() {
|
||||
settings_use_english_holder.beVisibleIf(config.wasUseEnglishToggled || Locale.getDefault().language != "en")
|
||||
settings_use_english.isChecked = config.useEnglish
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import android.app.Activity
|
|||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
|
|
@ -88,6 +89,15 @@ class ThreadActivity : SimpleActivity() {
|
|||
if (it) {
|
||||
setupButtons()
|
||||
setupCachedMessages {
|
||||
val searchedMessageId = intent.getLongExtra(SEARCHED_MESSAGE_ID, -1L)
|
||||
intent.removeExtra(SEARCHED_MESSAGE_ID)
|
||||
if (searchedMessageId != -1L) {
|
||||
val index = threadItems.indexOfFirst { (it as? Message)?.id == searchedMessageId }
|
||||
if (index != -1) {
|
||||
thread_messages_list.smoothScrollToPosition(index)
|
||||
}
|
||||
}
|
||||
|
||||
setupThread()
|
||||
}
|
||||
} else {
|
||||
|
|
@ -106,13 +116,83 @@ class ThreadActivity : SimpleActivity() {
|
|||
isActivityVisible = false
|
||||
}
|
||||
|
||||
private fun setupThread() {
|
||||
val privateCursor = getMyContactsCursor()?.loadInBackground()
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
bus?.unregister(this)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_thread, menu)
|
||||
menu.apply {
|
||||
findItem(R.id.delete).isVisible = threadItems.isNotEmpty()
|
||||
findItem(R.id.block_number).isVisible = isNougatPlus()
|
||||
}
|
||||
|
||||
updateMenuItemColors(menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (participants.isEmpty()) {
|
||||
return true
|
||||
}
|
||||
|
||||
when (item.itemId) {
|
||||
R.id.block_number -> blockNumber()
|
||||
R.id.delete -> askConfirmDelete()
|
||||
R.id.manage_people -> managePeople()
|
||||
R.id.mark_as_unread -> markAsUnread()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, resultData)
|
||||
if (requestCode == PICK_ATTACHMENT_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
|
||||
addAttachment(resultData.data!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCachedMessages(callback: () -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
val cachedMessagesCode = messages.hashCode()
|
||||
messages = try {
|
||||
messagesDB.getThreadMessages(threadId).toMutableList() as ArrayList<Message>
|
||||
} catch (e: Exception) {
|
||||
ArrayList()
|
||||
}
|
||||
|
||||
setupParticipants()
|
||||
setupAdapter()
|
||||
|
||||
runOnUiThread {
|
||||
if (messages.isEmpty()) {
|
||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
thread_type_message.requestFocus()
|
||||
}
|
||||
|
||||
setupThreadTitle()
|
||||
setupSIMSelector()
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupThread() {
|
||||
val privateCursor = getMyContactsCursor(false, true)?.loadInBackground()
|
||||
ensureBackgroundThread {
|
||||
val cachedMessagesCode = messages.clone().hashCode()
|
||||
messages = getMessages(threadId)
|
||||
if (messages.hashCode() == cachedMessagesCode) {
|
||||
return@ensureBackgroundThread
|
||||
|
||||
val hasParticipantWithoutName = participants.any {
|
||||
it.phoneNumbers.contains(it.name)
|
||||
}
|
||||
|
||||
try {
|
||||
if (participants.isNotEmpty() && messages.hashCode() == cachedMessagesCode && !hasParticipantWithoutName) {
|
||||
return@ensureBackgroundThread
|
||||
}
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
||||
setupParticipants()
|
||||
|
|
@ -162,63 +242,6 @@ class ThreadActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
bus?.unregister(this)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_thread, menu)
|
||||
menu.apply {
|
||||
findItem(R.id.delete).isVisible = threadItems.isNotEmpty()
|
||||
findItem(R.id.block_number).isVisible = isNougatPlus()
|
||||
}
|
||||
|
||||
updateMenuItemColors(menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (participants.isEmpty()) {
|
||||
return true
|
||||
}
|
||||
|
||||
when (item.itemId) {
|
||||
R.id.block_number -> blockNumber()
|
||||
R.id.delete -> askConfirmDelete()
|
||||
R.id.manage_people -> managePeople()
|
||||
R.id.mark_as_unread -> markAsUnread()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, resultData)
|
||||
if (requestCode == PICK_ATTACHMENT_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
|
||||
addAttachment(resultData.data!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCachedMessages(callback: () -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
messages = messagesDB.getThreadMessages(threadId).toMutableList() as ArrayList<Message>
|
||||
setupParticipants()
|
||||
setupAdapter()
|
||||
|
||||
runOnUiThread {
|
||||
if (messages.isEmpty()) {
|
||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
thread_type_message.requestFocus()
|
||||
}
|
||||
|
||||
setupThreadTitle()
|
||||
setupSIMSelector()
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAdapter() {
|
||||
threadItems = getThreadItems()
|
||||
invalidateOptionsMenu()
|
||||
|
|
@ -458,11 +481,20 @@ class ThreadActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun showSelectedContacts() {
|
||||
val adjustedColor = getAdjustedPrimaryColor()
|
||||
|
||||
val views = ArrayList<View>()
|
||||
participants.forEach {
|
||||
val contact = it
|
||||
layoutInflater.inflate(R.layout.item_selected_contact, null).apply {
|
||||
val selectedContactBg = resources.getDrawable(R.drawable.item_selected_contact_background)
|
||||
(selectedContactBg as LayerDrawable).findDrawableByLayerId(R.id.selected_contact_bg).applyColorFilter(adjustedColor)
|
||||
selected_contact_holder.background = selectedContactBg
|
||||
|
||||
selected_contact_name.text = contact.name
|
||||
selected_contact_name.setTextColor(adjustedColor.getContrastColor())
|
||||
selected_contact_remove.applyColorFilter(adjustedColor.getContrastColor())
|
||||
|
||||
selected_contact_remove.setOnClickListener {
|
||||
if (contact.rawId != participants.first().rawId) {
|
||||
removeSelectedContact(contact.rawId)
|
||||
|
|
@ -514,7 +546,7 @@ class ThreadActivity : SimpleActivity() {
|
|||
var hadUnreadItems = false
|
||||
val cnt = messages.size
|
||||
for (i in 0 until cnt) {
|
||||
val message = messages[i]
|
||||
val message = messages.getOrNull(i) ?: continue
|
||||
// do not show the date/time above every message, only if the difference between the 2 messages is at least MIN_DATE_TIME_DIFF_SECS
|
||||
if (message.date - prevDateTime > MIN_DATE_TIME_DIFF_SECS) {
|
||||
val simCardID = subscriptionIdToSimId[message.subscriptionId] ?: "?"
|
||||
|
|
|
|||
|
|
@ -5,35 +5,46 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Filter
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import com.simplemobiletools.commons.extensions.darkenColor
|
||||
import com.simplemobiletools.commons.extensions.getContrastColor
|
||||
import com.simplemobiletools.commons.extensions.normalizeString
|
||||
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
||||
import com.simplemobiletools.commons.models.SimpleContact
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.activities.SimpleActivity
|
||||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
|
||||
class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: ArrayList<SimpleContact>) : ArrayAdapter<SimpleContact>(activity, 0, contacts) {
|
||||
var resultList = ArrayList<SimpleContact>()
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val contact = resultList[position]
|
||||
val contact = resultList.getOrNull(position)
|
||||
var listItem = convertView
|
||||
if (listItem == null || listItem.tag != contact.name.isNotEmpty()) {
|
||||
if (listItem == null || listItem.tag != contact?.name?.isNotEmpty()) {
|
||||
listItem = LayoutInflater.from(activity).inflate(R.layout.item_contact_with_number, parent, false)
|
||||
}
|
||||
|
||||
listItem!!.apply {
|
||||
tag = contact.name.isNotEmpty()
|
||||
tag = contact?.name?.isNotEmpty()
|
||||
// clickable and focusable properties seem to break Autocomplete clicking, so remove them
|
||||
findViewById<View>(R.id.item_contact_frame).apply {
|
||||
isClickable = false
|
||||
isFocusable = false
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.item_contact_name).text = contact.name
|
||||
findViewById<TextView>(R.id.item_contact_number).text = contact.phoneNumbers.first()
|
||||
val backgroundColor = activity.config.backgroundColor
|
||||
findViewById<RelativeLayout>(R.id.item_contact_holder).setBackgroundColor(backgroundColor.darkenColor())
|
||||
|
||||
SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.name)
|
||||
findViewById<TextView>(R.id.item_contact_name).setTextColor(backgroundColor.getContrastColor())
|
||||
findViewById<TextView>(R.id.item_contact_number).setTextColor(backgroundColor.getContrastColor())
|
||||
|
||||
if (contact != null) {
|
||||
findViewById<TextView>(R.id.item_contact_name).text = contact.name
|
||||
findViewById<TextView>(R.id.item_contact_number).text = contact.phoneNumbers.first()
|
||||
SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.name)
|
||||
}
|
||||
}
|
||||
|
||||
return listItem
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ import com.simplemobiletools.smsmessenger.R
|
|||
import com.simplemobiletools.smsmessenger.activities.SimpleActivity
|
||||
import java.util.*
|
||||
|
||||
class ContactsAdapter(activity: SimpleActivity, var contacts: ArrayList<SimpleContact>, recyclerView: MyRecyclerView, fastScroller: FastScroller?,
|
||||
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
class ContactsAdapter(
|
||||
activity: SimpleActivity, var contacts: ArrayList<SimpleContact>, recyclerView: MyRecyclerView, fastScroller: FastScroller?,
|
||||
itemClick: (Any) -> Unit
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
private var fontSize = activity.getTextSize()
|
||||
|
||||
override fun getActionMenuId() = 0
|
||||
|
|
@ -51,10 +53,12 @@ class ContactsAdapter(activity: SimpleActivity, var contacts: ArrayList<SimpleCo
|
|||
|
||||
override fun getItemCount() = contacts.size
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isDestroyed && !activity.isFinishing) {
|
||||
Glide.with(activity).clear(holder.itemView.findViewById<ImageView>(R.id.item_contact_image))
|
||||
fun updateContacts(newContacts: ArrayList<SimpleContact>) {
|
||||
val oldHashCode = contacts.hashCode()
|
||||
val newHashCode = newContacts.hashCode()
|
||||
if (newHashCode != oldHashCode) {
|
||||
contacts = newContacts
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,4 +79,11 @@ class ContactsAdapter(activity: SimpleActivity, var contacts: ArrayList<SimpleCo
|
|||
SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isDestroyed && !activity.isFinishing) {
|
||||
Glide.with(activity).clear(holder.itemView.findViewById<ImageView>(R.id.item_contact_image))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.simplemobiletools.smsmessenger.adapters
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.net.Uri
|
||||
|
|
@ -26,8 +27,10 @@ import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
|||
import com.simplemobiletools.smsmessenger.models.Conversation
|
||||
import kotlinx.android.synthetic.main.item_conversation.view.*
|
||||
|
||||
class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayList<Conversation>, recyclerView: MyRecyclerView, fastScroller: FastScroller,
|
||||
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
class ConversationsAdapter(
|
||||
activity: SimpleActivity, var conversations: ArrayList<Conversation>, recyclerView: MyRecyclerView, fastScroller: FastScroller,
|
||||
itemClick: (Any) -> Unit
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
private var fontSize = activity.getTextSize()
|
||||
|
||||
init {
|
||||
|
|
@ -120,11 +123,13 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
|
|||
Intent(Intent.ACTION_DIAL).apply {
|
||||
data = Uri.fromParts("tel", conversation.phoneNumber, null)
|
||||
|
||||
if (resolveActivity(activity.packageManager) != null) {
|
||||
try {
|
||||
activity.startActivity(this)
|
||||
finishActMode()
|
||||
} else {
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
activity.toast(R.string.no_app_found)
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -185,12 +190,7 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
|
|||
action = Intent.ACTION_INSERT_OR_EDIT
|
||||
type = "vnd.android.cursor.item/contact"
|
||||
putExtra(KEY_PHONE, conversation.phoneNumber)
|
||||
|
||||
if (resolveActivity(activity.packageManager) != null) {
|
||||
activity.startActivity(this)
|
||||
} else {
|
||||
activity.toast(R.string.no_app_found)
|
||||
}
|
||||
activity.launchActivityIntent(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,10 +209,11 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
|
|||
}
|
||||
|
||||
fun updateConversations(newConversations: ArrayList<Conversation>) {
|
||||
val latestConversations = newConversations.clone() as ArrayList<Conversation>
|
||||
val oldHashCode = conversations.hashCode()
|
||||
val newHashCode = newConversations.hashCode()
|
||||
val newHashCode = latestConversations.hashCode()
|
||||
if (newHashCode != oldHashCode) {
|
||||
conversations = newConversations
|
||||
conversations = latestConversations
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
|
@ -232,7 +233,7 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
|
|||
}
|
||||
|
||||
conversation_date.apply {
|
||||
text = conversation.date.formatDateOrTime(context, true)
|
||||
text = conversation.date.formatDateOrTime(context, true, false)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package com.simplemobiletools.smsmessenger.adapters
|
||||
|
||||
import android.util.TypedValue
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.bumptech.glide.Glide
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.extensions.getTextSize
|
||||
import com.simplemobiletools.commons.extensions.highlightTextPart
|
||||
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.activities.SimpleActivity
|
||||
import com.simplemobiletools.smsmessenger.models.SearchResult
|
||||
import kotlinx.android.synthetic.main.item_search_result.view.*
|
||||
import java.util.*
|
||||
|
||||
class SearchResultsAdapter(
|
||||
activity: SimpleActivity, var searchResults: ArrayList<SearchResult>, recyclerView: MyRecyclerView, highlightText: String, itemClick: (Any) -> Unit
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, null, itemClick) {
|
||||
|
||||
private var fontSize = activity.getTextSize()
|
||||
private var textToHighlight = highlightText
|
||||
|
||||
override fun getActionMenuId() = 0
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {}
|
||||
|
||||
override fun actionItemPressed(id: Int) {}
|
||||
|
||||
override fun getSelectableItemCount() = searchResults.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = false
|
||||
|
||||
override fun getItemSelectionKey(position: Int) = searchResults.getOrNull(position)?.hashCode()
|
||||
|
||||
override fun getItemKeyPosition(key: Int) = searchResults.indexOfFirst { it.hashCode() == key }
|
||||
|
||||
override fun onActionModeCreated() {}
|
||||
|
||||
override fun onActionModeDestroyed() {}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_search_result, parent)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val searchResult = searchResults[position]
|
||||
holder.bindView(searchResult, true, false) { itemView, layoutPosition ->
|
||||
setupView(itemView, searchResult)
|
||||
}
|
||||
bindViewHolder(holder)
|
||||
}
|
||||
|
||||
override fun getItemCount() = searchResults.size
|
||||
|
||||
fun updateItems(newItems: ArrayList<SearchResult>, highlightText: String = "") {
|
||||
if (newItems.hashCode() != searchResults.hashCode()) {
|
||||
searchResults = newItems.clone() as ArrayList<SearchResult>
|
||||
textToHighlight = highlightText
|
||||
notifyDataSetChanged()
|
||||
} else if (textToHighlight != highlightText) {
|
||||
textToHighlight = highlightText
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupView(view: View, searchResult: SearchResult) {
|
||||
view.apply {
|
||||
search_result_title.apply {
|
||||
text = searchResult.title.highlightTextPart(textToHighlight, adjustedPrimaryColor)
|
||||
setTextColor(textColor)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f)
|
||||
}
|
||||
|
||||
search_result_snippet.apply {
|
||||
text = searchResult.snippet.highlightTextPart(textToHighlight, adjustedPrimaryColor)
|
||||
setTextColor(textColor)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f)
|
||||
}
|
||||
|
||||
search_result_date.apply {
|
||||
text = searchResult.date
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
|
||||
}
|
||||
|
||||
SimpleContactsHelper(context).loadContactImage(searchResult.photoUri, search_result_image, searchResult.title)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.search_result_image != null) {
|
||||
Glide.with(activity).clear(holder.itemView.search_result_image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.simplemobiletools.smsmessenger.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
|
|
@ -42,8 +43,10 @@ import kotlinx.android.synthetic.main.item_thread_error.view.*
|
|||
import kotlinx.android.synthetic.main.item_thread_sending.view.*
|
||||
import kotlinx.android.synthetic.main.item_thread_success.view.*
|
||||
|
||||
class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem>, recyclerView: MyRecyclerView, fastScroller: FastScroller,
|
||||
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
class ThreadAdapter(
|
||||
activity: SimpleActivity, var messages: ArrayList<ThreadItem>, recyclerView: MyRecyclerView, fastScroller: FastScroller,
|
||||
itemClick: (Any) -> Unit
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
private val roundedCornersRadius = resources.getDimension(R.dimen.normal_margin).toInt()
|
||||
private var fontSize = activity.getTextSize()
|
||||
|
||||
|
|
@ -134,17 +137,17 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
|||
}
|
||||
|
||||
private fun copyToClipboard() {
|
||||
val firstItem = getSelectedItems().first() as? Message ?: return
|
||||
val firstItem = getSelectedItems().firstOrNull() as? Message ?: return
|
||||
activity.copyToClipboard(firstItem.body)
|
||||
}
|
||||
|
||||
private fun shareText() {
|
||||
val firstItem = getSelectedItems().first() as? Message ?: return
|
||||
val firstItem = getSelectedItems().firstOrNull() as? Message ?: return
|
||||
activity.shareTextIntent(firstItem.body)
|
||||
}
|
||||
|
||||
private fun selectText() {
|
||||
val firstItem = getSelectedItems().first() as? Message ?: return
|
||||
val firstItem = getSelectedItems().firstOrNull() as? Message ?: return
|
||||
if (firstItem.body.trim().isNotEmpty()) {
|
||||
SelectTextDialog(activity, firstItem.body)
|
||||
}
|
||||
|
|
@ -198,10 +201,11 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
|||
private fun isThreadDateTime(position: Int) = messages.getOrNull(position) is ThreadDateTime
|
||||
|
||||
fun updateMessages(newMessages: ArrayList<ThreadItem>) {
|
||||
val latestMessages = newMessages.clone() as ArrayList<ThreadItem>
|
||||
val oldHashCode = messages.hashCode()
|
||||
val newHashCode = newMessages.hashCode()
|
||||
val newHashCode = latestMessages.hashCode()
|
||||
if (newHashCode != oldHashCode) {
|
||||
messages = newMessages
|
||||
messages = latestMessages
|
||||
notifyDataSetChanged()
|
||||
recyclerView.scrollToPosition(messages.size - 1)
|
||||
}
|
||||
|
|
@ -224,7 +228,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
|||
} else {
|
||||
thread_message_sender_photo?.beGone()
|
||||
val background = context.getAdjustedPrimaryColor()
|
||||
thread_message_body.background.applyColorFilter(background.adjustAlpha(0.8f))
|
||||
thread_message_body.background.applyColorFilter(background)
|
||||
|
||||
val contrastColor = background.getContrastColor()
|
||||
thread_message_body.setTextColor(contrastColor)
|
||||
|
|
@ -287,7 +291,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
|||
val background = context.getAdjustedPrimaryColor()
|
||||
val attachmentView = layoutInflater.inflate(R.layout.item_sent_unknown_attachment, null).apply {
|
||||
thread_sent_attachment_label.apply {
|
||||
this.background.applyColorFilter(background.adjustAlpha(0.8f))
|
||||
this.background.applyColorFilter(background)
|
||||
setTextColor(background.getContrastColor())
|
||||
if (attachment.filename.isNotEmpty()) {
|
||||
thread_sent_attachment_label.text = attachment.filename
|
||||
|
|
@ -310,18 +314,20 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
|||
private fun launchViewIntent(uri: Uri, mimetype: String, filename: String) {
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
setDataAndType(uri, mimetype)
|
||||
setDataAndType(uri, mimetype.toLowerCase())
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
|
||||
if (resolveActivity(activity.packageManager) != null) {
|
||||
try {
|
||||
activity.startActivity(this)
|
||||
} else {
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
val newMimetype = filename.getMimeType()
|
||||
if (newMimetype.isNotEmpty() && mimetype != newMimetype) {
|
||||
launchViewIntent(uri, newMimetype, filename)
|
||||
} else {
|
||||
activity.toast(R.string.no_app_found)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -329,7 +335,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
|||
private fun setupDateTime(view: View, dateTime: ThreadDateTime) {
|
||||
view.apply {
|
||||
thread_date_time.apply {
|
||||
text = dateTime.date.formatDateOrTime(context, false)
|
||||
text = dateTime.date.formatDateOrTime(context, false, false)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
|
||||
}
|
||||
thread_date_time.setTextColor(textColor)
|
||||
|
|
|
|||
|
|
@ -488,7 +488,6 @@ fun Context.getNameAndPhotoFromPhoneNumber(number: String): NamePhoto {
|
|||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
|
||||
return NamePhoto(number, null)
|
||||
|
|
@ -507,8 +506,12 @@ fun Context.insertNewSMS(address: String, subject: String, body: String, date: L
|
|||
put(Sms.SUBSCRIPTION_ID, subscriptionId)
|
||||
}
|
||||
|
||||
val newUri = contentResolver.insert(uri, contentValues)
|
||||
return newUri?.lastPathSegment?.toLong() ?: 0L
|
||||
return try {
|
||||
val newUri = contentResolver.insert(uri, contentValues)
|
||||
newUri?.lastPathSegment?.toLong() ?: 0L
|
||||
} catch (e: Exception) {
|
||||
0L
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.deleteConversation(threadId: Long) {
|
||||
|
|
@ -633,7 +636,7 @@ fun Context.getThreadId(addresses: Set<String>): Long {
|
|||
}
|
||||
|
||||
fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) {
|
||||
val privateCursor = getMyContactsCursor()?.loadInBackground()
|
||||
val privateCursor = getMyContactsCursor(false, true)?.loadInBackground()
|
||||
ensureBackgroundThread {
|
||||
val senderName = getNameFromAddress(address, privateCursor)
|
||||
|
||||
|
|
@ -709,37 +712,41 @@ fun Context.showMessageNotification(address: String, body: String, threadId: Lon
|
|||
val builder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL).apply {
|
||||
when (config.notificationSetting) {
|
||||
CONFIGURE_NAME_AND_MESSAGE -> {
|
||||
this.setContentTitle(sender)
|
||||
this.setLargeIcon(largeIcon)
|
||||
this.setContentText(body)
|
||||
setContentTitle(sender)
|
||||
setLargeIcon(largeIcon)
|
||||
setContentText(body)
|
||||
}
|
||||
CONFIGURE_NAME -> {
|
||||
this.setContentTitle(sender)
|
||||
this.setLargeIcon(largeIcon)
|
||||
setContentTitle(sender)
|
||||
setLargeIcon(largeIcon)
|
||||
}
|
||||
}
|
||||
this.color = config.primaryColor
|
||||
this.setSmallIcon(R.drawable.ic_messenger)
|
||||
this.setStyle(NotificationCompat.BigTextStyle().setSummaryText(summaryText).bigText(body))
|
||||
this.setContentIntent(pendingIntent)
|
||||
this.priority = NotificationCompat.PRIORITY_MAX
|
||||
this.setDefaults(Notification.DEFAULT_LIGHTS)
|
||||
this.setCategory(Notification.CATEGORY_MESSAGE)
|
||||
this.setAutoCancel(true)
|
||||
this.setSound(soundUri, AudioManager.STREAM_NOTIFICATION)
|
||||
|
||||
color = getAdjustedPrimaryColor()
|
||||
setSmallIcon(R.drawable.ic_messenger)
|
||||
setStyle(NotificationCompat.BigTextStyle().setSummaryText(summaryText).bigText(body))
|
||||
setContentIntent(pendingIntent)
|
||||
priority = NotificationCompat.PRIORITY_MAX
|
||||
setDefaults(Notification.DEFAULT_LIGHTS)
|
||||
setCategory(Notification.CATEGORY_MESSAGE)
|
||||
setAutoCancel(true)
|
||||
setSound(soundUri, AudioManager.STREAM_NOTIFICATION)
|
||||
}
|
||||
|
||||
if (replyAction != null && config.notificationSetting == CONFIGURE_NAME_AND_MESSAGE) {
|
||||
builder.addAction(replyAction)
|
||||
}
|
||||
|
||||
builder.addAction(R.drawable.ic_check_vector, getString(R.string.mark_as_read), markAsReadPendingIntent)
|
||||
.setChannelId(NOTIFICATION_CHANNEL)
|
||||
|
||||
notificationManager.notify(threadId.hashCode(), builder.build())
|
||||
}
|
||||
|
||||
fun Context.getConfigurationText(type: Int) = getString(when (type) {
|
||||
CONFIGURE_NAME_AND_MESSAGE -> R.string.configure_name_and_message
|
||||
CONFIGURE_NAME -> R.string.configure_name
|
||||
else -> R.string.configure_no_details
|
||||
})
|
||||
fun Context.getConfigurationText(type: Int) = getString(
|
||||
when (type) {
|
||||
CONFIGURE_NAME_AND_MESSAGE -> R.string.sender_and_message
|
||||
CONFIGURE_NAME -> R.string.sender_only
|
||||
else -> R.string.nothing
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const val THREAD_TEXT = "thread_text"
|
|||
const val THREAD_NUMBER = "thread_number"
|
||||
const val THREAD_ATTACHMENT_URI = "thread_attachment_uri"
|
||||
const val THREAD_ATTACHMENT_URIS = "thread_attachment_uris"
|
||||
const val SEARCHED_MESSAGE_ID = "searched_message_id"
|
||||
const val USE_SIM_ID_PREFIX = "use_sim_id_"
|
||||
const val NOTIFICATION_CHANNEL = "simple_sms_messenger"
|
||||
const val SHOW_CHARACTER_COUNTER = "show_character_counter"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ interface ConversationsDao {
|
|||
@Query("SELECT * FROM conversations WHERE read = 0")
|
||||
fun getUnreadConversations(): List<Conversation>
|
||||
|
||||
@Query("SELECT * FROM conversations WHERE title LIKE :text")
|
||||
fun getConversationsWithText(text: String): List<Conversation>
|
||||
|
||||
@Query("UPDATE conversations SET read = 1 WHERE thread_id = :threadId")
|
||||
fun markRead(threadId: Long)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ interface MessagesDao {
|
|||
@Query("SELECT * FROM messages WHERE thread_id = :threadId")
|
||||
fun getThreadMessages(threadId: Long): List<Message>
|
||||
|
||||
@Query("SELECT * FROM messages WHERE body LIKE :text")
|
||||
fun getMessagesWithText(text: String): List<Message>
|
||||
|
||||
@Query("UPDATE messages SET read = 1 WHERE id = :id")
|
||||
fun markRead(id: Long)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
package com.simplemobiletools.smsmessenger.models
|
||||
|
||||
data class SearchResult(val messageId: Long, val title: String, val snippet: String, val date: String, val threadId: Long, var photoUri: String)
|
||||
|
|
@ -3,17 +3,14 @@ package com.simplemobiletools.smsmessenger.receivers
|
|||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.RemoteInput
|
||||
import com.klinker.android.send_message.Settings
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import com.simplemobiletools.commons.extensions.notificationManager
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.conversationsDB
|
||||
import com.simplemobiletools.smsmessenger.extensions.markThreadMessagesRead
|
||||
import com.simplemobiletools.smsmessenger.helpers.NOTIFICATION_CHANNEL
|
||||
import com.simplemobiletools.smsmessenger.helpers.REPLY
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_NUMBER
|
||||
|
|
@ -22,26 +19,28 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
|||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val address = intent.getStringExtra(THREAD_NUMBER)
|
||||
val threadId = intent.getLongExtra(THREAD_ID, 0L)
|
||||
val msg = RemoteInput.getResultsFromIntent(intent).getCharSequence(REPLY).toString()
|
||||
val msg = RemoteInput.getResultsFromIntent(intent).getCharSequence(REPLY)?.toString() ?: return
|
||||
|
||||
val settings = Settings()
|
||||
settings.useSystemSending = true
|
||||
settings.deliveryReports = true
|
||||
|
||||
val transaction = Transaction(context, settings)
|
||||
val message = com.klinker.android.send_message.Message(msg, address)
|
||||
|
||||
try {
|
||||
val smsSentIntent = Intent(context, SmsStatusSentReceiver::class.java)
|
||||
val deliveredIntent = Intent(context, SmsStatusDeliveredReceiver::class.java)
|
||||
|
||||
transaction.setExplicitBroadcastForSentSms(smsSentIntent)
|
||||
transaction.setExplicitBroadcastForDeliveredSms(deliveredIntent)
|
||||
|
||||
transaction.sendNewMessage(message, threadId)
|
||||
} catch (e: Exception) {
|
||||
context.showErrorToast(e)
|
||||
}
|
||||
|
||||
val repliedNotification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
|
||||
.setSmallIcon(R.drawable.ic_messenger)
|
||||
.setContentText(msg)
|
||||
.build()
|
||||
|
||||
context.notificationManager.notify(threadId.hashCode(), repliedNotification)
|
||||
context.notificationManager.cancel(threadId.hashCode())
|
||||
|
||||
ensureBackgroundThread {
|
||||
context.markThreadMessagesRead(threadId)
|
||||
|
|
|
|||
|
|
@ -40,17 +40,21 @@ class SmsReceiver : BroadcastReceiver() {
|
|||
val newMessageId = context.insertNewSMS(address, subject, body, date, read, threadId, type, subscriptionId)
|
||||
|
||||
val conversation = context.getConversations(threadId).firstOrNull() ?: return@ensureBackgroundThread
|
||||
context.conversationsDB.insertOrUpdate(conversation)
|
||||
context.updateUnreadCountBadge(context.conversationsDB.getUnreadConversations())
|
||||
try {
|
||||
context.conversationsDB.insertOrUpdate(conversation)
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
||||
context.updateUnreadCountBadge(context.conversationsDB.getUnreadConversations())
|
||||
val participant = SimpleContact(0, 0, address, "", arrayListOf(address), ArrayList(), ArrayList())
|
||||
val message = Message(newMessageId, body, type, arrayListOf(participant), (date / 1000).toInt(), false, threadId,
|
||||
false, null, address, "", subscriptionId)
|
||||
val participants = arrayListOf(participant)
|
||||
val messageDate = (date / 1000).toInt()
|
||||
val message = Message(newMessageId, body, type, participants, messageDate, false, threadId, false, null, address, "", subscriptionId)
|
||||
context.messagesDB.insertOrUpdate(message)
|
||||
refreshMessages()
|
||||
}
|
||||
|
||||
context.showReceivedMessageNotification(address, body, threadId, null)
|
||||
refreshMessages()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
package com.simplemobiletools.smsmessenger.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Telephony
|
||||
import com.klinker.android.send_message.DeliveredReceiver
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.smsmessenger.extensions.messagesDB
|
||||
import com.simplemobiletools.smsmessenger.extensions.updateMessageType
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
|
||||
class SmsStatusDeliveredReceiver : BroadcastReceiver() {
|
||||
class SmsStatusDeliveredReceiver : DeliveredReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
override fun onMessageStatusUpdated(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
if (intent.extras?.containsKey("message_uri") == true) {
|
||||
val uri = Uri.parse(intent.getStringExtra("message_uri"))
|
||||
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import android.app.Notification
|
|||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.AudioAttributes
|
||||
|
|
@ -16,6 +15,8 @@ import android.os.Handler
|
|||
import android.os.Looper
|
||||
import android.provider.Telephony
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.klinker.android.send_message.SentReceiver
|
||||
import com.simplemobiletools.commons.extensions.getAdjustedPrimaryColor
|
||||
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
||||
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
|
|
@ -27,9 +28,9 @@ import com.simplemobiletools.smsmessenger.helpers.NOTIFICATION_CHANNEL
|
|||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
|
||||
class SmsStatusSentReceiver : BroadcastReceiver() {
|
||||
class SmsStatusSentReceiver : SentReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
override fun onMessageStatusUpdated(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
if (intent.extras?.containsKey("message_uri") == true) {
|
||||
val uri = Uri.parse(intent.getStringExtra("message_uri"))
|
||||
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
|
||||
|
|
@ -40,6 +41,7 @@ class SmsStatusSentReceiver : BroadcastReceiver() {
|
|||
} else {
|
||||
Telephony.Sms.MESSAGE_TYPE_OUTBOX
|
||||
}
|
||||
|
||||
context.updateMessageType(messageId, type)
|
||||
context.messagesDB.updateType(messageId, type)
|
||||
refreshMessages()
|
||||
|
|
@ -49,7 +51,7 @@ class SmsStatusSentReceiver : BroadcastReceiver() {
|
|||
|
||||
private fun showSendingFailedNotification(context: Context, messageId: Long) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
val privateCursor = context.getMyContactsCursor()?.loadInBackground()
|
||||
val privateCursor = context.getMyContactsCursor(false, true)?.loadInBackground()
|
||||
ensureBackgroundThread {
|
||||
val address = context.getMessageRecipientAddress(messageId)
|
||||
val threadId = context.getThreadId(address)
|
||||
|
|
@ -92,7 +94,7 @@ class SmsStatusSentReceiver : BroadcastReceiver() {
|
|||
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
|
||||
.setContentTitle(context.getString(R.string.message_not_sent_short))
|
||||
.setContentText(summaryText)
|
||||
.setColor(context.config.primaryColor)
|
||||
.setColor(context.getAdjustedPrimaryColor())
|
||||
.setSmallIcon(R.drawable.ic_messenger)
|
||||
.setLargeIcon(largeIcon)
|
||||
.setStyle(NotificationCompat.BigTextStyle().bigText(summaryText))
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import android.net.Uri
|
|||
import com.klinker.android.send_message.Settings
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import com.simplemobiletools.smsmessenger.extensions.getThreadId
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusDeliveredReceiver
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusSentReceiver
|
||||
|
||||
class HeadlessSmsSendService : Service() {
|
||||
override fun onBind(intent: Intent?) = null
|
||||
|
|
@ -20,8 +22,17 @@ class HeadlessSmsSendService : Service() {
|
|||
val text = intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||
val settings = Settings()
|
||||
settings.useSystemSending = true
|
||||
settings.deliveryReports = true
|
||||
|
||||
val transaction = Transaction(this, settings)
|
||||
val message = com.klinker.android.send_message.Message(text, number)
|
||||
|
||||
val smsSentIntent = Intent(this, SmsStatusSentReceiver::class.java)
|
||||
val deliveredIntent = Intent(this, SmsStatusDeliveredReceiver::class.java)
|
||||
|
||||
transaction.setExplicitBroadcastForSentSms(smsSentIntent)
|
||||
transaction.setExplicitBroadcastForDeliveredSms(deliveredIntent)
|
||||
|
||||
transaction.sendNewMessage(message, getThreadId(number))
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue