Setup full screen app lock
- Updated commons
This commit is contained in:
parent
0df10f18f0
commit
3f17c2d94c
10 changed files with 553 additions and 227 deletions
|
|
@ -1,11 +1,7 @@
|
||||||
package org.fossify.messages
|
package org.fossify.messages
|
||||||
|
|
||||||
import android.app.Application
|
import org.fossify.commons.FossifyApp
|
||||||
import org.fossify.commons.extensions.checkUseEnglish
|
|
||||||
|
|
||||||
class App : Application() {
|
class App : FossifyApp() {
|
||||||
override fun onCreate() {
|
override val isAppLockFeatureAvailable = true
|
||||||
super.onCreate()
|
|
||||||
checkUseEnglish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import android.os.Bundle
|
||||||
import org.fossify.commons.dialogs.ConfirmationDialog
|
import org.fossify.commons.dialogs.ConfirmationDialog
|
||||||
import org.fossify.commons.extensions.*
|
import org.fossify.commons.extensions.*
|
||||||
import org.fossify.commons.helpers.NavigationIcon
|
import org.fossify.commons.helpers.NavigationIcon
|
||||||
import org.fossify.commons.helpers.WAS_PROTECTION_HANDLED
|
|
||||||
import org.fossify.commons.helpers.ensureBackgroundThread
|
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||||
import org.fossify.messages.R
|
import org.fossify.messages.R
|
||||||
import org.fossify.messages.adapters.ArchivedConversationsAdapter
|
import org.fossify.messages.adapters.ArchivedConversationsAdapter
|
||||||
|
|
@ -165,7 +164,6 @@ class ArchivedConversationsActivity : SimpleActivity() {
|
||||||
val conversation = any as Conversation
|
val conversation = any as Conversation
|
||||||
putExtra(THREAD_ID, conversation.threadId)
|
putExtra(THREAD_ID, conversation.threadId)
|
||||||
putExtra(THREAD_TITLE, conversation.title)
|
putExtra(THREAD_TITLE, conversation.title)
|
||||||
putExtra(WAS_PROTECTION_HANDLED, true)
|
|
||||||
startActivity(this)
|
startActivity(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,46 @@ import android.graphics.drawable.LayerDrawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Telephony
|
import android.provider.Telephony
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import org.fossify.commons.dialogs.PermissionRequiredDialog
|
import org.fossify.commons.dialogs.PermissionRequiredDialog
|
||||||
import org.fossify.commons.extensions.*
|
import org.fossify.commons.extensions.adjustAlpha
|
||||||
import org.fossify.commons.helpers.*
|
import org.fossify.commons.extensions.appLaunched
|
||||||
|
import org.fossify.commons.extensions.appLockManager
|
||||||
|
import org.fossify.commons.extensions.applyColorFilter
|
||||||
|
import org.fossify.commons.extensions.areSystemAnimationsEnabled
|
||||||
|
import org.fossify.commons.extensions.beGone
|
||||||
|
import org.fossify.commons.extensions.beGoneIf
|
||||||
|
import org.fossify.commons.extensions.beVisible
|
||||||
|
import org.fossify.commons.extensions.beVisibleIf
|
||||||
|
import org.fossify.commons.extensions.checkAppSideloading
|
||||||
|
import org.fossify.commons.extensions.checkWhatsNew
|
||||||
|
import org.fossify.commons.extensions.convertToBitmap
|
||||||
|
import org.fossify.commons.extensions.fadeIn
|
||||||
|
import org.fossify.commons.extensions.formatDateOrTime
|
||||||
|
import org.fossify.commons.extensions.getMyContactsCursor
|
||||||
|
import org.fossify.commons.extensions.getProperBackgroundColor
|
||||||
|
import org.fossify.commons.extensions.getProperPrimaryColor
|
||||||
|
import org.fossify.commons.extensions.getProperTextColor
|
||||||
|
import org.fossify.commons.extensions.hideKeyboard
|
||||||
|
import org.fossify.commons.extensions.navigationBarHeight
|
||||||
|
import org.fossify.commons.extensions.openNotificationSettings
|
||||||
|
import org.fossify.commons.extensions.toast
|
||||||
|
import org.fossify.commons.extensions.underlineText
|
||||||
|
import org.fossify.commons.extensions.updateTextColors
|
||||||
|
import org.fossify.commons.extensions.viewBinding
|
||||||
|
import org.fossify.commons.helpers.LICENSE_EVENT_BUS
|
||||||
|
import org.fossify.commons.helpers.LICENSE_INDICATOR_FAST_SCROLL
|
||||||
|
import org.fossify.commons.helpers.LICENSE_SMS_MMS
|
||||||
|
import org.fossify.commons.helpers.LOWER_ALPHA
|
||||||
|
import org.fossify.commons.helpers.MyContactsContentProvider
|
||||||
|
import org.fossify.commons.helpers.PERMISSION_READ_CONTACTS
|
||||||
|
import org.fossify.commons.helpers.PERMISSION_READ_SMS
|
||||||
|
import org.fossify.commons.helpers.PERMISSION_SEND_SMS
|
||||||
|
import org.fossify.commons.helpers.SHORT_ANIMATION_DURATION
|
||||||
|
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||||
|
import org.fossify.commons.helpers.isNougatMR1Plus
|
||||||
|
import org.fossify.commons.helpers.isQPlus
|
||||||
import org.fossify.commons.models.FAQItem
|
import org.fossify.commons.models.FAQItem
|
||||||
import org.fossify.commons.models.Release
|
import org.fossify.commons.models.Release
|
||||||
import org.fossify.messages.BuildConfig
|
import org.fossify.messages.BuildConfig
|
||||||
|
|
@ -22,7 +58,16 @@ import org.fossify.messages.R
|
||||||
import org.fossify.messages.adapters.ConversationsAdapter
|
import org.fossify.messages.adapters.ConversationsAdapter
|
||||||
import org.fossify.messages.adapters.SearchResultsAdapter
|
import org.fossify.messages.adapters.SearchResultsAdapter
|
||||||
import org.fossify.messages.databinding.ActivityMainBinding
|
import org.fossify.messages.databinding.ActivityMainBinding
|
||||||
import org.fossify.messages.extensions.*
|
import org.fossify.messages.extensions.checkAndDeleteOldRecycleBinMessages
|
||||||
|
import org.fossify.messages.extensions.clearAllMessagesIfNeeded
|
||||||
|
import org.fossify.messages.extensions.clearExpiredScheduledMessages
|
||||||
|
import org.fossify.messages.extensions.config
|
||||||
|
import org.fossify.messages.extensions.conversationsDB
|
||||||
|
import org.fossify.messages.extensions.getConversations
|
||||||
|
import org.fossify.messages.extensions.getMessages
|
||||||
|
import org.fossify.messages.extensions.insertOrUpdateConversation
|
||||||
|
import org.fossify.messages.extensions.messagesDB
|
||||||
|
import org.fossify.messages.extensions.updateUnreadCountBadge
|
||||||
import org.fossify.messages.helpers.SEARCHED_MESSAGE_ID
|
import org.fossify.messages.helpers.SEARCHED_MESSAGE_ID
|
||||||
import org.fossify.messages.helpers.THREAD_ID
|
import org.fossify.messages.helpers.THREAD_ID
|
||||||
import org.fossify.messages.helpers.THREAD_TITLE
|
import org.fossify.messages.helpers.THREAD_TITLE
|
||||||
|
|
@ -41,7 +86,6 @@ class MainActivity : SimpleActivity() {
|
||||||
private var storedFontSize = 0
|
private var storedFontSize = 0
|
||||||
private var lastSearchedText = ""
|
private var lastSearchedText = ""
|
||||||
private var bus: EventBus? = null
|
private var bus: EventBus? = null
|
||||||
private var wasProtectionHandled = false
|
|
||||||
|
|
||||||
private val binding by viewBinding(ActivityMainBinding::inflate)
|
private val binding by viewBinding(ActivityMainBinding::inflate)
|
||||||
|
|
||||||
|
|
@ -63,15 +107,8 @@ class MainActivity : SimpleActivity() {
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
checkAndDeleteOldRecycleBinMessages()
|
checkAndDeleteOldRecycleBinMessages()
|
||||||
handleAppPasswordProtection {
|
clearAllMessagesIfNeeded {
|
||||||
wasProtectionHandled = it
|
loadMessages()
|
||||||
if (it) {
|
|
||||||
clearAllMessagesIfNeeded {
|
|
||||||
loadMessages()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,7 +145,8 @@ class MainActivity : SimpleActivity() {
|
||||||
binding.conversationsProgressBar.trackColor = properPrimaryColor.adjustAlpha(LOWER_ALPHA)
|
binding.conversationsProgressBar.trackColor = properPrimaryColor.adjustAlpha(LOWER_ALPHA)
|
||||||
checkShortcut()
|
checkShortcut()
|
||||||
(binding.conversationsFab.layoutParams as? CoordinatorLayout.LayoutParams)?.bottomMargin =
|
(binding.conversationsFab.layoutParams as? CoordinatorLayout.LayoutParams)?.bottomMargin =
|
||||||
navigationBarHeight + resources.getDimension(org.fossify.commons.R.dimen.activity_margin).toInt()
|
navigationBarHeight + resources.getDimension(org.fossify.commons.R.dimen.activity_margin)
|
||||||
|
.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
|
@ -125,33 +163,11 @@ class MainActivity : SimpleActivity() {
|
||||||
if (binding.mainMenu.isSearchOpen) {
|
if (binding.mainMenu.isSearchOpen) {
|
||||||
binding.mainMenu.closeSearch()
|
binding.mainMenu.closeSearch()
|
||||||
} else {
|
} else {
|
||||||
|
appLockManager.lock()
|
||||||
super.onBackPressed()
|
super.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
super.onSaveInstanceState(outState)
|
|
||||||
outState.putBoolean(WAS_PROTECTION_HANDLED, wasProtectionHandled)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
|
||||||
super.onRestoreInstanceState(savedInstanceState)
|
|
||||||
wasProtectionHandled = savedInstanceState.getBoolean(WAS_PROTECTION_HANDLED, false)
|
|
||||||
|
|
||||||
if (!wasProtectionHandled) {
|
|
||||||
handleAppPasswordProtection {
|
|
||||||
wasProtectionHandled = it
|
|
||||||
if (it) {
|
|
||||||
loadMessages()
|
|
||||||
} else {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loadMessages()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupOptionsMenu() {
|
private fun setupOptionsMenu() {
|
||||||
binding.mainMenu.getToolbar().inflateMenu(R.menu.menu_main)
|
binding.mainMenu.getToolbar().inflateMenu(R.menu.menu_main)
|
||||||
binding.mainMenu.toggleHideOnScroll(true)
|
binding.mainMenu.toggleHideOnScroll(true)
|
||||||
|
|
@ -332,7 +348,8 @@ class MainActivity : SimpleActivity() {
|
||||||
conversationsDB.deleteThreadId(threadId)
|
conversationsDB.deleteThreadId(threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
val newConversation = conversations.find { it.phoneNumber == cachedConversation.phoneNumber }
|
val newConversation =
|
||||||
|
conversations.find { it.phoneNumber == cachedConversation.phoneNumber }
|
||||||
if (isTemporaryThread && newConversation != null) {
|
if (isTemporaryThread && newConversation != null) {
|
||||||
// delete the original temporary thread and move any scheduled messages to the new thread
|
// delete the original temporary thread and move any scheduled messages to the new thread
|
||||||
conversationsDB.deleteThreadId(threadId)
|
conversationsDB.deleteThreadId(threadId)
|
||||||
|
|
@ -346,7 +363,9 @@ class MainActivity : SimpleActivity() {
|
||||||
|
|
||||||
cachedConversations.forEach { cachedConv ->
|
cachedConversations.forEach { cachedConv ->
|
||||||
val conv = conversations.find {
|
val conv = conversations.find {
|
||||||
it.threadId == cachedConv.threadId && !Conversation.areContentsTheSame(cachedConv, it)
|
it.threadId == cachedConv.threadId && !Conversation.areContentsTheSame(
|
||||||
|
old = cachedConv, new = it
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (conv != null) {
|
if (conv != null) {
|
||||||
val lastModified = maxOf(cachedConv.date, conv.date)
|
val lastModified = maxOf(cachedConv.date, conv.date)
|
||||||
|
|
@ -362,7 +381,11 @@ class MainActivity : SimpleActivity() {
|
||||||
|
|
||||||
if (config.appRunCount == 1) {
|
if (config.appRunCount == 1) {
|
||||||
conversations.map { it.threadId }.forEach { threadId ->
|
conversations.map { it.threadId }.forEach { threadId ->
|
||||||
val messages = getMessages(threadId, getImageResolutions = false, includeScheduledMessages = false)
|
val messages = getMessages(
|
||||||
|
threadId = threadId,
|
||||||
|
getImageResolutions = false,
|
||||||
|
includeScheduledMessages = false
|
||||||
|
)
|
||||||
messages.chunked(30).forEach { currentMessages ->
|
messages.chunked(30).forEach { currentMessages ->
|
||||||
messagesDB.insertMessages(*currentMessages.toTypedArray())
|
messagesDB.insertMessages(*currentMessages.toTypedArray())
|
||||||
}
|
}
|
||||||
|
|
@ -390,7 +413,10 @@ class MainActivity : SimpleActivity() {
|
||||||
return currAdapter as ConversationsAdapter
|
return currAdapter as ConversationsAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupConversations(conversations: ArrayList<Conversation>, cached: Boolean = false) {
|
private fun setupConversations(
|
||||||
|
conversations: ArrayList<Conversation>,
|
||||||
|
cached: Boolean = false
|
||||||
|
) {
|
||||||
val sortedConversations = conversations.sortedWith(
|
val sortedConversations = conversations.sortedWith(
|
||||||
compareByDescending<Conversation> { config.pinnedConversations.contains(it.threadId.toString()) }
|
compareByDescending<Conversation> { config.pinnedConversations.contains(it.threadId.toString()) }
|
||||||
.thenByDescending { it.date }
|
.thenByDescending { it.date }
|
||||||
|
|
@ -435,10 +461,13 @@ class MainActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fadeOutSearch() {
|
private fun fadeOutSearch() {
|
||||||
binding.searchHolder.animate().alpha(0f).setDuration(SHORT_ANIMATION_DURATION).withEndAction {
|
binding.searchHolder.animate()
|
||||||
binding.searchHolder.beGone()
|
.alpha(0f)
|
||||||
searchTextChanged("", true)
|
.setDuration(SHORT_ANIMATION_DURATION)
|
||||||
}.start()
|
.withEndAction {
|
||||||
|
binding.searchHolder.beGone()
|
||||||
|
searchTextChanged("", true)
|
||||||
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
|
@ -451,7 +480,6 @@ class MainActivity : SimpleActivity() {
|
||||||
val conversation = any as Conversation
|
val conversation = any as Conversation
|
||||||
putExtra(THREAD_ID, conversation.threadId)
|
putExtra(THREAD_ID, conversation.threadId)
|
||||||
putExtra(THREAD_TITLE, conversation.title)
|
putExtra(THREAD_TITLE, conversation.title)
|
||||||
putExtra(WAS_PROTECTION_HANDLED, wasProtectionHandled)
|
|
||||||
startActivity(this)
|
startActivity(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -481,8 +509,13 @@ class MainActivity : SimpleActivity() {
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
private fun getCreateNewContactShortcut(appIconColor: Int): ShortcutInfo {
|
private fun getCreateNewContactShortcut(appIconColor: Int): ShortcutInfo {
|
||||||
val newEvent = getString(R.string.new_conversation)
|
val newEvent = getString(R.string.new_conversation)
|
||||||
val drawable = resources.getDrawable(org.fossify.commons.R.drawable.shortcut_plus)
|
val drawable =
|
||||||
(drawable as LayerDrawable).findDrawableByLayerId(org.fossify.commons.R.id.shortcut_plus_background).applyColorFilter(appIconColor)
|
AppCompatResources.getDrawable(this, org.fossify.commons.R.drawable.shortcut_plus)
|
||||||
|
|
||||||
|
(drawable as LayerDrawable).findDrawableByLayerId(
|
||||||
|
org.fossify.commons.R.id.shortcut_plus_background
|
||||||
|
).applyColorFilter(appIconColor)
|
||||||
|
|
||||||
val bmp = drawable.convertToBitmap()
|
val bmp = drawable.convertToBitmap()
|
||||||
|
|
||||||
val intent = Intent(this, NewConversationActivity::class.java)
|
val intent = Intent(this, NewConversationActivity::class.java)
|
||||||
|
|
@ -517,11 +550,27 @@ class MainActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showSearchResults(messages: List<Message>, conversations: List<Conversation>, searchedText: String) {
|
private fun showSearchResults(
|
||||||
|
messages: List<Message>,
|
||||||
|
conversations: List<Conversation>,
|
||||||
|
searchedText: String
|
||||||
|
) {
|
||||||
val searchResults = ArrayList<SearchResult>()
|
val searchResults = ArrayList<SearchResult>()
|
||||||
conversations.forEach { conversation ->
|
conversations.forEach { conversation ->
|
||||||
val date = conversation.date.formatDateOrTime(this, true, true)
|
val date = (conversation.date * 1000L).formatDateOrTime(
|
||||||
val searchResult = SearchResult(-1, conversation.title, conversation.phoneNumber, date, conversation.threadId, conversation.photoUri)
|
context = this,
|
||||||
|
hideTimeOnOtherDays = true,
|
||||||
|
showCurrentYear = true
|
||||||
|
)
|
||||||
|
|
||||||
|
val searchResult = SearchResult(
|
||||||
|
messageId = -1,
|
||||||
|
title = conversation.title,
|
||||||
|
snippet = conversation.phoneNumber,
|
||||||
|
date = date,
|
||||||
|
threadId = conversation.threadId,
|
||||||
|
photoUri = conversation.photoUri
|
||||||
|
)
|
||||||
searchResults.add(searchResult)
|
searchResults.add(searchResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -532,8 +581,20 @@ class MainActivity : SimpleActivity() {
|
||||||
recipient = TextUtils.join(", ", participantNames)
|
recipient = TextUtils.join(", ", participantNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
val date = message.date.formatDateOrTime(this, true, true)
|
val date = (message.date * 1000L).formatDateOrTime(
|
||||||
val searchResult = SearchResult(message.id, recipient, message.body, date, message.threadId, message.senderPhotoUri)
|
context = this,
|
||||||
|
hideTimeOnOtherDays = true,
|
||||||
|
showCurrentYear = true
|
||||||
|
)
|
||||||
|
|
||||||
|
val searchResult = SearchResult(
|
||||||
|
messageId = message.id,
|
||||||
|
title = recipient,
|
||||||
|
snippet = message.body,
|
||||||
|
date = date,
|
||||||
|
threadId = message.threadId,
|
||||||
|
photoUri = message.senderPhotoUri
|
||||||
|
)
|
||||||
searchResults.add(searchResult)
|
searchResults.add(searchResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -579,17 +640,36 @@ class MainActivity : SimpleActivity() {
|
||||||
val licenses = LICENSE_EVENT_BUS or LICENSE_SMS_MMS or LICENSE_INDICATOR_FAST_SCROLL
|
val licenses = LICENSE_EVENT_BUS or LICENSE_SMS_MMS or LICENSE_INDICATOR_FAST_SCROLL
|
||||||
|
|
||||||
val faqItems = arrayListOf(
|
val faqItems = arrayListOf(
|
||||||
FAQItem(R.string.faq_2_title, R.string.faq_2_text),
|
FAQItem(title = R.string.faq_2_title, text = R.string.faq_2_text),
|
||||||
FAQItem(R.string.faq_3_title, R.string.faq_3_text),
|
FAQItem(title = R.string.faq_3_title, text = R.string.faq_3_text),
|
||||||
FAQItem(org.fossify.commons.R.string.faq_9_title_commons, org.fossify.commons.R.string.faq_9_text_commons)
|
FAQItem(
|
||||||
|
title = org.fossify.commons.R.string.faq_9_title_commons,
|
||||||
|
text = org.fossify.commons.R.string.faq_9_text_commons
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)) {
|
if (!resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)) {
|
||||||
faqItems.add(FAQItem(org.fossify.commons.R.string.faq_2_title_commons, org.fossify.commons.R.string.faq_2_text_commons))
|
faqItems.add(
|
||||||
faqItems.add(FAQItem(org.fossify.commons.R.string.faq_6_title_commons, org.fossify.commons.R.string.faq_6_text_commons))
|
FAQItem(
|
||||||
|
title = org.fossify.commons.R.string.faq_2_title_commons,
|
||||||
|
text = org.fossify.commons.R.string.faq_2_text_commons
|
||||||
|
)
|
||||||
|
)
|
||||||
|
faqItems.add(
|
||||||
|
FAQItem(
|
||||||
|
title = org.fossify.commons.R.string.faq_6_title_commons,
|
||||||
|
text = org.fossify.commons.R.string.faq_6_text_commons
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)
|
startAboutActivity(
|
||||||
|
appNameId = R.string.app_name,
|
||||||
|
licenseMask = licenses,
|
||||||
|
versionName = BuildConfig.VERSION_NAME,
|
||||||
|
faqItems = faqItems,
|
||||||
|
showFAQBeforeMail = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import org.fossify.commons.activities.BaseSimpleActivity
|
|
||||||
import org.fossify.commons.dialogs.ExportBlockedNumbersDialog
|
import org.fossify.commons.dialogs.ExportBlockedNumbersDialog
|
||||||
import org.fossify.commons.dialogs.FilePickerDialog
|
import org.fossify.commons.dialogs.FilePickerDialog
|
||||||
import org.fossify.commons.extensions.beVisibleIf
|
import org.fossify.commons.extensions.beVisibleIf
|
||||||
|
|
@ -19,8 +18,6 @@ import org.fossify.commons.extensions.toast
|
||||||
import org.fossify.commons.extensions.underlineText
|
import org.fossify.commons.extensions.underlineText
|
||||||
import org.fossify.commons.extensions.updateTextColors
|
import org.fossify.commons.extensions.updateTextColors
|
||||||
import org.fossify.commons.extensions.viewBinding
|
import org.fossify.commons.extensions.viewBinding
|
||||||
import org.fossify.commons.helpers.APP_ICON_IDS
|
|
||||||
import org.fossify.commons.helpers.APP_LAUNCHER_NAME
|
|
||||||
import org.fossify.commons.helpers.ExportResult
|
import org.fossify.commons.helpers.ExportResult
|
||||||
import org.fossify.commons.helpers.NavigationIcon
|
import org.fossify.commons.helpers.NavigationIcon
|
||||||
import org.fossify.commons.helpers.PERMISSION_READ_STORAGE
|
import org.fossify.commons.helpers.PERMISSION_READ_STORAGE
|
||||||
|
|
@ -40,11 +37,7 @@ import org.fossify.messages.helpers.BlockedKeywordsImporter
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
|
||||||
class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewListener {
|
class ManageBlockedKeywordsActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
|
|
||||||
override fun getAppIconIDs() = intent.getIntegerArrayListExtra(APP_ICON_IDS) ?: ArrayList()
|
|
||||||
|
|
||||||
override fun getAppLauncherName() = intent.getStringExtra(APP_LAUNCHER_NAME) ?: ""
|
|
||||||
|
|
||||||
private val binding by viewBinding(ActivityManageBlockedKeywordsBinding::inflate)
|
private val binding by viewBinding(ActivityManageBlockedKeywordsBinding::inflate)
|
||||||
|
|
||||||
|
|
@ -131,10 +124,11 @@ class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewL
|
||||||
if (isQPlus()) {
|
if (isQPlus()) {
|
||||||
Intent(Intent.ACTION_GET_CONTENT).apply {
|
Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||||
addCategory(Intent.CATEGORY_OPENABLE)
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
type = "text/plain"
|
val mimeType = "text/plain"
|
||||||
|
type = mimeType
|
||||||
|
|
||||||
try {
|
try {
|
||||||
importActivityResultLauncher.launch(type)
|
importActivityResultLauncher.launch(mimeType)
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
toast(org.fossify.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
|
toast(org.fossify.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,13 @@ import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import org.fossify.commons.dialogs.ConfirmationDialog
|
import org.fossify.commons.dialogs.ConfirmationDialog
|
||||||
import org.fossify.commons.extensions.*
|
import org.fossify.commons.extensions.areSystemAnimationsEnabled
|
||||||
|
import org.fossify.commons.extensions.beGoneIf
|
||||||
|
import org.fossify.commons.extensions.beVisibleIf
|
||||||
|
import org.fossify.commons.extensions.getProperBackgroundColor
|
||||||
|
import org.fossify.commons.extensions.hideKeyboard
|
||||||
|
import org.fossify.commons.extensions.viewBinding
|
||||||
import org.fossify.commons.helpers.NavigationIcon
|
import org.fossify.commons.helpers.NavigationIcon
|
||||||
import org.fossify.commons.helpers.WAS_PROTECTION_HANDLED
|
|
||||||
import org.fossify.commons.helpers.ensureBackgroundThread
|
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||||
import org.fossify.messages.R
|
import org.fossify.messages.R
|
||||||
import org.fossify.messages.adapters.RecycleBinConversationsAdapter
|
import org.fossify.messages.adapters.RecycleBinConversationsAdapter
|
||||||
|
|
@ -40,7 +44,10 @@ class RecycleBinConversationsActivity : SimpleActivity() {
|
||||||
useTransparentNavigation = true,
|
useTransparentNavigation = true,
|
||||||
useTopSearchMenu = false
|
useTopSearchMenu = false
|
||||||
)
|
)
|
||||||
setupMaterialScrollListener(scrollingView = binding.conversationsList, toolbar = binding.recycleBinToolbar)
|
setupMaterialScrollListener(
|
||||||
|
scrollingView = binding.conversationsList,
|
||||||
|
toolbar = binding.recycleBinToolbar
|
||||||
|
)
|
||||||
|
|
||||||
loadRecycleBinConversations()
|
loadRecycleBinConversations()
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +89,8 @@ class RecycleBinConversationsActivity : SimpleActivity() {
|
||||||
private fun loadRecycleBinConversations() {
|
private fun loadRecycleBinConversations() {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val conversations = try {
|
val conversations = try {
|
||||||
conversationsDB.getAllWithMessagesInRecycleBin().toMutableList() as ArrayList<Conversation>
|
conversationsDB.getAllWithMessagesInRecycleBin()
|
||||||
|
.toMutableList() as ArrayList<Conversation>
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
ArrayList()
|
ArrayList()
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +174,6 @@ class RecycleBinConversationsActivity : SimpleActivity() {
|
||||||
val conversation = any as Conversation
|
val conversation = any as Conversation
|
||||||
putExtra(THREAD_ID, conversation.threadId)
|
putExtra(THREAD_ID, conversation.threadId)
|
||||||
putExtra(THREAD_TITLE, conversation.title)
|
putExtra(THREAD_TITLE, conversation.title)
|
||||||
putExtra(WAS_PROTECTION_HANDLED, true)
|
|
||||||
putExtra(IS_RECYCLE_BIN, true)
|
putExtra(IS_RECYCLE_BIN, true)
|
||||||
startActivity(this)
|
startActivity(this)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,6 @@ open class SimpleActivity : BaseSimpleActivity() {
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
||||||
|
|
||||||
|
override fun getRepositoryName() = "Messages"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,14 @@ import android.widget.LinearLayout.LayoutParams
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.core.view.*
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.view.WindowInsetsAnimationCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
|
@ -47,8 +52,52 @@ import org.fossify.commons.dialogs.ConfirmationDialog
|
||||||
import org.fossify.commons.dialogs.FeatureLockedDialog
|
import org.fossify.commons.dialogs.FeatureLockedDialog
|
||||||
import org.fossify.commons.dialogs.PermissionRequiredDialog
|
import org.fossify.commons.dialogs.PermissionRequiredDialog
|
||||||
import org.fossify.commons.dialogs.RadioGroupDialog
|
import org.fossify.commons.dialogs.RadioGroupDialog
|
||||||
import org.fossify.commons.extensions.*
|
import org.fossify.commons.extensions.addBlockedNumber
|
||||||
import org.fossify.commons.helpers.*
|
import org.fossify.commons.extensions.addLockedLabelIfNeeded
|
||||||
|
import org.fossify.commons.extensions.applyColorFilter
|
||||||
|
import org.fossify.commons.extensions.beGone
|
||||||
|
import org.fossify.commons.extensions.beVisible
|
||||||
|
import org.fossify.commons.extensions.beVisibleIf
|
||||||
|
import org.fossify.commons.extensions.darkenColor
|
||||||
|
import org.fossify.commons.extensions.formatDate
|
||||||
|
import org.fossify.commons.extensions.getBottomNavigationBackgroundColor
|
||||||
|
import org.fossify.commons.extensions.getContrastColor
|
||||||
|
import org.fossify.commons.extensions.getFilenameFromUri
|
||||||
|
import org.fossify.commons.extensions.getMyContactsCursor
|
||||||
|
import org.fossify.commons.extensions.getMyFileUri
|
||||||
|
import org.fossify.commons.extensions.getProperBackgroundColor
|
||||||
|
import org.fossify.commons.extensions.getProperPrimaryColor
|
||||||
|
import org.fossify.commons.extensions.getProperTextColor
|
||||||
|
import org.fossify.commons.extensions.getTextSize
|
||||||
|
import org.fossify.commons.extensions.hideKeyboard
|
||||||
|
import org.fossify.commons.extensions.isDynamicTheme
|
||||||
|
import org.fossify.commons.extensions.isOrWasThankYouInstalled
|
||||||
|
import org.fossify.commons.extensions.isVisible
|
||||||
|
import org.fossify.commons.extensions.launchActivityIntent
|
||||||
|
import org.fossify.commons.extensions.normalizeString
|
||||||
|
import org.fossify.commons.extensions.notificationManager
|
||||||
|
import org.fossify.commons.extensions.onTextChangeListener
|
||||||
|
import org.fossify.commons.extensions.openRequestExactAlarmSettings
|
||||||
|
import org.fossify.commons.extensions.realScreenSize
|
||||||
|
import org.fossify.commons.extensions.showErrorToast
|
||||||
|
import org.fossify.commons.extensions.showKeyboard
|
||||||
|
import org.fossify.commons.extensions.toInt
|
||||||
|
import org.fossify.commons.extensions.toast
|
||||||
|
import org.fossify.commons.extensions.updateTextColors
|
||||||
|
import org.fossify.commons.extensions.value
|
||||||
|
import org.fossify.commons.extensions.viewBinding
|
||||||
|
import org.fossify.commons.helpers.ContactsHelper
|
||||||
|
import org.fossify.commons.helpers.ExportResult
|
||||||
|
import org.fossify.commons.helpers.KEY_PHONE
|
||||||
|
import org.fossify.commons.helpers.MyContactsContentProvider
|
||||||
|
import org.fossify.commons.helpers.NavigationIcon
|
||||||
|
import org.fossify.commons.helpers.PERMISSION_READ_PHONE_STATE
|
||||||
|
import org.fossify.commons.helpers.SimpleContactsHelper
|
||||||
|
import org.fossify.commons.helpers.VcfExporter
|
||||||
|
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||||
|
import org.fossify.commons.helpers.isNougatPlus
|
||||||
|
import org.fossify.commons.helpers.isOreoPlus
|
||||||
|
import org.fossify.commons.helpers.isSPlus
|
||||||
import org.fossify.commons.models.PhoneNumber
|
import org.fossify.commons.models.PhoneNumber
|
||||||
import org.fossify.commons.models.RadioItem
|
import org.fossify.commons.models.RadioItem
|
||||||
import org.fossify.commons.models.SimpleContact
|
import org.fossify.commons.models.SimpleContact
|
||||||
|
|
@ -63,11 +112,80 @@ import org.fossify.messages.databinding.ItemSelectedContactBinding
|
||||||
import org.fossify.messages.dialogs.InvalidNumberDialog
|
import org.fossify.messages.dialogs.InvalidNumberDialog
|
||||||
import org.fossify.messages.dialogs.RenameConversationDialog
|
import org.fossify.messages.dialogs.RenameConversationDialog
|
||||||
import org.fossify.messages.dialogs.ScheduleMessageDialog
|
import org.fossify.messages.dialogs.ScheduleMessageDialog
|
||||||
import org.fossify.messages.extensions.*
|
import org.fossify.messages.extensions.clearExpiredScheduledMessages
|
||||||
import org.fossify.messages.helpers.*
|
import org.fossify.messages.extensions.config
|
||||||
import org.fossify.messages.messaging.*
|
import org.fossify.messages.extensions.conversationsDB
|
||||||
import org.fossify.messages.models.*
|
import org.fossify.messages.extensions.createTemporaryThread
|
||||||
import org.fossify.messages.models.ThreadItem.*
|
import org.fossify.messages.extensions.deleteConversation
|
||||||
|
import org.fossify.messages.extensions.deleteMessage
|
||||||
|
import org.fossify.messages.extensions.deleteScheduledMessage
|
||||||
|
import org.fossify.messages.extensions.deleteSmsDraft
|
||||||
|
import org.fossify.messages.extensions.dialNumber
|
||||||
|
import org.fossify.messages.extensions.emptyMessagesRecycleBinForConversation
|
||||||
|
import org.fossify.messages.extensions.getAddresses
|
||||||
|
import org.fossify.messages.extensions.getDefaultKeyboardHeight
|
||||||
|
import org.fossify.messages.extensions.getFileSizeFromUri
|
||||||
|
import org.fossify.messages.extensions.getMessages
|
||||||
|
import org.fossify.messages.extensions.getSmsDraft
|
||||||
|
import org.fossify.messages.extensions.getThreadId
|
||||||
|
import org.fossify.messages.extensions.getThreadParticipants
|
||||||
|
import org.fossify.messages.extensions.getThreadTitle
|
||||||
|
import org.fossify.messages.extensions.indexOfFirstOrNull
|
||||||
|
import org.fossify.messages.extensions.isGifMimeType
|
||||||
|
import org.fossify.messages.extensions.isImageMimeType
|
||||||
|
import org.fossify.messages.extensions.markMessageRead
|
||||||
|
import org.fossify.messages.extensions.markThreadMessagesUnread
|
||||||
|
import org.fossify.messages.extensions.messagesDB
|
||||||
|
import org.fossify.messages.extensions.moveMessageToRecycleBin
|
||||||
|
import org.fossify.messages.extensions.removeDiacriticsIfNeeded
|
||||||
|
import org.fossify.messages.extensions.renameConversation
|
||||||
|
import org.fossify.messages.extensions.restoreAllMessagesFromRecycleBinForConversation
|
||||||
|
import org.fossify.messages.extensions.restoreMessageFromRecycleBin
|
||||||
|
import org.fossify.messages.extensions.saveSmsDraft
|
||||||
|
import org.fossify.messages.extensions.showWithAnimation
|
||||||
|
import org.fossify.messages.extensions.subscriptionManagerCompat
|
||||||
|
import org.fossify.messages.extensions.toArrayList
|
||||||
|
import org.fossify.messages.extensions.updateConversationArchivedStatus
|
||||||
|
import org.fossify.messages.extensions.updateLastConversationMessage
|
||||||
|
import org.fossify.messages.extensions.updateScheduledMessagesThreadId
|
||||||
|
import org.fossify.messages.helpers.CAPTURE_AUDIO_INTENT
|
||||||
|
import org.fossify.messages.helpers.CAPTURE_PHOTO_INTENT
|
||||||
|
import org.fossify.messages.helpers.CAPTURE_VIDEO_INTENT
|
||||||
|
import org.fossify.messages.helpers.FILE_SIZE_NONE
|
||||||
|
import org.fossify.messages.helpers.IS_RECYCLE_BIN
|
||||||
|
import org.fossify.messages.helpers.MESSAGES_LIMIT
|
||||||
|
import org.fossify.messages.helpers.PICK_CONTACT_INTENT
|
||||||
|
import org.fossify.messages.helpers.PICK_DOCUMENT_INTENT
|
||||||
|
import org.fossify.messages.helpers.PICK_PHOTO_INTENT
|
||||||
|
import org.fossify.messages.helpers.PICK_SAVE_FILE_INTENT
|
||||||
|
import org.fossify.messages.helpers.PICK_VIDEO_INTENT
|
||||||
|
import org.fossify.messages.helpers.SEARCHED_MESSAGE_ID
|
||||||
|
import org.fossify.messages.helpers.THREAD_ATTACHMENT_URI
|
||||||
|
import org.fossify.messages.helpers.THREAD_ATTACHMENT_URIS
|
||||||
|
import org.fossify.messages.helpers.THREAD_ID
|
||||||
|
import org.fossify.messages.helpers.THREAD_NUMBER
|
||||||
|
import org.fossify.messages.helpers.THREAD_TEXT
|
||||||
|
import org.fossify.messages.helpers.THREAD_TITLE
|
||||||
|
import org.fossify.messages.helpers.generateRandomId
|
||||||
|
import org.fossify.messages.helpers.refreshMessages
|
||||||
|
import org.fossify.messages.messaging.cancelScheduleSendPendingIntent
|
||||||
|
import org.fossify.messages.messaging.isLongMmsMessage
|
||||||
|
import org.fossify.messages.messaging.isShortCodeWithLetters
|
||||||
|
import org.fossify.messages.messaging.scheduleMessage
|
||||||
|
import org.fossify.messages.messaging.sendMessageCompat
|
||||||
|
import org.fossify.messages.models.Attachment
|
||||||
|
import org.fossify.messages.models.AttachmentSelection
|
||||||
|
import org.fossify.messages.models.Conversation
|
||||||
|
import org.fossify.messages.models.Events
|
||||||
|
import org.fossify.messages.models.Message
|
||||||
|
import org.fossify.messages.models.MessageAttachment
|
||||||
|
import org.fossify.messages.models.SIMCard
|
||||||
|
import org.fossify.messages.models.ThreadItem
|
||||||
|
import org.fossify.messages.models.ThreadItem.ThreadDateTime
|
||||||
|
import org.fossify.messages.models.ThreadItem.ThreadError
|
||||||
|
import org.fossify.messages.models.ThreadItem.ThreadLoading
|
||||||
|
import org.fossify.messages.models.ThreadItem.ThreadSending
|
||||||
|
import org.fossify.messages.models.ThreadItem.ThreadSent
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
@ -75,6 +193,7 @@ import org.joda.time.DateTime
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
import kotlin.collections.set
|
||||||
|
|
||||||
class ThreadActivity : SimpleActivity() {
|
class ThreadActivity : SimpleActivity() {
|
||||||
private val MIN_DATE_TIME_DIFF_SECS = 300
|
private val MIN_DATE_TIME_DIFF_SECS = 300
|
||||||
|
|
@ -101,7 +220,6 @@ class ThreadActivity : SimpleActivity() {
|
||||||
private var loadingOlderMessages = false
|
private var loadingOlderMessages = false
|
||||||
private var allMessagesFetched = false
|
private var allMessagesFetched = false
|
||||||
private var oldestMessageDate = -1
|
private var oldestMessageDate = -1
|
||||||
private var wasProtectionHandled = false
|
|
||||||
private var isRecycleBin = false
|
private var isRecycleBin = false
|
||||||
|
|
||||||
private var isScheduledMessage: Boolean = false
|
private var isScheduledMessage: Boolean = false
|
||||||
|
|
@ -113,7 +231,7 @@ class ThreadActivity : SimpleActivity() {
|
||||||
|
|
||||||
private val binding by viewBinding(ActivityThreadBinding::inflate)
|
private val binding by viewBinding(ActivityThreadBinding::inflate)
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
finish()
|
finish()
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
|
@ -126,7 +244,12 @@ class ThreadActivity : SimpleActivity() {
|
||||||
setupOptionsMenu()
|
setupOptionsMenu()
|
||||||
refreshMenuItems()
|
refreshMenuItems()
|
||||||
|
|
||||||
updateMaterialActivityViews(binding.threadCoordinator, null, useTransparentNavigation = false, useTopSearchMenu = false)
|
updateMaterialActivityViews(
|
||||||
|
mainCoordinatorLayout = binding.threadCoordinator,
|
||||||
|
nestedView = null,
|
||||||
|
useTransparentNavigation = false,
|
||||||
|
useTopSearchMenu = false
|
||||||
|
)
|
||||||
setupMaterialScrollListener(null, binding.threadToolbar)
|
setupMaterialScrollListener(null, binding.threadToolbar)
|
||||||
|
|
||||||
val extras = intent.extras
|
val extras = intent.extras
|
||||||
|
|
@ -141,28 +264,11 @@ class ThreadActivity : SimpleActivity() {
|
||||||
binding.threadToolbar.title = it
|
binding.threadToolbar.title = it
|
||||||
}
|
}
|
||||||
isRecycleBin = intent.getBooleanExtra(IS_RECYCLE_BIN, false)
|
isRecycleBin = intent.getBooleanExtra(IS_RECYCLE_BIN, false)
|
||||||
wasProtectionHandled = intent.getBooleanExtra(WAS_PROTECTION_HANDLED, false)
|
|
||||||
|
|
||||||
bus = EventBus.getDefault()
|
bus = EventBus.getDefault()
|
||||||
bus!!.register(this)
|
bus!!.register(this)
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
loadConversation()
|
||||||
if (!wasProtectionHandled) {
|
|
||||||
handleAppPasswordProtection {
|
|
||||||
wasProtectionHandled = it
|
|
||||||
if (it) {
|
|
||||||
clearAllMessagesIfNeeded {
|
|
||||||
loadConversation()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loadConversation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setupAttachmentPickerView()
|
setupAttachmentPickerView()
|
||||||
setupKeyboardListener()
|
setupKeyboardListener()
|
||||||
hideAttachmentPicker()
|
hideAttachmentPicker()
|
||||||
|
|
@ -171,7 +277,11 @@ class ThreadActivity : SimpleActivity() {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
setupToolbar(binding.threadToolbar, NavigationIcon.Arrow, statusBarColor = getProperBackgroundColor())
|
setupToolbar(
|
||||||
|
toolbar = binding.threadToolbar,
|
||||||
|
toolbarNavigationIcon = NavigationIcon.Arrow,
|
||||||
|
statusBarColor = getProperBackgroundColor()
|
||||||
|
)
|
||||||
|
|
||||||
val smsDraft = getSmsDraft(threadId)
|
val smsDraft = getSmsDraft(threadId)
|
||||||
if (smsDraft != null) {
|
if (smsDraft != null) {
|
||||||
|
|
@ -224,49 +334,32 @@ class ThreadActivity : SimpleActivity() {
|
||||||
bus?.unregister(this)
|
bus?.unregister(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
super.onSaveInstanceState(outState)
|
|
||||||
outState.putBoolean(WAS_PROTECTION_HANDLED, wasProtectionHandled)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
|
||||||
super.onRestoreInstanceState(savedInstanceState)
|
|
||||||
wasProtectionHandled = savedInstanceState.getBoolean(WAS_PROTECTION_HANDLED, false)
|
|
||||||
|
|
||||||
if (!wasProtectionHandled) {
|
|
||||||
handleAppPasswordProtection {
|
|
||||||
wasProtectionHandled = it
|
|
||||||
if (it) {
|
|
||||||
loadConversation()
|
|
||||||
} else {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loadConversation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun refreshMenuItems() {
|
private fun refreshMenuItems() {
|
||||||
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
|
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
|
||||||
val archiveAvailable = config.isArchiveAvailable
|
val archiveAvailable = config.isArchiveAvailable
|
||||||
binding.threadToolbar.menu.apply {
|
binding.threadToolbar.menu.apply {
|
||||||
findItem(R.id.delete).isVisible = threadItems.isNotEmpty()
|
findItem(R.id.delete).isVisible = threadItems.isNotEmpty()
|
||||||
findItem(R.id.restore).isVisible = threadItems.isNotEmpty() && isRecycleBin
|
findItem(R.id.restore).isVisible = threadItems.isNotEmpty() && isRecycleBin
|
||||||
findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin && archiveAvailable
|
findItem(R.id.archive).isVisible =
|
||||||
findItem(R.id.unarchive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == true && !isRecycleBin && archiveAvailable
|
threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin && archiveAvailable
|
||||||
findItem(R.id.rename_conversation).isVisible = participants.size > 1 && conversation != null && !isRecycleBin
|
findItem(R.id.unarchive).isVisible =
|
||||||
|
threadItems.isNotEmpty() && conversation?.isArchived == true && !isRecycleBin && archiveAvailable
|
||||||
|
findItem(R.id.rename_conversation).isVisible =
|
||||||
|
participants.size > 1 && conversation != null && !isRecycleBin
|
||||||
findItem(R.id.conversation_details).isVisible = conversation != null && !isRecycleBin
|
findItem(R.id.conversation_details).isVisible = conversation != null && !isRecycleBin
|
||||||
findItem(R.id.block_number).title = addLockedLabelIfNeeded(org.fossify.commons.R.string.block_number)
|
findItem(R.id.block_number).title =
|
||||||
|
addLockedLabelIfNeeded(org.fossify.commons.R.string.block_number)
|
||||||
findItem(R.id.block_number).isVisible = isNougatPlus() && !isRecycleBin
|
findItem(R.id.block_number).isVisible = isNougatPlus() && !isRecycleBin
|
||||||
findItem(R.id.dial_number).isVisible = participants.size == 1 && !isSpecialNumber() && !isRecycleBin
|
findItem(R.id.dial_number).isVisible =
|
||||||
|
participants.size == 1 && !isSpecialNumber() && !isRecycleBin
|
||||||
findItem(R.id.manage_people).isVisible = !isSpecialNumber() && !isRecycleBin
|
findItem(R.id.manage_people).isVisible = !isSpecialNumber() && !isRecycleBin
|
||||||
findItem(R.id.mark_as_unread).isVisible = threadItems.isNotEmpty() && !isRecycleBin
|
findItem(R.id.mark_as_unread).isVisible = threadItems.isNotEmpty() && !isRecycleBin
|
||||||
|
|
||||||
// allow saving number in cases when we dont have it stored yet and it is a casual readable number
|
// allow saving number in cases when we don't have it stored yet and it is a casual readable number
|
||||||
findItem(R.id.add_number_to_contact).isVisible = participants.size == 1 && participants.first().name == firstPhoneNumber && firstPhoneNumber.any {
|
findItem(R.id.add_number_to_contact).isVisible =
|
||||||
it.isDigit()
|
participants.size == 1 && participants.first().name == firstPhoneNumber && firstPhoneNumber.any {
|
||||||
} && !isRecycleBin
|
it.isDigit()
|
||||||
|
} && !isRecycleBin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,7 +397,12 @@ class ThreadActivity : SimpleActivity() {
|
||||||
addAttachment(capturedImageUri!!)
|
addAttachment(capturedImageUri!!)
|
||||||
} else if (data != null) {
|
} else if (data != null) {
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
CAPTURE_VIDEO_INTENT, PICK_DOCUMENT_INTENT, CAPTURE_AUDIO_INTENT, PICK_PHOTO_INTENT, PICK_VIDEO_INTENT -> addAttachment(data)
|
CAPTURE_VIDEO_INTENT,
|
||||||
|
PICK_DOCUMENT_INTENT,
|
||||||
|
CAPTURE_AUDIO_INTENT,
|
||||||
|
PICK_PHOTO_INTENT,
|
||||||
|
PICK_VIDEO_INTENT -> addAttachment(data)
|
||||||
|
|
||||||
PICK_CONTACT_INTENT -> addContactAttachment(data)
|
PICK_CONTACT_INTENT -> addContactAttachment(data)
|
||||||
PICK_SAVE_FILE_INTENT -> saveAttachment(resultData)
|
PICK_SAVE_FILE_INTENT -> saveAttachment(resultData)
|
||||||
}
|
}
|
||||||
|
|
@ -360,8 +458,10 @@ class ThreadActivity : SimpleActivity() {
|
||||||
if (!isRecycleBin) {
|
if (!isRecycleBin) {
|
||||||
messages = getMessages(threadId, true)
|
messages = getMessages(threadId, true)
|
||||||
if (config.useRecycleBin) {
|
if (config.useRecycleBin) {
|
||||||
val recycledMessages = messagesDB.getThreadMessagesFromRecycleBin(threadId).map { it.id }
|
val recycledMessages =
|
||||||
messages = messages.filter { !recycledMessages.contains(it.id) }.toMutableList() as ArrayList<Message>
|
messagesDB.getThreadMessagesFromRecycleBin(threadId).map { it.id }
|
||||||
|
messages = messages.filter { !recycledMessages.contains(it.id) }
|
||||||
|
.toMutableList() as ArrayList<Message>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,11 +483,13 @@ class ThreadActivity : SimpleActivity() {
|
||||||
if (privateContacts.isNotEmpty()) {
|
if (privateContacts.isNotEmpty()) {
|
||||||
val senderNumbersToReplace = HashMap<String, String>()
|
val senderNumbersToReplace = HashMap<String, String>()
|
||||||
participants.filter { it.doesHavePhoneNumber(it.name) }.forEach { participant ->
|
participants.filter { it.doesHavePhoneNumber(it.name) }.forEach { participant ->
|
||||||
privateContacts.firstOrNull { it.doesHavePhoneNumber(participant.phoneNumbers.first().normalizedNumber) }?.apply {
|
privateContacts.firstOrNull { it.doesHavePhoneNumber(participant.phoneNumbers.first().normalizedNumber) }
|
||||||
senderNumbersToReplace[participant.phoneNumbers.first().normalizedNumber] = name
|
?.apply {
|
||||||
participant.name = name
|
senderNumbersToReplace[participant.phoneNumbers.first().normalizedNumber] =
|
||||||
participant.photoUri = photoUri
|
name
|
||||||
}
|
participant.name = name
|
||||||
|
participant.photoUri = photoUri
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
messages.forEach { message ->
|
messages.forEach { message ->
|
||||||
|
|
@ -407,7 +509,15 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val phoneNumber = PhoneNumber(number, 0, "", number)
|
val phoneNumber = PhoneNumber(number, 0, "", number)
|
||||||
val contact = SimpleContact(0, 0, name, "", arrayListOf(phoneNumber), ArrayList(), ArrayList())
|
val contact = SimpleContact(
|
||||||
|
rawId = 0,
|
||||||
|
contactId = 0,
|
||||||
|
name = name,
|
||||||
|
photoUri = "",
|
||||||
|
phoneNumbers = arrayListOf(phoneNumber),
|
||||||
|
birthdays = ArrayList(),
|
||||||
|
anniversaries = ArrayList()
|
||||||
|
)
|
||||||
participants.add(contact)
|
participants.add(contact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,17 +544,24 @@ class ThreadActivity : SimpleActivity() {
|
||||||
recyclerView = binding.threadMessagesList,
|
recyclerView = binding.threadMessagesList,
|
||||||
itemClick = { handleItemClick(it) },
|
itemClick = { handleItemClick(it) },
|
||||||
isRecycleBin = isRecycleBin,
|
isRecycleBin = isRecycleBin,
|
||||||
deleteMessages = { messages, toRecycleBin, fromRecycleBin -> deleteMessages(messages, toRecycleBin, fromRecycleBin) }
|
deleteMessages = { messages, toRecycleBin, fromRecycleBin ->
|
||||||
|
deleteMessages(
|
||||||
|
messages,
|
||||||
|
toRecycleBin,
|
||||||
|
fromRecycleBin
|
||||||
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.threadMessagesList.adapter = currAdapter
|
binding.threadMessagesList.adapter = currAdapter
|
||||||
binding.threadMessagesList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
|
binding.threadMessagesList.endlessScrollListener =
|
||||||
override fun updateBottom() {}
|
object : MyRecyclerView.EndlessScrollListener {
|
||||||
|
override fun updateBottom() {}
|
||||||
|
|
||||||
override fun updateTop() {
|
override fun updateTop() {
|
||||||
fetchNextMessages()
|
fetchNextMessages()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return currAdapter as ThreadAdapter
|
return currAdapter as ThreadAdapter
|
||||||
}
|
}
|
||||||
|
|
@ -458,7 +575,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
val layoutManager = binding.threadMessagesList.layoutManager as LinearLayoutManager
|
val layoutManager = binding.threadMessagesList.layoutManager as LinearLayoutManager
|
||||||
val lastPosition = itemCount - 1
|
val lastPosition = itemCount - 1
|
||||||
val lastVisiblePosition = layoutManager.findLastVisibleItemPosition()
|
val lastVisiblePosition = layoutManager.findLastVisibleItemPosition()
|
||||||
val shouldScrollToBottom = currentList.lastOrNull() != threadItems.lastOrNull() && lastPosition - lastVisiblePosition == 1
|
val shouldScrollToBottom =
|
||||||
|
currentList.lastOrNull() != threadItems.lastOrNull() && lastPosition - lastVisiblePosition == 1
|
||||||
updateMessages(threadItems, if (shouldScrollToBottom) lastPosition else -1)
|
updateMessages(threadItems, if (shouldScrollToBottom) lastPosition else -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -470,7 +588,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
binding.addContactOrNumber.setAdapter(adapter)
|
binding.addContactOrNumber.setAdapter(adapter)
|
||||||
binding.addContactOrNumber.imeOptions = EditorInfo.IME_ACTION_NEXT
|
binding.addContactOrNumber.imeOptions = EditorInfo.IME_ACTION_NEXT
|
||||||
binding.addContactOrNumber.setOnItemClickListener { _, _, position, _ ->
|
binding.addContactOrNumber.setOnItemClickListener { _, _, position, _ ->
|
||||||
val currContacts = (binding.addContactOrNumber.adapter as AutoCompleteTextViewAdapter).resultList
|
val currContacts =
|
||||||
|
(binding.addContactOrNumber.adapter as AutoCompleteTextViewAdapter).resultList
|
||||||
val selectedContact = currContacts[position]
|
val selectedContact = currContacts[position]
|
||||||
addSelectedContact(selectedContact)
|
addSelectedContact(selectedContact)
|
||||||
}
|
}
|
||||||
|
|
@ -485,7 +604,15 @@ class ThreadActivity : SimpleActivity() {
|
||||||
binding.confirmInsertedNumber.setOnClickListener {
|
binding.confirmInsertedNumber.setOnClickListener {
|
||||||
val number = binding.addContactOrNumber.value
|
val number = binding.addContactOrNumber.value
|
||||||
val phoneNumber = PhoneNumber(number, 0, "", number)
|
val phoneNumber = PhoneNumber(number, 0, "", number)
|
||||||
val contact = SimpleContact(number.hashCode(), number.hashCode(), number, "", arrayListOf(phoneNumber), ArrayList(), ArrayList())
|
val contact = SimpleContact(
|
||||||
|
rawId = number.hashCode(),
|
||||||
|
contactId = number.hashCode(),
|
||||||
|
name = number,
|
||||||
|
photoUri = "",
|
||||||
|
phoneNumbers = arrayListOf(phoneNumber),
|
||||||
|
birthdays = ArrayList(),
|
||||||
|
anniversaries = ArrayList()
|
||||||
|
)
|
||||||
addSelectedContact(contact)
|
addSelectedContact(contact)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -504,7 +631,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
super.onScrolled(recyclerView, dx, dy)
|
super.onScrolled(recyclerView, dx, dy)
|
||||||
val layoutManager = binding.threadMessagesList.layoutManager as LinearLayoutManager
|
val layoutManager = binding.threadMessagesList.layoutManager as LinearLayoutManager
|
||||||
val lastVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition()
|
val lastVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition()
|
||||||
val isCloseToBottom = lastVisibleItemPosition >= getOrCreateThreadAdapter().itemCount - SCROLL_TO_BOTTOM_FAB_LIMIT
|
val isCloseToBottom =
|
||||||
|
lastVisibleItemPosition >= getOrCreateThreadAdapter().itemCount - SCROLL_TO_BOTTOM_FAB_LIMIT
|
||||||
if (isCloseToBottom) {
|
if (isCloseToBottom) {
|
||||||
binding.scrollToBottomFab.hide()
|
binding.scrollToBottomFab.hide()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -524,7 +652,11 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteMessages(messagesToRemove: List<Message>, toRecycleBin: Boolean, fromRecycleBin: Boolean) {
|
private fun deleteMessages(
|
||||||
|
messagesToRemove: List<Message>,
|
||||||
|
toRecycleBin: Boolean,
|
||||||
|
fromRecycleBin: Boolean
|
||||||
|
) {
|
||||||
val deletePosition = threadItems.indexOf(messagesToRemove.first())
|
val deletePosition = threadItems.indexOf(messagesToRemove.first())
|
||||||
messages.removeAll(messagesToRemove.toSet())
|
messages.removeAll(messagesToRemove.toSet())
|
||||||
threadItems = getThreadItems()
|
threadItems = getThreadItems()
|
||||||
|
|
@ -574,7 +706,10 @@ class ThreadActivity : SimpleActivity() {
|
||||||
val newList = currentList.toMutableList().apply {
|
val newList = currentList.toMutableList().apply {
|
||||||
removeAll { it is ThreadLoading }
|
removeAll { it is ThreadLoading }
|
||||||
}
|
}
|
||||||
updateMessages(newMessages = newList as ArrayList<ThreadItem>, scrollPosition = 0)
|
updateMessages(
|
||||||
|
newMessages = newList as ArrayList<ThreadItem>,
|
||||||
|
scrollPosition = 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
@ -615,7 +750,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
val searchedMessageId = intent.getLongExtra(SEARCHED_MESSAGE_ID, -1L)
|
val searchedMessageId = intent.getLongExtra(SEARCHED_MESSAGE_ID, -1L)
|
||||||
intent.removeExtra(SEARCHED_MESSAGE_ID)
|
intent.removeExtra(SEARCHED_MESSAGE_ID)
|
||||||
if (searchedMessageId != -1L) {
|
if (searchedMessageId != -1L) {
|
||||||
val index = threadItems.indexOfFirst { (it as? Message)?.id == searchedMessageId }
|
val index =
|
||||||
|
threadItems.indexOfFirst { (it as? Message)?.id == searchedMessageId }
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
binding.threadMessagesList.smoothScrollToPosition(index)
|
binding.threadMessagesList.smoothScrollToPosition(index)
|
||||||
}
|
}
|
||||||
|
|
@ -677,6 +813,7 @@ class ThreadActivity : SimpleActivity() {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
val messageLength = SmsMessage.calculateLength(messageString, false)
|
val messageLength = SmsMessage.calculateLength(messageString, false)
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
threadCharacterCounter.text = "${messageLength[2]}/${messageLength[0]}"
|
threadCharacterCounter.text = "${messageLength[2]}/${messageLength[0]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -726,11 +863,13 @@ class ThreadActivity : SimpleActivity() {
|
||||||
threadAddAttachment.setOnClickListener {
|
threadAddAttachment.setOnClickListener {
|
||||||
if (attachmentPickerHolder.isVisible()) {
|
if (attachmentPickerHolder.isVisible()) {
|
||||||
isAttachmentPickerVisible = false
|
isAttachmentPickerVisible = false
|
||||||
WindowCompat.getInsetsController(window, threadTypeMessage).show(WindowInsetsCompat.Type.ime())
|
WindowCompat.getInsetsController(window, threadTypeMessage)
|
||||||
|
.show(WindowInsetsCompat.Type.ime())
|
||||||
} else {
|
} else {
|
||||||
isAttachmentPickerVisible = true
|
isAttachmentPickerVisible = true
|
||||||
showOrHideAttachmentPicker()
|
showOrHideAttachmentPicker()
|
||||||
WindowCompat.getInsetsController(window, threadTypeMessage).hide(WindowInsetsCompat.Type.ime())
|
WindowCompat.getInsetsController(window, threadTypeMessage)
|
||||||
|
.hide(WindowInsetsCompat.Type.ime())
|
||||||
}
|
}
|
||||||
window.decorView.requestApplyInsets()
|
window.decorView.requestApplyInsets()
|
||||||
}
|
}
|
||||||
|
|
@ -779,14 +918,22 @@ class ThreadActivity : SimpleActivity() {
|
||||||
if (it.mimetype.startsWith("image/")) {
|
if (it.mimetype.startsWith("image/")) {
|
||||||
val fileOptions = BitmapFactory.Options()
|
val fileOptions = BitmapFactory.Options()
|
||||||
fileOptions.inJustDecodeBounds = true
|
fileOptions.inJustDecodeBounds = true
|
||||||
BitmapFactory.decodeStream(contentResolver.openInputStream(it.getUri()), null, fileOptions)
|
BitmapFactory.decodeStream(
|
||||||
|
contentResolver.openInputStream(it.getUri()),
|
||||||
|
null,
|
||||||
|
fileOptions
|
||||||
|
)
|
||||||
it.width = fileOptions.outWidth
|
it.width = fileOptions.outWidth
|
||||||
it.height = fileOptions.outHeight
|
it.height = fileOptions.outHeight
|
||||||
} else if (it.mimetype.startsWith("video/")) {
|
} else if (it.mimetype.startsWith("video/")) {
|
||||||
val metaRetriever = MediaMetadataRetriever()
|
val metaRetriever = MediaMetadataRetriever()
|
||||||
metaRetriever.setDataSource(this, it.getUri())
|
metaRetriever.setDataSource(this, it.getUri())
|
||||||
it.width = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)!!.toInt()
|
it.width = metaRetriever.extractMetadata(
|
||||||
it.height = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)!!.toInt()
|
MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH
|
||||||
|
)!!.toInt()
|
||||||
|
it.height = metaRetriever.extractMetadata(
|
||||||
|
MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT
|
||||||
|
)!!.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.width < 0) {
|
if (it.width < 0) {
|
||||||
|
|
@ -885,6 +1032,7 @@ class ThreadActivity : SimpleActivity() {
|
||||||
binding.messageHolder.threadSelectSimIcon.setOnClickListener {
|
binding.messageHolder.threadSelectSimIcon.setOnClickListener {
|
||||||
currentSIMCardIndex = (currentSIMCardIndex + 1) % availableSIMCards.size
|
currentSIMCardIndex = (currentSIMCardIndex + 1) % availableSIMCards.size
|
||||||
val currentSIMCard = availableSIMCards[currentSIMCardIndex]
|
val currentSIMCard = availableSIMCards[currentSIMCardIndex]
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
binding.messageHolder.threadSelectSimNumber.text = currentSIMCard.id.toString()
|
binding.messageHolder.threadSelectSimNumber.text = currentSIMCard.id.toString()
|
||||||
val currentSubscriptionId = currentSIMCard.subscriptionId
|
val currentSubscriptionId = currentSIMCard.subscriptionId
|
||||||
numbers.forEach {
|
numbers.forEach {
|
||||||
|
|
@ -894,9 +1042,13 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.messageHolder.threadSelectSimNumber.setTextColor(getProperTextColor().getContrastColor())
|
binding.messageHolder.threadSelectSimNumber.setTextColor(
|
||||||
|
getProperTextColor().getContrastColor()
|
||||||
|
)
|
||||||
try {
|
try {
|
||||||
binding.messageHolder.threadSelectSimNumber.text = (availableSIMCards[currentSIMCardIndex].id).toString()
|
@SuppressLint("SetTextI18n")
|
||||||
|
binding.messageHolder.threadSelectSimNumber.text =
|
||||||
|
(availableSIMCards[currentSIMCardIndex].id).toString()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
showErrorToast(e)
|
showErrorToast(e)
|
||||||
}
|
}
|
||||||
|
|
@ -904,9 +1056,13 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
private fun getProperSimIndex(availableSIMs: MutableList<SubscriptionInfo>, numbers: List<String>): Int {
|
private fun getProperSimIndex(
|
||||||
|
availableSIMs: MutableList<SubscriptionInfo>,
|
||||||
|
numbers: List<String>
|
||||||
|
): Int {
|
||||||
val userPreferredSimId = config.getUseSIMIdAtNumber(numbers.first())
|
val userPreferredSimId = config.getUseSIMIdAtNumber(numbers.first())
|
||||||
val userPreferredSimIdx = availableSIMs.indexOfFirstOrNull { it.subscriptionId == userPreferredSimId }
|
val userPreferredSimIdx =
|
||||||
|
availableSIMs.indexOfFirstOrNull { it.subscriptionId == userPreferredSimId }
|
||||||
|
|
||||||
val lastMessage = messages.lastOrNull()
|
val lastMessage = messages.lastOrNull()
|
||||||
val senderPreferredSimIdx = if (lastMessage?.isReceivedMessage() == true) {
|
val senderPreferredSimIdx = if (lastMessage?.isReceivedMessage() == true) {
|
||||||
|
|
@ -936,7 +1092,10 @@ class ThreadActivity : SimpleActivity() {
|
||||||
private fun blockNumber() {
|
private fun blockNumber() {
|
||||||
val numbers = participants.getAddresses()
|
val numbers = participants.getAddresses()
|
||||||
val numbersString = TextUtils.join(", ", numbers)
|
val numbersString = TextUtils.join(", ", numbers)
|
||||||
val question = String.format(resources.getString(org.fossify.commons.R.string.block_confirmation), numbersString)
|
val question = String.format(
|
||||||
|
resources.getString(org.fossify.commons.R.string.block_confirmation),
|
||||||
|
numbersString
|
||||||
|
)
|
||||||
|
|
||||||
ConfirmationDialog(this, question) {
|
ConfirmationDialog(this, question) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
|
|
@ -1021,8 +1180,13 @@ class ThreadActivity : SimpleActivity() {
|
||||||
val views = ArrayList<View>()
|
val views = ArrayList<View>()
|
||||||
participants.forEach { contact ->
|
participants.forEach { contact ->
|
||||||
ItemSelectedContactBinding.inflate(layoutInflater).apply {
|
ItemSelectedContactBinding.inflate(layoutInflater).apply {
|
||||||
val selectedContactBg = resources.getDrawable(R.drawable.item_selected_contact_background)
|
val selectedContactBg =
|
||||||
(selectedContactBg as LayerDrawable).findDrawableByLayerId(R.id.selected_contact_bg).applyColorFilter(properPrimaryColor)
|
AppCompatResources.getDrawable(
|
||||||
|
this@ThreadActivity,
|
||||||
|
R.drawable.item_selected_contact_background
|
||||||
|
)
|
||||||
|
(selectedContactBg as LayerDrawable).findDrawableByLayerId(R.id.selected_contact_bg)
|
||||||
|
.applyColorFilter(properPrimaryColor)
|
||||||
selectedContactHolder.background = selectedContactBg
|
selectedContactHolder.background = selectedContactBg
|
||||||
|
|
||||||
selectedContactName.text = contact.name
|
selectedContactName.text = contact.name
|
||||||
|
|
@ -1063,7 +1227,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addNumberToContact() {
|
private fun addNumberToContact() {
|
||||||
val phoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.normalizedNumber ?: return
|
val phoneNumber =
|
||||||
|
participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.normalizedNumber ?: return
|
||||||
Intent().apply {
|
Intent().apply {
|
||||||
action = Intent.ACTION_INSERT_OR_EDIT
|
action = Intent.ACTION_INSERT_OR_EDIT
|
||||||
type = "vnd.android.cursor.item/contact"
|
type = "vnd.android.cursor.item/contact"
|
||||||
|
|
@ -1113,7 +1278,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
val message = messages.getOrNull(i) ?: continue
|
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,
|
// 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,
|
||||||
// or if the message is sent from a different SIM
|
// or if the message is sent from a different SIM
|
||||||
val isSentFromDifferentKnownSIM = prevSIMId != -1 && message.subscriptionId != -1 && prevSIMId != message.subscriptionId
|
val isSentFromDifferentKnownSIM =
|
||||||
|
prevSIMId != -1 && message.subscriptionId != -1 && prevSIMId != message.subscriptionId
|
||||||
if (message.date - prevDateTime > MIN_DATE_TIME_DIFF_SECS || isSentFromDifferentKnownSIM) {
|
if (message.date - prevDateTime > MIN_DATE_TIME_DIFF_SECS || isSentFromDifferentKnownSIM) {
|
||||||
val simCardID = subscriptionIdToSimId[message.subscriptionId] ?: "?"
|
val simCardID = subscriptionIdToSimId[message.subscriptionId] ?: "?"
|
||||||
items.add(ThreadDateTime(message.date, simCardID))
|
items.add(ThreadDateTime(message.date, simCardID))
|
||||||
|
|
@ -1136,7 +1302,12 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == cnt - 1 && (message.type == Telephony.Sms.MESSAGE_TYPE_SENT)) {
|
if (i == cnt - 1 && (message.type == Telephony.Sms.MESSAGE_TYPE_SENT)) {
|
||||||
items.add(ThreadSent(message.id, delivered = message.status == Telephony.Sms.STATUS_COMPLETE))
|
items.add(
|
||||||
|
ThreadSent(
|
||||||
|
messageId = message.id,
|
||||||
|
delivered = message.status == Telephony.Sms.STATUS_COMPLETE
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
prevSIMId = message.subscriptionId
|
prevSIMId = message.subscriptionId
|
||||||
}
|
}
|
||||||
|
|
@ -1153,7 +1324,11 @@ class ThreadActivity : SimpleActivity() {
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun launchActivityForResult(intent: Intent, requestCode: Int, @StringRes error: Int = org.fossify.commons.R.string.no_app_found) {
|
private fun launchActivityForResult(
|
||||||
|
intent: Intent,
|
||||||
|
requestCode: Int,
|
||||||
|
@StringRes error: Int = org.fossify.commons.R.string.no_app_found
|
||||||
|
) {
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
try {
|
try {
|
||||||
startActivityForResult(intent, requestCode)
|
startActivityForResult(intent, requestCode)
|
||||||
|
|
@ -1293,13 +1468,18 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveAttachment(resultData: Intent) {
|
private fun saveAttachment(resultData: Intent) {
|
||||||
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
val takeFlags =
|
||||||
applicationContext.contentResolver.takePersistableUriPermission(resultData.data!!, takeFlags)
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
applicationContext.contentResolver.takePersistableUriPermission(
|
||||||
|
resultData.data!!,
|
||||||
|
takeFlags
|
||||||
|
)
|
||||||
var inputStream: InputStream? = null
|
var inputStream: InputStream? = null
|
||||||
var outputStream: OutputStream? = null
|
var outputStream: OutputStream? = null
|
||||||
try {
|
try {
|
||||||
inputStream = contentResolver.openInputStream(Uri.parse(lastAttachmentUri))
|
inputStream = contentResolver.openInputStream(Uri.parse(lastAttachmentUri))
|
||||||
outputStream = contentResolver.openOutputStream(Uri.parse(resultData.dataString!!), "rwt")
|
outputStream =
|
||||||
|
contentResolver.openOutputStream(Uri.parse(resultData.dataString!!), "rwt")
|
||||||
inputStream!!.copyTo(outputStream!!)
|
inputStream!!.copyTo(outputStream!!)
|
||||||
outputStream.flush()
|
outputStream.flush()
|
||||||
toast(org.fossify.commons.R.string.file_saved)
|
toast(org.fossify.commons.R.string.file_saved)
|
||||||
|
|
@ -1338,7 +1518,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
|
|
||||||
text = removeDiacriticsIfNeeded(text)
|
text = removeDiacriticsIfNeeded(text)
|
||||||
|
|
||||||
val subscriptionId = availableSIMCards.getOrNull(currentSIMCardIndex)?.subscriptionId ?: SmsManager.getDefaultSmsSubscriptionId()
|
val subscriptionId = availableSIMCards.getOrNull(currentSIMCardIndex)?.subscriptionId
|
||||||
|
?: SmsManager.getDefaultSmsSubscriptionId()
|
||||||
|
|
||||||
if (isScheduledMessage) {
|
if (isScheduledMessage) {
|
||||||
sendScheduledMessage(text, subscriptionId)
|
sendScheduledMessage(text, subscriptionId)
|
||||||
|
|
@ -1367,7 +1548,12 @@ class ThreadActivity : SimpleActivity() {
|
||||||
val conversation = conversationsDB.getConversationWithThreadId(threadId)
|
val conversation = conversationsDB.getConversationWithThreadId(threadId)
|
||||||
if (conversation != null) {
|
if (conversation != null) {
|
||||||
val nowSeconds = (System.currentTimeMillis() / 1000).toInt()
|
val nowSeconds = (System.currentTimeMillis() / 1000).toInt()
|
||||||
conversationsDB.insertOrUpdate(conversation.copy(date = nowSeconds, snippet = message.body))
|
conversationsDB.insertOrUpdate(
|
||||||
|
conversation.copy(
|
||||||
|
date = nowSeconds,
|
||||||
|
snippet = message.body
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
scheduleMessage(message)
|
scheduleMessage(message)
|
||||||
insertOrUpdateMessage(message)
|
insertOrUpdateMessage(message)
|
||||||
|
|
@ -1379,7 +1565,9 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
showErrorToast(e.localizedMessage ?: getString(org.fossify.commons.R.string.unknown_error_occurred))
|
showErrorToast(
|
||||||
|
e.localizedMessage ?: getString(org.fossify.commons.R.string.unknown_error_occurred)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1392,7 +1580,11 @@ class ThreadActivity : SimpleActivity() {
|
||||||
sendMessageCompat(text, addresses, subscriptionId, attachments, messageToResend)
|
sendMessageCompat(text, addresses, subscriptionId, attachments, messageToResend)
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val messageIds = messages.map { it.id }
|
val messageIds = messages.map { it.id }
|
||||||
val messages = getMessages(threadId, getImageResolutions = true, limit = maxOf(1, attachments.size))
|
val messages = getMessages(
|
||||||
|
threadId = threadId,
|
||||||
|
getImageResolutions = true,
|
||||||
|
limit = maxOf(1, attachments.size)
|
||||||
|
)
|
||||||
.filter { it.id !in messageIds }
|
.filter { it.id !in messageIds }
|
||||||
for (message in messages) {
|
for (message in messages) {
|
||||||
insertOrUpdateMessage(message)
|
insertOrUpdateMessage(message)
|
||||||
|
|
@ -1403,7 +1595,9 @@ class ThreadActivity : SimpleActivity() {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
showErrorToast(e)
|
showErrorToast(e)
|
||||||
} catch (e: Error) {
|
} catch (e: Error) {
|
||||||
showErrorToast(e.localizedMessage ?: getString(org.fossify.commons.R.string.unknown_error_occurred))
|
showErrorToast(
|
||||||
|
e.localizedMessage ?: getString(org.fossify.commons.R.string.unknown_error_occurred)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1437,13 +1631,17 @@ class ThreadActivity : SimpleActivity() {
|
||||||
private fun showSelectedContact(views: ArrayList<View>) {
|
private fun showSelectedContact(views: ArrayList<View>) {
|
||||||
binding.selectedContacts.removeAllViews()
|
binding.selectedContacts.removeAllViews()
|
||||||
var newLinearLayout = LinearLayout(this)
|
var newLinearLayout = LinearLayout(this)
|
||||||
newLinearLayout.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
|
newLinearLayout.layoutParams =
|
||||||
|
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
|
||||||
newLinearLayout.orientation = LinearLayout.HORIZONTAL
|
newLinearLayout.orientation = LinearLayout.HORIZONTAL
|
||||||
|
|
||||||
val sideMargin = (binding.selectedContacts.layoutParams as RelativeLayout.LayoutParams).leftMargin
|
val sideMargin =
|
||||||
|
(binding.selectedContacts.layoutParams as RelativeLayout.LayoutParams).leftMargin
|
||||||
val mediumMargin = resources.getDimension(org.fossify.commons.R.dimen.medium_margin).toInt()
|
val mediumMargin = resources.getDimension(org.fossify.commons.R.dimen.medium_margin).toInt()
|
||||||
val parentWidth = realScreenSize.x - sideMargin * 2
|
val parentWidth = realScreenSize.x - sideMargin * 2
|
||||||
val firstRowWidth = parentWidth - resources.getDimension(org.fossify.commons.R.dimen.normal_icon_size).toInt() + sideMargin / 2
|
val firstRowWidth =
|
||||||
|
parentWidth - resources.getDimension(org.fossify.commons.R.dimen.normal_icon_size)
|
||||||
|
.toInt() + sideMargin / 2
|
||||||
var widthSoFar = 0
|
var widthSoFar = 0
|
||||||
var isFirstRow = true
|
var isFirstRow = true
|
||||||
|
|
||||||
|
|
@ -1465,7 +1663,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
isFirstRow = false
|
isFirstRow = false
|
||||||
binding.selectedContacts.addView(newLinearLayout)
|
binding.selectedContacts.addView(newLinearLayout)
|
||||||
newLinearLayout = LinearLayout(this)
|
newLinearLayout = LinearLayout(this)
|
||||||
newLinearLayout.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
|
newLinearLayout.layoutParams =
|
||||||
|
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
|
||||||
newLinearLayout.orientation = LinearLayout.HORIZONTAL
|
newLinearLayout.orientation = LinearLayout.HORIZONTAL
|
||||||
params = LayoutParams(layout.measuredWidth, layout.measuredHeight)
|
params = LayoutParams(layout.measuredWidth, layout.measuredHeight)
|
||||||
params.topMargin = mediumMargin
|
params.topMargin = mediumMargin
|
||||||
|
|
@ -1482,7 +1681,8 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSelectedContact(id: Int) {
|
private fun removeSelectedContact(id: Int) {
|
||||||
participants = participants.filter { it.rawId != id }.toMutableList() as ArrayList<SimpleContact>
|
participants =
|
||||||
|
participants.filter { it.rawId != id }.toMutableList() as ArrayList<SimpleContact>
|
||||||
showSelectedContacts()
|
showSelectedContacts()
|
||||||
updateMessageType()
|
updateMessageType()
|
||||||
}
|
}
|
||||||
|
|
@ -1502,7 +1702,10 @@ class ThreadActivity : SimpleActivity() {
|
||||||
return numbers
|
return numbers
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fixParticipantNumbers(participants: ArrayList<SimpleContact>, properNumbers: ArrayList<String>): ArrayList<SimpleContact> {
|
private fun fixParticipantNumbers(
|
||||||
|
participants: ArrayList<SimpleContact>,
|
||||||
|
properNumbers: ArrayList<String>
|
||||||
|
): ArrayList<SimpleContact> {
|
||||||
for (number in properNumbers) {
|
for (number in properNumbers) {
|
||||||
for (participant in participants) {
|
for (participant in participants) {
|
||||||
participant.phoneNumbers = participant.phoneNumbers.map {
|
participant.phoneNumbers = participant.phoneNumbers.map {
|
||||||
|
|
@ -1529,7 +1732,11 @@ class ThreadActivity : SimpleActivity() {
|
||||||
type = mimeType
|
type = mimeType
|
||||||
addCategory(Intent.CATEGORY_OPENABLE)
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
putExtra(Intent.EXTRA_TITLE, path.split("/").last())
|
putExtra(Intent.EXTRA_TITLE, path.split("/").last())
|
||||||
launchActivityForResult(this, PICK_SAVE_FILE_INTENT, error = org.fossify.commons.R.string.system_service_disabled)
|
launchActivityForResult(
|
||||||
|
intent = this,
|
||||||
|
requestCode = PICK_SAVE_FILE_INTENT,
|
||||||
|
error = org.fossify.commons.R.string.system_service_disabled
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1549,12 +1756,16 @@ class ThreadActivity : SimpleActivity() {
|
||||||
|
|
||||||
val lastMaxId = messages.filterNot { it.isScheduled }.maxByOrNull { it.id }?.id ?: 0L
|
val lastMaxId = messages.filterNot { it.isScheduled }.maxByOrNull { it.id }?.id ?: 0L
|
||||||
val newThreadId = getThreadId(participants.getAddresses().toSet())
|
val newThreadId = getThreadId(participants.getAddresses().toSet())
|
||||||
val newMessages = getMessages(newThreadId, getImageResolutions = true, includeScheduledMessages = false)
|
val newMessages =
|
||||||
|
getMessages(newThreadId, getImageResolutions = true, includeScheduledMessages = false)
|
||||||
|
|
||||||
if (messages.isNotEmpty() && messages.all { it.isScheduled } && newMessages.isNotEmpty()) {
|
if (messages.isNotEmpty() && messages.all { it.isScheduled } && newMessages.isNotEmpty()) {
|
||||||
// update scheduled messages with real thread id
|
// update scheduled messages with real thread id
|
||||||
threadId = newThreadId
|
threadId = newThreadId
|
||||||
updateScheduledMessagesThreadId(messages = messages.filter { it.threadId != threadId }, threadId)
|
updateScheduledMessagesThreadId(
|
||||||
|
messages = messages.filter { it.threadId != threadId },
|
||||||
|
newThreadId = threadId
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
messages = newMessages.apply {
|
messages = newMessages.apply {
|
||||||
|
|
@ -1567,9 +1778,10 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
messages.filter { !it.isScheduled && !it.isReceivedMessage() && it.id > lastMaxId }.forEach { latestMessage ->
|
messages.filter { !it.isScheduled && !it.isReceivedMessage() && it.id > lastMaxId }
|
||||||
messagesDB.insertOrIgnore(latestMessage)
|
.forEach { latestMessage ->
|
||||||
}
|
messagesDB.insertOrIgnore(latestMessage)
|
||||||
|
}
|
||||||
|
|
||||||
setupAdapter()
|
setupAdapter()
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
|
|
@ -1599,7 +1811,11 @@ class ThreadActivity : SimpleActivity() {
|
||||||
RadioItem(TYPE_SEND, getString(R.string.send_now)),
|
RadioItem(TYPE_SEND, getString(R.string.send_now)),
|
||||||
RadioItem(TYPE_DELETE, getString(org.fossify.commons.R.string.delete))
|
RadioItem(TYPE_DELETE, getString(org.fossify.commons.R.string.delete))
|
||||||
)
|
)
|
||||||
RadioGroupDialog(activity = this, items = items, titleId = R.string.scheduled_message) { any ->
|
RadioGroupDialog(
|
||||||
|
activity = this,
|
||||||
|
items = items,
|
||||||
|
titleId = R.string.scheduled_message
|
||||||
|
) { any ->
|
||||||
when (any as Int) {
|
when (any as Int) {
|
||||||
TYPE_DELETE -> cancelScheduledMessageAndRefresh(message.id)
|
TYPE_DELETE -> cancelScheduledMessageAndRefresh(message.id)
|
||||||
TYPE_EDIT -> editScheduledMessage(message)
|
TYPE_EDIT -> editScheduledMessage(message)
|
||||||
|
|
@ -1680,12 +1896,13 @@ class ThreadActivity : SimpleActivity() {
|
||||||
|
|
||||||
val dateTime = scheduledDateTime
|
val dateTime = scheduledDateTime
|
||||||
val millis = dateTime.millis
|
val millis = dateTime.millis
|
||||||
binding.messageHolder.scheduledMessageButton.text = if (dateTime.yearOfCentury().get() > DateTime.now().yearOfCentury().get()) {
|
binding.messageHolder.scheduledMessageButton.text =
|
||||||
millis.formatDate(this)
|
if (dateTime.yearOfCentury().get() > DateTime.now().yearOfCentury().get()) {
|
||||||
} else {
|
millis.formatDate(this)
|
||||||
val flags = FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or FORMAT_NO_YEAR
|
} else {
|
||||||
DateUtils.formatDateTime(this, millis, flags)
|
val flags = FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or FORMAT_NO_YEAR
|
||||||
}
|
DateUtils.formatDateTime(this, millis, flags)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideScheduleSendUi() {
|
private fun hideScheduleSendUi() {
|
||||||
|
|
@ -1702,7 +1919,9 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
ResourcesCompat.getDrawable(resources, drawableResId, theme)?.apply {
|
ResourcesCompat.getDrawable(resources, drawableResId, theme)?.apply {
|
||||||
applyColorFilter(getProperTextColor())
|
applyColorFilter(getProperTextColor())
|
||||||
binding.messageHolder.threadSendMessage.setCompoundDrawablesWithIntrinsicBounds(null, this, null, null)
|
binding.messageHolder.threadSendMessage.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
null, this, null, null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1836,14 +2055,18 @@ class ThreadActivity : SimpleActivity() {
|
||||||
view.onApplyWindowInsets(insets)
|
view.onApplyWindowInsets(insets)
|
||||||
}
|
}
|
||||||
|
|
||||||
val callback = object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
|
val callback =
|
||||||
override fun onPrepare(animation: WindowInsetsAnimationCompat) {
|
object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
|
||||||
super.onPrepare(animation)
|
override fun onPrepare(animation: WindowInsetsAnimationCompat) {
|
||||||
showOrHideAttachmentPicker()
|
super.onPrepare(animation)
|
||||||
}
|
showOrHideAttachmentPicker()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onProgress(insets: WindowInsetsCompat, runningAnimations: MutableList<WindowInsetsAnimationCompat>) = insets
|
override fun onProgress(
|
||||||
}
|
insets: WindowInsetsCompat,
|
||||||
|
runningAnimations: MutableList<WindowInsetsAnimationCompat>
|
||||||
|
) = insets
|
||||||
|
}
|
||||||
ViewCompat.setWindowInsetsAnimationCallback(window.decorView, callback)
|
ViewCompat.setWindowInsetsAnimationCallback(window.decorView, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1868,7 +2091,7 @@ class ThreadActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getBottomBarColor() = if (baseConfig.isUsingSystemTheme) {
|
private fun getBottomBarColor() = if (isDynamicTheme()) {
|
||||||
resources.getColor(org.fossify.commons.R.color.you_bottom_bar_color)
|
resources.getColor(org.fossify.commons.R.color.you_bottom_bar_color)
|
||||||
} else {
|
} else {
|
||||||
getBottomNavigationBackgroundColor()
|
getBottomNavigationBackgroundColor()
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,14 @@ import androidx.appcompat.app.AlertDialog
|
||||||
import com.google.android.material.timepicker.MaterialTimePicker
|
import com.google.android.material.timepicker.MaterialTimePicker
|
||||||
import com.google.android.material.timepicker.TimeFormat
|
import com.google.android.material.timepicker.TimeFormat
|
||||||
import org.fossify.commons.activities.BaseSimpleActivity
|
import org.fossify.commons.activities.BaseSimpleActivity
|
||||||
import org.fossify.commons.extensions.*
|
import org.fossify.commons.extensions.applyColorFilter
|
||||||
|
import org.fossify.commons.extensions.getAlertDialogBuilder
|
||||||
|
import org.fossify.commons.extensions.getDatePickerDialogTheme
|
||||||
|
import org.fossify.commons.extensions.getProperTextColor
|
||||||
|
import org.fossify.commons.extensions.getTimeFormat
|
||||||
|
import org.fossify.commons.extensions.isDynamicTheme
|
||||||
|
import org.fossify.commons.extensions.setupDialogStuff
|
||||||
|
import org.fossify.commons.extensions.toast
|
||||||
import org.fossify.messages.R
|
import org.fossify.messages.R
|
||||||
import org.fossify.messages.databinding.ScheduleMessageDialogBinding
|
import org.fossify.messages.databinding.ScheduleMessageDialogBinding
|
||||||
import org.fossify.messages.extensions.config
|
import org.fossify.messages.extensions.config
|
||||||
|
|
@ -94,7 +101,12 @@ class ScheduleMessageDialog(
|
||||||
|
|
||||||
val dateSetListener = OnDateSetListener { _, y, m, d -> dateSet(y, m, d) }
|
val dateSetListener = OnDateSetListener { _, y, m, d -> dateSet(y, m, d) }
|
||||||
DatePickerDialog(
|
DatePickerDialog(
|
||||||
activity, activity.getDatePickerDialogTheme(), dateSetListener, year, monthOfYear, dayOfMonth
|
activity,
|
||||||
|
activity.getDatePickerDialogTheme(),
|
||||||
|
dateSetListener,
|
||||||
|
year,
|
||||||
|
monthOfYear,
|
||||||
|
dayOfMonth
|
||||||
).apply {
|
).apply {
|
||||||
datePicker.minDate = System.currentTimeMillis()
|
datePicker.minDate = System.currentTimeMillis()
|
||||||
show()
|
show()
|
||||||
|
|
@ -111,7 +123,7 @@ class ScheduleMessageDialog(
|
||||||
val hourOfDay = dateTime?.hourOfDay ?: getNextHour()
|
val hourOfDay = dateTime?.hourOfDay ?: getNextHour()
|
||||||
val minute = dateTime?.minuteOfHour ?: getNextMinute()
|
val minute = dateTime?.minuteOfHour ?: getNextMinute()
|
||||||
|
|
||||||
if (activity.config.isUsingSystemTheme) {
|
if (activity.isDynamicTheme()) {
|
||||||
val timeFormat = if (DateFormat.is24HourFormat(activity)) {
|
val timeFormat = if (DateFormat.is24HourFormat(activity)) {
|
||||||
TimeFormat.CLOCK_24H
|
TimeFormat.CLOCK_24H
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -132,7 +144,12 @@ class ScheduleMessageDialog(
|
||||||
} else {
|
} else {
|
||||||
val timeSetListener = OnTimeSetListener { _, hours, minutes -> timeSet(hours, minutes) }
|
val timeSetListener = OnTimeSetListener { _, hours, minutes -> timeSet(hours, minutes) }
|
||||||
TimePickerDialog(
|
TimePickerDialog(
|
||||||
activity, activity.getDatePickerDialogTheme(), timeSetListener, hourOfDay, minute, DateFormat.is24HourFormat(activity)
|
activity,
|
||||||
|
activity.getDatePickerDialogTheme(),
|
||||||
|
timeSetListener,
|
||||||
|
hourOfDay,
|
||||||
|
minute,
|
||||||
|
DateFormat.is24HourFormat(activity)
|
||||||
).apply {
|
).apply {
|
||||||
show()
|
show()
|
||||||
getButton(AlertDialog.BUTTON_NEGATIVE).apply {
|
getButton(AlertDialog.BUTTON_NEGATIVE).apply {
|
||||||
|
|
@ -187,7 +204,14 @@ class ScheduleMessageDialog(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getNextHour() = (calendar.get(Calendar.HOUR_OF_DAY) + 1).coerceIn(0, 23)
|
private fun getNextHour(): Int {
|
||||||
|
return (calendar.get(Calendar.HOUR_OF_DAY) + 1)
|
||||||
|
.coerceIn(0, 23)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getNextMinute() = (calendar.get(Calendar.MINUTE) + 5).roundToClosestMultipleOf(5).coerceIn(0, 59)
|
private fun getNextMinute(): Int {
|
||||||
|
return (calendar.get(Calendar.MINUTE) + 5)
|
||||||
|
.roundToClosestMultipleOf(5)
|
||||||
|
.coerceIn(0, 59)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,6 @@ import kotlin.math.roundToInt
|
||||||
/**
|
/**
|
||||||
* Returns the closest number divisible by [multipleOf].
|
* Returns the closest number divisible by [multipleOf].
|
||||||
*/
|
*/
|
||||||
fun Int.roundToClosestMultipleOf(multipleOf: Int = 1) = (toDouble() / multipleOf).roundToInt() * multipleOf
|
fun Int.roundToClosestMultipleOf(multipleOf: Int = 1): Int {
|
||||||
|
return (toDouble() / multipleOf).roundToInt() * multipleOf
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ eventbus = "3.3.1"
|
||||||
#Room
|
#Room
|
||||||
room = "2.6.1"
|
room = "2.6.1"
|
||||||
#Fossify
|
#Fossify
|
||||||
commons = "8685963657"
|
commons = "8038e3277e"
|
||||||
android-smsmms = "c3e678befd"
|
android-smsmms = "c3e678befd"
|
||||||
indicator-fast-scroll = "4524cd0b61"
|
indicator-fast-scroll = "4524cd0b61"
|
||||||
#Gradle
|
#Gradle
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue