Merge branch 'master' into fix_108

This commit is contained in:
Tibor Kaputa 2021-08-18 12:40:27 +02:00 committed by GitHub
commit 88213f1c39
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
79 changed files with 1317 additions and 238 deletions

View file

@ -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))
}

View file

@ -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("")
}

View file

@ -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)
}
}
}
}

View file

@ -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

View file

@ -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] ?: "?"