Migrate from kotlin synthetics to View binding

This commit is contained in:
Naveen 2023-08-17 15:54:29 +05:30
parent 3e1675d579
commit 0c01e607bb
No known key found for this signature in database
GPG Key ID: 0E155DAD31671DA3
36 changed files with 1139 additions and 1083 deletions

View File

@ -8,34 +8,40 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.ArchivedConversationsAdapter import com.simplemobiletools.smsmessenger.adapters.ArchivedConversationsAdapter
import com.simplemobiletools.smsmessenger.databinding.ActivityArchivedConversationsBinding
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Conversation
import com.simplemobiletools.smsmessenger.models.Events import com.simplemobiletools.smsmessenger.models.Events
import kotlinx.android.synthetic.main.activity_archived_conversations.*
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
class ArchivedConversationsActivity : SimpleActivity() { class ArchivedConversationsActivity : SimpleActivity() {
private var bus: EventBus? = null private var bus: EventBus? = null
private val binding by viewBinding(ActivityArchivedConversationsBinding::inflate)
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_archived_conversations) setContentView(binding.root)
setupOptionsMenu() setupOptionsMenu()
updateMaterialActivityViews(archive_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = false) updateMaterialActivityViews(
setupMaterialScrollListener(conversations_list, archive_toolbar) mainCoordinatorLayout = binding.archiveCoordinator,
nestedView = binding.conversationsList,
useTransparentNavigation = true,
useTopSearchMenu = false
)
setupMaterialScrollListener(scrollingView = binding.conversationsList, toolbar = binding.archiveToolbar)
loadArchivedConversations() loadArchivedConversations()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(archive_toolbar, NavigationIcon.Arrow) setupToolbar(binding.archiveToolbar, NavigationIcon.Arrow)
updateMenuColors() updateMenuColors()
loadArchivedConversations() loadArchivedConversations()
@ -47,9 +53,8 @@ class ArchivedConversationsActivity : SimpleActivity() {
} }
private fun setupOptionsMenu() { private fun setupOptionsMenu() {
archive_toolbar.inflateMenu(R.menu.archive_menu) binding.archiveToolbar.inflateMenu(R.menu.archive_menu)
binding.archiveToolbar.setOnMenuItemClickListener { menuItem ->
archive_toolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.empty_archive -> removeAll() R.id.empty_archive -> removeAll()
else -> return@setOnMenuItemClickListener false else -> return@setOnMenuItemClickListener false
@ -59,7 +64,7 @@ class ArchivedConversationsActivity : SimpleActivity() {
} }
private fun updateOptionsMenu(conversations: ArrayList<Conversation>) { private fun updateOptionsMenu(conversations: ArrayList<Conversation>) {
archive_toolbar.menu.apply { binding.archiveToolbar.menu.apply {
findItem(R.id.empty_archive).isVisible = conversations.isNotEmpty() findItem(R.id.empty_archive).isVisible = conversations.isNotEmpty()
} }
} }
@ -84,7 +89,7 @@ class ArchivedConversationsActivity : SimpleActivity() {
bus = EventBus.getDefault() bus = EventBus.getDefault()
try { try {
bus!!.register(this) bus!!.register(this)
} catch (e: Exception) { } catch (ignored: Exception) {
} }
} }
@ -97,19 +102,19 @@ class ArchivedConversationsActivity : SimpleActivity() {
} }
private fun getOrCreateConversationsAdapter(): ArchivedConversationsAdapter { private fun getOrCreateConversationsAdapter(): ArchivedConversationsAdapter {
var currAdapter = conversations_list.adapter var currAdapter = binding.conversationsList.adapter
if (currAdapter == null) { if (currAdapter == null) {
hideKeyboard() hideKeyboard()
currAdapter = ArchivedConversationsAdapter( currAdapter = ArchivedConversationsAdapter(
activity = this, activity = this,
recyclerView = conversations_list, recyclerView = binding.conversationsList,
onRefresh = { notifyDatasetChanged() }, onRefresh = { notifyDatasetChanged() },
itemClick = { handleConversationClick(it) } itemClick = { handleConversationClick(it) }
) )
conversations_list.adapter = currAdapter binding.conversationsList.adapter = currAdapter
if (areSystemAnimationsEnabled) { if (areSystemAnimationsEnabled) {
conversations_list.scheduleLayoutAnimation() binding.conversationsList.scheduleLayoutAnimation()
} }
} }
return currAdapter as ArchivedConversationsAdapter return currAdapter as ArchivedConversationsAdapter
@ -133,9 +138,9 @@ class ArchivedConversationsActivity : SimpleActivity() {
} }
private fun showOrHidePlaceholder(show: Boolean) { private fun showOrHidePlaceholder(show: Boolean) {
conversations_fastscroller.beGoneIf(show) binding.conversationsFastscroller.beGoneIf(show)
no_conversations_placeholder.beVisibleIf(show) binding.noConversationsPlaceholder.beVisibleIf(show)
no_conversations_placeholder.text = getString(R.string.no_archived_conversations) binding.noConversationsPlaceholder.text = getString(R.string.no_archived_conversations)
} }
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")

View File

@ -2,20 +2,17 @@ package com.simplemobiletools.smsmessenger.activities
import android.os.Bundle import android.os.Bundle
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import com.simplemobiletools.commons.extensions.applyColorFilter import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.helpers.NavigationIcon import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.ContactsAdapter import com.simplemobiletools.smsmessenger.adapters.ContactsAdapter
import com.simplemobiletools.smsmessenger.databinding.ActivityConversationDetailsBinding
import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Conversation
import kotlinx.android.synthetic.main.activity_conversation_details.*
class ConversationDetailsActivity : SimpleActivity() { class ConversationDetailsActivity : SimpleActivity() {
@ -23,13 +20,20 @@ class ConversationDetailsActivity : SimpleActivity() {
private var conversation: Conversation? = null private var conversation: Conversation? = null
private lateinit var participants: ArrayList<SimpleContact> private lateinit var participants: ArrayList<SimpleContact>
private val binding by viewBinding(ActivityConversationDetailsBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_conversation_details) setContentView(binding.root)
updateMaterialActivityViews(conversation_details_coordinator, participants_recyclerview, useTransparentNavigation = true, useTopSearchMenu = false) updateMaterialActivityViews(
setupMaterialScrollListener(participants_recyclerview, conversation_details_toolbar) mainCoordinatorLayout = binding.conversationDetailsCoordinator,
nestedView = binding.participantsRecyclerview,
useTransparentNavigation = true,
useTopSearchMenu = false
)
setupMaterialScrollListener(scrollingView = binding.participantsRecyclerview, toolbar = binding.conversationDetailsToolbar)
threadId = intent.getLongExtra(THREAD_ID, 0L) threadId = intent.getLongExtra(THREAD_ID, 0L)
ensureBackgroundThread { ensureBackgroundThread {
@ -49,16 +53,16 @@ class ConversationDetailsActivity : SimpleActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(conversation_details_toolbar, NavigationIcon.Arrow) setupToolbar(binding.conversationDetailsToolbar, NavigationIcon.Arrow)
updateTextColors(conversation_details_holder) updateTextColors(binding.conversationDetailsHolder)
val primaryColor = getProperPrimaryColor() val primaryColor = getProperPrimaryColor()
conversation_name_heading.setTextColor(primaryColor) binding.conversationNameHeading.setTextColor(primaryColor)
members_heading.setTextColor(primaryColor) binding.membersHeading.setTextColor(primaryColor)
} }
private fun setupTextViews() { private fun setupTextViews() {
conversation_name.apply { binding.conversationName.apply {
ResourcesCompat.getDrawable(resources, R.drawable.ic_edit_vector, theme)?.apply { ResourcesCompat.getDrawable(resources, R.drawable.ic_edit_vector, theme)?.apply {
applyColorFilter(getProperTextColor()) applyColorFilter(getProperTextColor())
setCompoundDrawablesWithIntrinsicBounds(null, null, this, null) setCompoundDrawablesWithIntrinsicBounds(null, null, this, null)
@ -77,7 +81,7 @@ class ConversationDetailsActivity : SimpleActivity() {
} }
private fun setupParticipants() { private fun setupParticipants() {
val adapter = ContactsAdapter(this, participants, participants_recyclerview) { val adapter = ContactsAdapter(this, participants, binding.participantsRecyclerview) {
val contact = it as SimpleContact val contact = it as SimpleContact
val address = contact.phoneNumbers.first().normalizedNumber val address = contact.phoneNumbers.first().normalizedNumber
getContactFromAddress(address) { simpleContact -> getContactFromAddress(address) { simpleContact ->
@ -86,6 +90,6 @@ class ConversationDetailsActivity : SimpleActivity() {
} }
} }
} }
participants_recyclerview.adapter = adapter binding.participantsRecyclerview.adapter = adapter
} }
} }

View File

@ -21,13 +21,13 @@ import com.simplemobiletools.smsmessenger.BuildConfig
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter
import com.simplemobiletools.smsmessenger.adapters.SearchResultsAdapter import com.simplemobiletools.smsmessenger.adapters.SearchResultsAdapter
import com.simplemobiletools.smsmessenger.databinding.ActivityMainBinding
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Conversation
import com.simplemobiletools.smsmessenger.models.Events import com.simplemobiletools.smsmessenger.models.Events
import com.simplemobiletools.smsmessenger.models.Message import com.simplemobiletools.smsmessenger.models.Message
import com.simplemobiletools.smsmessenger.models.SearchResult import com.simplemobiletools.smsmessenger.models.SearchResult
import kotlinx.android.synthetic.main.activity_main.*
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
@ -41,16 +41,23 @@ class MainActivity : SimpleActivity() {
private var bus: EventBus? = null private var bus: EventBus? = null
private var wasProtectionHandled = false private var wasProtectionHandled = false
private val binding by viewBinding(ActivityMainBinding::inflate)
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(binding.root)
appLaunched(BuildConfig.APPLICATION_ID) appLaunched(BuildConfig.APPLICATION_ID)
setupOptionsMenu() setupOptionsMenu()
refreshMenuItems() refreshMenuItems()
updateMaterialActivityViews(main_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = true) updateMaterialActivityViews(
mainCoordinatorLayout = binding.mainCoordinator,
nestedView = binding.conversationsList,
useTransparentNavigation = true,
useTopSearchMenu = true
)
if (savedInstanceState == null) { if (savedInstanceState == null) {
checkAndDeleteOldRecycleBinMessages() checkAndDeleteOldRecycleBinMessages()
@ -88,17 +95,17 @@ class MainActivity : SimpleActivity() {
updateDrafts() updateDrafts()
} }
updateTextColors(main_coordinator) updateTextColors(binding.mainCoordinator)
search_holder.setBackgroundColor(getProperBackgroundColor()) binding.searchHolder.setBackgroundColor(getProperBackgroundColor())
val properPrimaryColor = getProperPrimaryColor() val properPrimaryColor = getProperPrimaryColor()
no_conversations_placeholder_2.setTextColor(properPrimaryColor) binding.noConversationsPlaceholder2.setTextColor(properPrimaryColor)
no_conversations_placeholder_2.underlineText() binding.noConversationsPlaceholder2.underlineText()
conversations_fastscroller.updateColors(properPrimaryColor) binding.conversationsFastscroller.updateColors(properPrimaryColor)
conversations_progress_bar.setIndicatorColor(properPrimaryColor) binding.conversationsProgressBar.setIndicatorColor(properPrimaryColor)
conversations_progress_bar.trackColor = properPrimaryColor.adjustAlpha(LOWER_ALPHA) binding.conversationsProgressBar.trackColor = properPrimaryColor.adjustAlpha(LOWER_ALPHA)
checkShortcut() checkShortcut()
(conversations_fab?.layoutParams as? CoordinatorLayout.LayoutParams)?.bottomMargin = (binding.conversationsFab.layoutParams as? CoordinatorLayout.LayoutParams)?.bottomMargin =
navigationBarHeight + resources.getDimension(R.dimen.activity_margin).toInt() navigationBarHeight + resources.getDimension(R.dimen.activity_margin).toInt()
} }
@ -113,8 +120,8 @@ class MainActivity : SimpleActivity() {
} }
override fun onBackPressed() { override fun onBackPressed() {
if (main_menu.isSearchOpen) { if (binding.mainMenu.isSearchOpen) {
main_menu.closeSearch() binding.mainMenu.closeSearch()
} else { } else {
super.onBackPressed() super.onBackPressed()
} }
@ -144,18 +151,18 @@ class MainActivity : SimpleActivity() {
} }
private fun setupOptionsMenu() { private fun setupOptionsMenu() {
main_menu.getToolbar().inflateMenu(R.menu.menu_main) binding.mainMenu.getToolbar().inflateMenu(R.menu.menu_main)
main_menu.toggleHideOnScroll(true) binding.mainMenu.toggleHideOnScroll(true)
main_menu.setupMenu() binding.mainMenu.setupMenu()
main_menu.onSearchClosedListener = { binding.mainMenu.onSearchClosedListener = {
fadeOutSearch() fadeOutSearch()
} }
main_menu.onSearchTextChangedListener = { text -> binding.mainMenu.onSearchTextChangedListener = { text ->
if (text.isNotEmpty()) { if (text.isNotEmpty()) {
if (search_holder.alpha < 1f) { if (binding.searchHolder.alpha < 1f) {
search_holder.fadeIn() binding.searchHolder.fadeIn()
} }
} else { } else {
fadeOutSearch() fadeOutSearch()
@ -163,7 +170,7 @@ class MainActivity : SimpleActivity() {
searchTextChanged(text) searchTextChanged(text)
} }
main_menu.getToolbar().setOnMenuItemClickListener { menuItem -> binding.mainMenu.getToolbar().setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent() R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
R.id.show_recycle_bin -> launchRecycleBin() R.id.show_recycle_bin -> launchRecycleBin()
@ -177,7 +184,7 @@ class MainActivity : SimpleActivity() {
} }
private fun refreshMenuItems() { private fun refreshMenuItems() {
main_menu.getToolbar().menu.apply { binding.mainMenu.getToolbar().menu.apply {
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations) findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
findItem(R.id.show_recycle_bin).isVisible = config.useRecycleBin findItem(R.id.show_recycle_bin).isVisible = config.useRecycleBin
} }
@ -201,7 +208,7 @@ class MainActivity : SimpleActivity() {
private fun updateMenuColors() { private fun updateMenuColors() {
updateStatusbarColor(getProperBackgroundColor()) updateStatusbarColor(getProperBackgroundColor())
main_menu.updateColors() binding.mainMenu.updateColors()
} }
private fun loadMessages() { private fun loadMessages() {
@ -249,7 +256,7 @@ class MainActivity : SimpleActivity() {
bus = EventBus.getDefault() bus = EventBus.getDefault()
try { try {
bus!!.register(this) bus!!.register(this)
} catch (e: Exception) { } catch (ignored: Exception) {
} }
} }
} else { } else {
@ -267,11 +274,11 @@ class MainActivity : SimpleActivity() {
storeStateVariables() storeStateVariables()
getCachedConversations() getCachedConversations()
no_conversations_placeholder_2.setOnClickListener { binding.noConversationsPlaceholder2.setOnClickListener {
launchNewConversation() launchNewConversation()
} }
conversations_fab.setOnClickListener { binding.conversationsFab.setOnClickListener {
launchNewConversation() launchNewConversation()
} }
} }
@ -364,19 +371,19 @@ class MainActivity : SimpleActivity() {
} }
private fun getOrCreateConversationsAdapter(): ConversationsAdapter { private fun getOrCreateConversationsAdapter(): ConversationsAdapter {
var currAdapter = conversations_list.adapter var currAdapter = binding.conversationsList.adapter
if (currAdapter == null) { if (currAdapter == null) {
hideKeyboard() hideKeyboard()
currAdapter = ConversationsAdapter( currAdapter = ConversationsAdapter(
activity = this, activity = this,
recyclerView = conversations_list, recyclerView = binding.conversationsList,
onRefresh = { notifyDatasetChanged() }, onRefresh = { notifyDatasetChanged() },
itemClick = { handleConversationClick(it) } itemClick = { handleConversationClick(it) }
) )
conversations_list.adapter = currAdapter binding.conversationsList.adapter = currAdapter
if (areSystemAnimationsEnabled) { if (areSystemAnimationsEnabled) {
conversations_list.scheduleLayoutAnimation() binding.conversationsList.scheduleLayoutAnimation()
} }
} }
return currAdapter as ConversationsAdapter return currAdapter as ConversationsAdapter
@ -410,25 +417,25 @@ class MainActivity : SimpleActivity() {
private fun showOrHideProgress(show: Boolean) { private fun showOrHideProgress(show: Boolean) {
if (show) { if (show) {
conversations_progress_bar.show() binding.conversationsProgressBar.show()
no_conversations_placeholder.beVisible() binding.noConversationsPlaceholder.beVisible()
no_conversations_placeholder.text = getString(R.string.loading_messages) binding.noConversationsPlaceholder.text = getString(R.string.loading_messages)
} else { } else {
conversations_progress_bar.hide() binding.conversationsProgressBar.hide()
no_conversations_placeholder.beGone() binding.noConversationsPlaceholder.beGone()
} }
} }
private fun showOrHidePlaceholder(show: Boolean) { private fun showOrHidePlaceholder(show: Boolean) {
conversations_fastscroller.beGoneIf(show) binding.conversationsFastscroller.beGoneIf(show)
no_conversations_placeholder.beVisibleIf(show) binding.noConversationsPlaceholder.beVisibleIf(show)
no_conversations_placeholder.text = getString(R.string.no_conversations_found) binding.noConversationsPlaceholder.text = getString(R.string.no_conversations_found)
no_conversations_placeholder_2.beVisibleIf(show) binding.noConversationsPlaceholder2.beVisibleIf(show)
} }
private fun fadeOutSearch() { private fun fadeOutSearch() {
search_holder.animate().alpha(0f).setDuration(SHORT_ANIMATION_DURATION).withEndAction { binding.searchHolder.animate().alpha(0f).setDuration(SHORT_ANIMATION_DURATION).withEndAction {
search_holder.beGone() binding.searchHolder.beGone()
searchTextChanged("", true) searchTextChanged("", true)
}.start() }.start()
} }
@ -488,12 +495,12 @@ class MainActivity : SimpleActivity() {
} }
private fun searchTextChanged(text: String, forceUpdate: Boolean = false) { private fun searchTextChanged(text: String, forceUpdate: Boolean = false) {
if (!main_menu.isSearchOpen && !forceUpdate) { if (!binding.mainMenu.isSearchOpen && !forceUpdate) {
return return
} }
lastSearchedText = text lastSearchedText = text
search_placeholder_2.beGoneIf(text.length >= 2) binding.searchPlaceholder2.beGoneIf(text.length >= 2)
if (text.length >= 2) { if (text.length >= 2) {
ensureBackgroundThread { ensureBackgroundThread {
val searchQuery = "%$text%" val searchQuery = "%$text%"
@ -504,8 +511,8 @@ class MainActivity : SimpleActivity() {
} }
} }
} else { } else {
search_placeholder.beVisible() binding.searchPlaceholder.beVisible()
search_results_list.beGone() binding.searchResultsList.beGone()
} }
} }
@ -530,12 +537,12 @@ class MainActivity : SimpleActivity() {
} }
runOnUiThread { runOnUiThread {
search_results_list.beVisibleIf(searchResults.isNotEmpty()) binding.searchResultsList.beVisibleIf(searchResults.isNotEmpty())
search_placeholder.beVisibleIf(searchResults.isEmpty()) binding.searchPlaceholder.beVisibleIf(searchResults.isEmpty())
val currAdapter = search_results_list.adapter val currAdapter = binding.searchResultsList.adapter
if (currAdapter == null) { if (currAdapter == null) {
SearchResultsAdapter(this, searchResults, search_results_list, searchedText) { SearchResultsAdapter(this, searchResults, binding.searchResultsList, searchedText) {
hideKeyboard() hideKeyboard()
Intent(this, ThreadActivity::class.java).apply { Intent(this, ThreadActivity::class.java).apply {
putExtra(THREAD_ID, (it as SearchResult).threadId) putExtra(THREAD_ID, (it as SearchResult).threadId)
@ -544,7 +551,7 @@ class MainActivity : SimpleActivity() {
startActivity(this) startActivity(this)
} }
}.apply { }.apply {
search_results_list.adapter = this binding.searchResultsList.adapter = this
} }
} else { } else {
(currAdapter as SearchResultsAdapter).updateItems(searchResults, searchedText) (currAdapter as SearchResultsAdapter).updateItems(searchResults, searchedText)

View File

@ -6,35 +6,43 @@ import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.getProperPrimaryColor import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.underlineText import com.simplemobiletools.commons.extensions.underlineText
import com.simplemobiletools.commons.extensions.updateTextColors import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.APP_ICON_IDS import com.simplemobiletools.commons.helpers.APP_ICON_IDS
import com.simplemobiletools.commons.helpers.APP_LAUNCHER_NAME import com.simplemobiletools.commons.helpers.APP_LAUNCHER_NAME
import com.simplemobiletools.commons.helpers.NavigationIcon import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.databinding.ActivityManageBlockedKeywordsBinding
import com.simplemobiletools.smsmessenger.dialogs.AddBlockedKeywordDialog import com.simplemobiletools.smsmessenger.dialogs.AddBlockedKeywordDialog
import com.simplemobiletools.smsmessenger.dialogs.ManageBlockedKeywordsAdapter import com.simplemobiletools.smsmessenger.dialogs.ManageBlockedKeywordsAdapter
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.extensions.toArrayList import com.simplemobiletools.smsmessenger.extensions.toArrayList
import kotlinx.android.synthetic.main.activity_manage_blocked_keywords.*
class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewListener { class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewListener {
override fun getAppIconIDs() = intent.getIntegerArrayListExtra(APP_ICON_IDS) ?: ArrayList() override fun getAppIconIDs() = intent.getIntegerArrayListExtra(APP_ICON_IDS) ?: ArrayList()
override fun getAppLauncherName() = intent.getStringExtra(APP_LAUNCHER_NAME) ?: "" override fun getAppLauncherName() = intent.getStringExtra(APP_LAUNCHER_NAME) ?: ""
private val binding by viewBinding(ActivityManageBlockedKeywordsBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_manage_blocked_keywords) setContentView(binding.root)
updateBlockedKeywords() updateBlockedKeywords()
setupOptionsMenu() setupOptionsMenu()
updateMaterialActivityViews(block_keywords_coordinator, manage_blocked_keywords_list, useTransparentNavigation = true, useTopSearchMenu = false) updateMaterialActivityViews(
setupMaterialScrollListener(manage_blocked_keywords_list, block_keywords_toolbar) mainCoordinatorLayout = binding.blockKeywordsCoordinator,
updateTextColors(manage_blocked_keywords_wrapper) nestedView = binding.manageBlockedKeywordsList,
useTransparentNavigation = true,
useTopSearchMenu = false
)
setupMaterialScrollListener(scrollingView = binding.manageBlockedKeywordsList, toolbar = binding.blockKeywordsToolbar)
updateTextColors(binding.manageBlockedKeywordsWrapper)
manage_blocked_keywords_placeholder_2.apply { binding.manageBlockedKeywordsPlaceholder2.apply {
underlineText() underlineText()
setTextColor(getProperPrimaryColor()) setTextColor(getProperPrimaryColor())
setOnClickListener { setOnClickListener {
@ -45,11 +53,11 @@ class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewL
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(block_keywords_toolbar, NavigationIcon.Arrow) setupToolbar(binding.blockKeywordsToolbar, NavigationIcon.Arrow)
} }
private fun setupOptionsMenu() { private fun setupOptionsMenu() {
block_keywords_toolbar.setOnMenuItemClickListener { menuItem -> binding.blockKeywordsToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.add_blocked_keyword -> { R.id.add_blocked_keyword -> {
addOrEditBlockedKeyword() addOrEditBlockedKeyword()
@ -69,14 +77,14 @@ class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewL
ensureBackgroundThread { ensureBackgroundThread {
val blockedKeywords = config.blockedKeywords val blockedKeywords = config.blockedKeywords
runOnUiThread { runOnUiThread {
ManageBlockedKeywordsAdapter(this, blockedKeywords.toArrayList(), this, manage_blocked_keywords_list) { ManageBlockedKeywordsAdapter(this, blockedKeywords.toArrayList(), this, binding.manageBlockedKeywordsList) {
addOrEditBlockedKeyword(it as String) addOrEditBlockedKeyword(it as String)
}.apply { }.apply {
manage_blocked_keywords_list.adapter = this binding.manageBlockedKeywordsList.adapter = this
} }
manage_blocked_keywords_placeholder.beVisibleIf(blockedKeywords.isEmpty()) binding.manageBlockedKeywordsPlaceholder.beVisibleIf(blockedKeywords.isEmpty())
manage_blocked_keywords_placeholder_2.beVisibleIf(blockedKeywords.isEmpty()) binding.manageBlockedKeywordsPlaceholder2.beVisibleIf(blockedKeywords.isEmpty())
} }
} }
} }

View File

@ -14,31 +14,38 @@ import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.ContactsAdapter import com.simplemobiletools.smsmessenger.adapters.ContactsAdapter
import com.simplemobiletools.smsmessenger.databinding.ActivityNewConversationBinding
import com.simplemobiletools.smsmessenger.databinding.ItemSuggestedContactBinding
import com.simplemobiletools.smsmessenger.extensions.getSuggestedContacts import com.simplemobiletools.smsmessenger.extensions.getSuggestedContacts
import com.simplemobiletools.smsmessenger.extensions.getThreadId import com.simplemobiletools.smsmessenger.extensions.getThreadId
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.messaging.isShortCodeWithLetters import com.simplemobiletools.smsmessenger.messaging.isShortCodeWithLetters
import kotlinx.android.synthetic.main.activity_new_conversation.*
import kotlinx.android.synthetic.main.item_suggested_contact.view.*
import java.net.URLDecoder import java.net.URLDecoder
import java.util.* import java.util.Locale
class NewConversationActivity : SimpleActivity() { class NewConversationActivity : SimpleActivity() {
private var allContacts = ArrayList<SimpleContact>() private var allContacts = ArrayList<SimpleContact>()
private var privateContacts = ArrayList<SimpleContact>() private var privateContacts = ArrayList<SimpleContact>()
private val binding by viewBinding(ActivityNewConversationBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_conversation) setContentView(binding.root)
title = getString(R.string.new_conversation) title = getString(R.string.new_conversation)
updateTextColors(new_conversation_holder) updateTextColors(binding.newConversationHolder)
updateMaterialActivityViews(new_conversation_coordinator, contacts_list, useTransparentNavigation = true, useTopSearchMenu = false) updateMaterialActivityViews(
setupMaterialScrollListener(contacts_list, new_conversation_toolbar) mainCoordinatorLayout = binding.newConversationCoordinator,
nestedView = binding.contactsList,
useTransparentNavigation = true,
useTopSearchMenu = false
)
setupMaterialScrollListener(scrollingView = binding.contactsList, toolbar = binding.newConversationToolbar)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
new_conversation_address.requestFocus() binding.newConversationAddress.requestFocus()
// READ_CONTACTS permission is not mandatory, but without it we won't be able to show any suggestions during typing // READ_CONTACTS permission is not mandatory, but without it we won't be able to show any suggestions during typing
handlePermission(PERMISSION_READ_CONTACTS) { handlePermission(PERMISSION_READ_CONTACTS) {
@ -48,10 +55,10 @@ class NewConversationActivity : SimpleActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(new_conversation_toolbar, NavigationIcon.Arrow) setupToolbar(binding.newConversationToolbar, NavigationIcon.Arrow)
no_contacts_placeholder_2.setTextColor(getProperPrimaryColor()) binding.noContactsPlaceholder2.setTextColor(getProperPrimaryColor())
no_contacts_placeholder_2.underlineText() binding.noContactsPlaceholder2.underlineText()
suggestions_label.setTextColor(getProperPrimaryColor()) binding.suggestionsLabel.setTextColor(getProperPrimaryColor())
} }
private fun initContacts() { private fun initContacts() {
@ -60,7 +67,7 @@ class NewConversationActivity : SimpleActivity() {
} }
fetchContacts() fetchContacts()
new_conversation_address.onTextChangeListener { searchString -> binding.newConversationAddress.onTextChangeListener { searchString ->
val filteredContacts = ArrayList<SimpleContact>() val filteredContacts = ArrayList<SimpleContact>()
allContacts.forEach { contact -> allContacts.forEach { contact ->
if (contact.phoneNumbers.any { it.normalizedNumber.contains(searchString, true) } || if (contact.phoneNumbers.any { it.normalizedNumber.contains(searchString, true) } ||
@ -74,21 +81,21 @@ class NewConversationActivity : SimpleActivity() {
filteredContacts.sortWith(compareBy { !it.name.startsWith(searchString, true) }) filteredContacts.sortWith(compareBy { !it.name.startsWith(searchString, true) })
setupAdapter(filteredContacts) setupAdapter(filteredContacts)
new_conversation_confirm.beVisibleIf(searchString.length > 2) binding.newConversationConfirm.beVisibleIf(searchString.length > 2)
} }
new_conversation_confirm.applyColorFilter(getProperTextColor()) binding.newConversationConfirm.applyColorFilter(getProperTextColor())
new_conversation_confirm.setOnClickListener { binding.newConversationConfirm.setOnClickListener {
val number = new_conversation_address.value val number = binding.newConversationAddress.value
if (isShortCodeWithLetters(number)) { if (isShortCodeWithLetters(number)) {
new_conversation_address.setText("") binding.newConversationAddress.setText("")
toast(R.string.invalid_short_code, length = Toast.LENGTH_LONG) toast(R.string.invalid_short_code, length = Toast.LENGTH_LONG)
return@setOnClickListener return@setOnClickListener
} }
launchThreadActivity(number, number) launchThreadActivity(number, number)
} }
no_contacts_placeholder_2.setOnClickListener { binding.noContactsPlaceholder2.setOnClickListener {
handlePermission(PERMISSION_READ_CONTACTS) { handlePermission(PERMISSION_READ_CONTACTS) {
if (it) { if (it) {
fetchContacts() fetchContacts()
@ -97,11 +104,11 @@ class NewConversationActivity : SimpleActivity() {
} }
val properPrimaryColor = getProperPrimaryColor() val properPrimaryColor = getProperPrimaryColor()
contacts_letter_fastscroller.textColor = getProperTextColor().getColorStateList() binding.contactsLetterFastscroller.textColor = getProperTextColor().getColorStateList()
contacts_letter_fastscroller.pressedTextColor = properPrimaryColor binding.contactsLetterFastscroller.pressedTextColor = properPrimaryColor
contacts_letter_fastscroller_thumb.setupWithFastScroller(contacts_letter_fastscroller) binding.contactsLetterFastscrollerThumb.setupWithFastScroller(binding.contactsLetterFastscroller)
contacts_letter_fastscroller_thumb?.textColor = properPrimaryColor.getContrastColor() binding.contactsLetterFastscrollerThumb.textColor = properPrimaryColor.getContrastColor()
contacts_letter_fastscroller_thumb?.thumbColor = properPrimaryColor.getColorStateList() binding.contactsLetterFastscrollerThumb.thumbColor = properPrimaryColor.getColorStateList()
} }
private fun isThirdPartyIntent(): Boolean { private fun isThirdPartyIntent(): Boolean {
@ -133,18 +140,18 @@ class NewConversationActivity : SimpleActivity() {
private fun setupAdapter(contacts: ArrayList<SimpleContact>) { private fun setupAdapter(contacts: ArrayList<SimpleContact>) {
val hasContacts = contacts.isNotEmpty() val hasContacts = contacts.isNotEmpty()
contacts_list.beVisibleIf(hasContacts) binding.contactsList.beVisibleIf(hasContacts)
no_contacts_placeholder.beVisibleIf(!hasContacts) binding.noContactsPlaceholder.beVisibleIf(!hasContacts)
no_contacts_placeholder_2.beVisibleIf(!hasContacts && !hasPermission(PERMISSION_READ_CONTACTS)) binding.noContactsPlaceholder2.beVisibleIf(!hasContacts && !hasPermission(PERMISSION_READ_CONTACTS))
if (!hasContacts) { if (!hasContacts) {
val placeholderText = if (hasPermission(PERMISSION_READ_CONTACTS)) R.string.no_contacts_found else R.string.no_access_to_contacts val placeholderText = if (hasPermission(PERMISSION_READ_CONTACTS)) R.string.no_contacts_found else R.string.no_access_to_contacts
no_contacts_placeholder.text = getString(placeholderText) binding.noContactsPlaceholder.text = getString(placeholderText)
} }
val currAdapter = contacts_list.adapter val currAdapter = binding.contactsList.adapter
if (currAdapter == null) { if (currAdapter == null) {
ContactsAdapter(this, contacts, contacts_list) { ContactsAdapter(this, contacts, binding.contactsList) {
hideKeyboard() hideKeyboard()
val contact = it as SimpleContact val contact = it as SimpleContact
val phoneNumbers = contact.phoneNumbers val phoneNumbers = contact.phoneNumbers
@ -167,11 +174,11 @@ class NewConversationActivity : SimpleActivity() {
launchThreadActivity(phoneNumbers.first().normalizedNumber, contact.name) launchThreadActivity(phoneNumbers.first().normalizedNumber, contact.name)
} }
}.apply { }.apply {
contacts_list.adapter = this binding.contactsList.adapter = this
} }
if (areSystemAnimationsEnabled) { if (areSystemAnimationsEnabled) {
contacts_list.scheduleLayoutAnimation() binding.contactsList.scheduleLayoutAnimation()
} }
} else { } else {
(currAdapter as ContactsAdapter).updateContacts(contacts) (currAdapter as ContactsAdapter).updateContacts(contacts)
@ -186,23 +193,23 @@ class NewConversationActivity : SimpleActivity() {
privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor) privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor)
val suggestions = getSuggestedContacts(privateContacts) val suggestions = getSuggestedContacts(privateContacts)
runOnUiThread { runOnUiThread {
suggestions_holder.removeAllViews() binding.suggestionsHolder.removeAllViews()
if (suggestions.isEmpty()) { if (suggestions.isEmpty()) {
suggestions_label.beGone() binding.suggestionsLabel.beGone()
suggestions_scrollview.beGone() binding.suggestionsScrollview.beGone()
} else { } else {
suggestions_label.beVisible() binding.suggestionsLabel.beVisible()
suggestions_scrollview.beVisible() binding.suggestionsScrollview.beVisible()
suggestions.forEach { suggestions.forEach {
val contact = it val contact = it
layoutInflater.inflate(R.layout.item_suggested_contact, null).apply { ItemSuggestedContactBinding.inflate(layoutInflater).apply {
suggested_contact_name.text = contact.name suggestedContactName.text = contact.name
suggested_contact_name.setTextColor(getProperTextColor()) suggestedContactName.setTextColor(getProperTextColor())
if (!isDestroyed) { if (!isDestroyed) {
SimpleContactsHelper(this@NewConversationActivity).loadContactImage(contact.photoUri, suggested_contact_image, contact.name) SimpleContactsHelper(this@NewConversationActivity).loadContactImage(contact.photoUri, suggestedContactImage, contact.name)
suggestions_holder.addView(this) binding.suggestionsHolder.addView(root)
setOnClickListener { root.setOnClickListener {
launchThreadActivity(contact.phoneNumbers.first().normalizedNumber, contact.name) launchThreadActivity(contact.phoneNumbers.first().normalizedNumber, contact.name)
} }
} }
@ -215,11 +222,11 @@ class NewConversationActivity : SimpleActivity() {
} }
private fun setupLetterFastscroller(contacts: ArrayList<SimpleContact>) { private fun setupLetterFastscroller(contacts: ArrayList<SimpleContact>) {
contacts_letter_fastscroller.setupWithRecyclerView(contacts_list, { position -> binding.contactsLetterFastscroller.setupWithRecyclerView(binding.contactsList, { position ->
try { try {
val name = contacts[position].name val name = contacts[position].name
val character = if (name.isNotEmpty()) name.substring(0, 1) else "" val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()).normalizeString()) FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()).normalizeString())
} catch (e: Exception) { } catch (e: Exception) {
FastScrollItemIndicator.Text("") FastScrollItemIndicator.Text("")
} }

View File

@ -7,36 +7,41 @@ import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter
import com.simplemobiletools.smsmessenger.adapters.RecycleBinConversationsAdapter import com.simplemobiletools.smsmessenger.adapters.RecycleBinConversationsAdapter
import com.simplemobiletools.smsmessenger.databinding.ActivityRecycleBinConversationsBinding
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Conversation
import com.simplemobiletools.smsmessenger.models.Events import com.simplemobiletools.smsmessenger.models.Events
import kotlinx.android.synthetic.main.activity_recycle_bin_conversations.*
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
class RecycleBinConversationsActivity : SimpleActivity() { class RecycleBinConversationsActivity : SimpleActivity() {
private var bus: EventBus? = null private var bus: EventBus? = null
private val binding by viewBinding(ActivityRecycleBinConversationsBinding::inflate)
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recycle_bin_conversations) setContentView(binding.root)
setupOptionsMenu() setupOptionsMenu()
updateMaterialActivityViews(recycle_bin_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = false) updateMaterialActivityViews(
setupMaterialScrollListener(conversations_list, recycle_bin_toolbar) mainCoordinatorLayout = binding.recycleBinCoordinator,
nestedView = binding.conversationsList,
useTransparentNavigation = true,
useTopSearchMenu = false
)
setupMaterialScrollListener(scrollingView = binding.conversationsList, toolbar = binding.recycleBinToolbar)
loadRecycleBinConversations() loadRecycleBinConversations()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(recycle_bin_toolbar, NavigationIcon.Arrow) setupToolbar(binding.recycleBinToolbar, NavigationIcon.Arrow)
updateMenuColors() updateMenuColors()
loadRecycleBinConversations() loadRecycleBinConversations()
@ -48,9 +53,8 @@ class RecycleBinConversationsActivity : SimpleActivity() {
} }
private fun setupOptionsMenu() { private fun setupOptionsMenu() {
recycle_bin_toolbar.inflateMenu(R.menu.recycle_bin_menu) binding.recycleBinToolbar.inflateMenu(R.menu.recycle_bin_menu)
binding.recycleBinToolbar.setOnMenuItemClickListener { menuItem ->
recycle_bin_toolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.empty_recycle_bin -> removeAll() R.id.empty_recycle_bin -> removeAll()
else -> return@setOnMenuItemClickListener false else -> return@setOnMenuItemClickListener false
@ -60,7 +64,7 @@ class RecycleBinConversationsActivity : SimpleActivity() {
} }
private fun updateOptionsMenu(conversations: ArrayList<Conversation>) { private fun updateOptionsMenu(conversations: ArrayList<Conversation>) {
recycle_bin_toolbar.menu.apply { binding.recycleBinToolbar.menu.apply {
findItem(R.id.empty_recycle_bin).isVisible = conversations.isNotEmpty() findItem(R.id.empty_recycle_bin).isVisible = conversations.isNotEmpty()
} }
} }
@ -85,7 +89,7 @@ class RecycleBinConversationsActivity : SimpleActivity() {
bus = EventBus.getDefault() bus = EventBus.getDefault()
try { try {
bus!!.register(this) bus!!.register(this)
} catch (e: Exception) { } catch (ignored: Exception) {
} }
} }
@ -99,19 +103,19 @@ class RecycleBinConversationsActivity : SimpleActivity() {
} }
private fun getOrCreateConversationsAdapter(): RecycleBinConversationsAdapter { private fun getOrCreateConversationsAdapter(): RecycleBinConversationsAdapter {
var currAdapter = conversations_list.adapter var currAdapter = binding.conversationsList.adapter
if (currAdapter == null) { if (currAdapter == null) {
hideKeyboard() hideKeyboard()
currAdapter = RecycleBinConversationsAdapter( currAdapter = RecycleBinConversationsAdapter(
activity = this, activity = this,
recyclerView = conversations_list, recyclerView = binding.conversationsList,
onRefresh = { notifyDatasetChanged() }, onRefresh = { notifyDatasetChanged() },
itemClick = { handleConversationClick(it) } itemClick = { handleConversationClick(it) }
) )
conversations_list.adapter = currAdapter binding.conversationsList.adapter = currAdapter
if (areSystemAnimationsEnabled) { if (areSystemAnimationsEnabled) {
conversations_list.scheduleLayoutAnimation() binding.conversationsList.scheduleLayoutAnimation()
} }
} }
return currAdapter as RecycleBinConversationsAdapter return currAdapter as RecycleBinConversationsAdapter
@ -135,9 +139,9 @@ class RecycleBinConversationsActivity : SimpleActivity() {
} }
private fun showOrHidePlaceholder(show: Boolean) { private fun showOrHidePlaceholder(show: Boolean) {
conversations_fastscroller.beGoneIf(show) binding.conversationsFastscroller.beGoneIf(show)
no_conversations_placeholder.beVisibleIf(show) binding.noConversationsPlaceholder.beVisibleIf(show)
no_conversations_placeholder.text = getString(R.string.no_conversations_found) binding.noConversationsPlaceholder.text = getString(R.string.no_conversations_found)
} }
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")

View File

@ -12,13 +12,13 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.databinding.ActivitySettingsBinding
import com.simplemobiletools.smsmessenger.dialogs.ExportMessagesDialog import com.simplemobiletools.smsmessenger.dialogs.ExportMessagesDialog
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.extensions.emptyMessagesRecycleBin import com.simplemobiletools.smsmessenger.extensions.emptyMessagesRecycleBin
import com.simplemobiletools.smsmessenger.extensions.messagesDB import com.simplemobiletools.smsmessenger.extensions.messagesDB
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.models.* import com.simplemobiletools.smsmessenger.models.*
import kotlinx.android.synthetic.main.activity_settings.*
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import java.util.* import java.util.*
@ -30,18 +30,25 @@ class SettingsActivity : SimpleActivity() {
private val messagesFileType = "application/json" private val messagesFileType = "application/json"
private val messageImportFileTypes = listOf("application/json", "application/xml", "text/xml") private val messageImportFileTypes = listOf("application/json", "application/xml", "text/xml")
private val binding by viewBinding(ActivitySettingsBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings) setContentView(binding.root)
updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = true, useTopSearchMenu = false) updateMaterialActivityViews(
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar) mainCoordinatorLayout = binding.settingsCoordinator,
nestedView = binding.settingsHolder,
useTransparentNavigation = true,
useTopSearchMenu = false
)
setupMaterialScrollListener(scrollingView = binding.settingsNestedScrollview, toolbar = binding.settingsToolbar)
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(settings_toolbar, NavigationIcon.Arrow) setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
setupPurchaseThankYou() setupPurchaseThankYou()
setupCustomizeColors() setupCustomizeColors()
@ -65,20 +72,20 @@ class SettingsActivity : SimpleActivity() {
setupAppPasswordProtection() setupAppPasswordProtection()
setupMessagesExport() setupMessagesExport()
setupMessagesImport() setupMessagesImport()
updateTextColors(settings_nested_scrollview) updateTextColors(binding.settingsNestedScrollview)
if (blockedNumbersAtPause != -1 && blockedNumbersAtPause != getBlockedNumbers().hashCode()) { if (blockedNumbersAtPause != -1 && blockedNumbersAtPause != getBlockedNumbers().hashCode()) {
refreshMessages() refreshMessages()
} }
arrayOf( arrayOf(
settings_color_customization_section_label, binding.settingsColorCustomizationSectionLabel,
settings_general_settings_label, binding.settingsGeneralSettingsLabel,
settings_outgoing_messages_label, binding.settingsOutgoingMessagesLabel,
settings_notifications_label, binding.settingsNotificationsLabel,
settings_recycle_bin_label, binding.settingsEmptyRecycleBinLabel,
settings_security_label, binding.settingsSecurityLabel,
settings_migrating_label binding.settingsMigratingLabel
).forEach { ).forEach {
it.setTextColor(getProperPrimaryColor()) it.setTextColor(getProperPrimaryColor())
} }
@ -98,7 +105,7 @@ class SettingsActivity : SimpleActivity() {
} }
private fun setupMessagesExport() { private fun setupMessagesExport() {
settings_export_messages_holder.setOnClickListener { binding.settingsExportMessagesHolder.setOnClickListener {
ExportMessagesDialog(this) { fileName -> ExportMessagesDialog(this) { fileName ->
saveDocument.launch(fileName) saveDocument.launch(fileName)
} }
@ -106,7 +113,7 @@ class SettingsActivity : SimpleActivity() {
} }
private fun setupMessagesImport() { private fun setupMessagesImport() {
settings_import_messages_holder.setOnClickListener { binding.settingsImportMessagesHolder.setOnClickListener {
getContent.launch(messageImportFileTypes.toTypedArray()) getContent.launch(messageImportFileTypes.toTypedArray())
} }
} }
@ -139,87 +146,87 @@ class SettingsActivity : SimpleActivity() {
blockedNumbersAtPause = getBlockedNumbers().hashCode() blockedNumbersAtPause = getBlockedNumbers().hashCode()
} }
private fun setupPurchaseThankYou() { private fun setupPurchaseThankYou() = binding.apply {
settings_purchase_thank_you_holder.beGoneIf(isOrWasThankYouInstalled()) settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
settings_purchase_thank_you_holder.setOnClickListener { settingsPurchaseThankYouHolder.setOnClickListener {
launchPurchaseThankYouIntent() launchPurchaseThankYouIntent()
} }
} }
private fun setupCustomizeColors() { private fun setupCustomizeColors() = binding.apply {
settings_color_customization_label.text = getCustomizeColorsString() settingsColorCustomizationLabel.text = getCustomizeColorsString()
settings_color_customization_holder.setOnClickListener { settingsColorCustomizationHolder.setOnClickListener {
handleCustomizeColorsClick() handleCustomizeColorsClick()
} }
} }
private fun setupCustomizeNotifications() { private fun setupCustomizeNotifications() = binding.apply {
settings_customize_notifications_holder.beVisibleIf(isOreoPlus()) settingsCustomizeNotificationsHolder.beVisibleIf(isOreoPlus())
settings_customize_notifications_holder.setOnClickListener { settingsCustomizeNotificationsHolder.setOnClickListener {
launchCustomizeNotificationsIntent() launchCustomizeNotificationsIntent()
} }
} }
private fun setupUseEnglish() { private fun setupUseEnglish() = binding.apply {
settings_use_english_holder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus()) settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settings_use_english.isChecked = config.useEnglish settingsUseEnglish.isChecked = config.useEnglish
settings_use_english_holder.setOnClickListener { settingsUseEnglishHolder.setOnClickListener {
settings_use_english.toggle() settingsUseEnglish.toggle()
config.useEnglish = settings_use_english.isChecked config.useEnglish = settingsUseEnglish.isChecked
exitProcess(0) exitProcess(0)
} }
} }
private fun setupLanguage() { private fun setupLanguage() = binding.apply {
settings_language.text = Locale.getDefault().displayLanguage settingsLanguage.text = Locale.getDefault().displayLanguage
settings_language_holder.beVisibleIf(isTiramisuPlus()) settingsLanguageHolder.beVisibleIf(isTiramisuPlus())
settings_language_holder.setOnClickListener { settingsLanguageHolder.setOnClickListener {
launchChangeAppLanguageIntent() launchChangeAppLanguageIntent()
} }
} }
// support for device-wise blocking came on Android 7, rely only on that // support for device-wise blocking came on Android 7, rely only on that
@TargetApi(Build.VERSION_CODES.N) @TargetApi(Build.VERSION_CODES.N)
private fun setupManageBlockedNumbers() { private fun setupManageBlockedNumbers() = binding.apply {
settings_manage_blocked_numbers.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers) settingsManageBlockedNumbers.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers)
settings_manage_blocked_numbers_holder.beVisibleIf(isNougatPlus()) settingsManageBlockedNumbersHolder.beVisibleIf(isNougatPlus())
settings_manage_blocked_numbers_holder.setOnClickListener { settingsManageBlockedNumbersHolder.setOnClickListener {
if (isOrWasThankYouInstalled()) { if (isOrWasThankYouInstalled()) {
Intent(this, ManageBlockedNumbersActivity::class.java).apply { Intent(this@SettingsActivity, ManageBlockedNumbersActivity::class.java).apply {
startActivity(this) startActivity(this)
} }
} else { } else {
FeatureLockedDialog(this) { } FeatureLockedDialog(this@SettingsActivity) { }
} }
} }
} }
private fun setupManageBlockedKeywords() { private fun setupManageBlockedKeywords() = binding.apply {
settings_manage_blocked_keywords.text = addLockedLabelIfNeeded(R.string.manage_blocked_keywords) settingsManageBlockedKeywords.text = addLockedLabelIfNeeded(R.string.manage_blocked_keywords)
settings_manage_blocked_keywords_holder.setOnClickListener { settingsManageBlockedKeywordsHolder.setOnClickListener {
if (isOrWasThankYouInstalled()) { if (isOrWasThankYouInstalled()) {
Intent(this, ManageBlockedKeywordsActivity::class.java).apply { Intent(this@SettingsActivity, ManageBlockedKeywordsActivity::class.java).apply {
startActivity(this) startActivity(this)
} }
} else { } else {
FeatureLockedDialog(this) { } FeatureLockedDialog(this@SettingsActivity) { }
} }
} }
} }
private fun setupChangeDateTimeFormat() { private fun setupChangeDateTimeFormat() = binding.apply {
settings_change_date_time_format_holder.setOnClickListener { settingsChangeDateTimeFormatHolder.setOnClickListener {
ChangeDateTimeFormatDialog(this) { ChangeDateTimeFormatDialog(this@SettingsActivity) {
refreshMessages() refreshMessages()
} }
} }
} }
private fun setupFontSize() { private fun setupFontSize() = binding.apply {
settings_font_size.text = getFontSizeText() settingsFontSize.text = getFontSizeText()
settings_font_size_holder.setOnClickListener { settingsFontSizeHolder.setOnClickListener {
val items = arrayListOf( val items = arrayListOf(
RadioItem(FONT_SIZE_SMALL, getString(R.string.small)), RadioItem(FONT_SIZE_SMALL, getString(R.string.small)),
RadioItem(FONT_SIZE_MEDIUM, getString(R.string.medium)), RadioItem(FONT_SIZE_MEDIUM, getString(R.string.medium)),
@ -229,62 +236,62 @@ class SettingsActivity : SimpleActivity() {
RadioGroupDialog(this@SettingsActivity, items, config.fontSize) { RadioGroupDialog(this@SettingsActivity, items, config.fontSize) {
config.fontSize = it as Int config.fontSize = it as Int
settings_font_size.text = getFontSizeText() settingsFontSize.text = getFontSizeText()
} }
} }
} }
private fun setupShowCharacterCounter() { private fun setupShowCharacterCounter() = binding.apply {
settings_show_character_counter.isChecked = config.showCharacterCounter settingsShowCharacterCounter.isChecked = config.showCharacterCounter
settings_show_character_counter_holder.setOnClickListener { settingsShowCharacterCounterHolder.setOnClickListener {
settings_show_character_counter.toggle() settingsShowCharacterCounter.toggle()
config.showCharacterCounter = settings_show_character_counter.isChecked config.showCharacterCounter = settingsShowCharacterCounter.isChecked
} }
} }
private fun setupUseSimpleCharacters() { private fun setupUseSimpleCharacters() = binding.apply {
settings_use_simple_characters.isChecked = config.useSimpleCharacters settingsUseSimpleCharacters.isChecked = config.useSimpleCharacters
settings_use_simple_characters_holder.setOnClickListener { settingsUseSimpleCharactersHolder.setOnClickListener {
settings_use_simple_characters.toggle() settingsUseSimpleCharacters.toggle()
config.useSimpleCharacters = settings_use_simple_characters.isChecked config.useSimpleCharacters = settingsUseSimpleCharacters.isChecked
} }
} }
private fun setupSendOnEnter() { private fun setupSendOnEnter() = binding.apply {
settings_send_on_enter.isChecked = config.sendOnEnter settingsSendOnEnter.isChecked = config.sendOnEnter
settings_send_on_enter_holder.setOnClickListener { settingsSendOnEnterHolder.setOnClickListener {
settings_send_on_enter.toggle() settingsSendOnEnter.toggle()
config.sendOnEnter = settings_send_on_enter.isChecked config.sendOnEnter = settingsSendOnEnter.isChecked
} }
} }
private fun setupEnableDeliveryReports() { private fun setupEnableDeliveryReports() = binding.apply {
settings_enable_delivery_reports.isChecked = config.enableDeliveryReports settingsEnableDeliveryReports.isChecked = config.enableDeliveryReports
settings_enable_delivery_reports_holder.setOnClickListener { settingsEnableDeliveryReportsHolder.setOnClickListener {
settings_enable_delivery_reports.toggle() settingsEnableDeliveryReports.toggle()
config.enableDeliveryReports = settings_enable_delivery_reports.isChecked config.enableDeliveryReports = settingsEnableDeliveryReports.isChecked
} }
} }
private fun setupSendLongMessageAsMMS() { private fun setupSendLongMessageAsMMS() = binding.apply {
settings_send_long_message_mms.isChecked = config.sendLongMessageMMS settingsSendLongMessageMms.isChecked = config.sendLongMessageMMS
settings_send_long_message_mms_holder.setOnClickListener { settingsSendLongMessageMmsHolder.setOnClickListener {
settings_send_long_message_mms.toggle() settingsSendLongMessageMms.toggle()
config.sendLongMessageMMS = settings_send_long_message_mms.isChecked config.sendLongMessageMMS = settingsSendLongMessageMms.isChecked
} }
} }
private fun setupGroupMessageAsMMS() { private fun setupGroupMessageAsMMS() = binding.apply {
settings_send_group_message_mms.isChecked = config.sendGroupMessageMMS settingsSendGroupMessageMms.isChecked = config.sendGroupMessageMMS
settings_send_group_message_mms_holder.setOnClickListener { settingsSendGroupMessageMmsHolder.setOnClickListener {
settings_send_group_message_mms.toggle() settingsSendGroupMessageMms.toggle()
config.sendGroupMessageMMS = settings_send_group_message_mms.isChecked config.sendGroupMessageMMS = settingsSendGroupMessageMms.isChecked
} }
} }
private fun setupLockScreenVisibility() { private fun setupLockScreenVisibility() = binding.apply {
settings_lock_screen_visibility.text = getLockScreenVisibilityText() settingsLockScreenVisibility.text = getLockScreenVisibilityText()
settings_lock_screen_visibility_holder.setOnClickListener { settingsLockScreenVisibilityHolder.setOnClickListener {
val items = arrayListOf( val items = arrayListOf(
RadioItem(LOCK_SCREEN_SENDER_MESSAGE, getString(R.string.sender_and_message)), RadioItem(LOCK_SCREEN_SENDER_MESSAGE, getString(R.string.sender_and_message)),
RadioItem(LOCK_SCREEN_SENDER, getString(R.string.sender_only)), RadioItem(LOCK_SCREEN_SENDER, getString(R.string.sender_only)),
@ -293,7 +300,7 @@ class SettingsActivity : SimpleActivity() {
RadioGroupDialog(this@SettingsActivity, items, config.lockScreenVisibilitySetting) { RadioGroupDialog(this@SettingsActivity, items, config.lockScreenVisibilitySetting) {
config.lockScreenVisibilitySetting = it as Int config.lockScreenVisibilitySetting = it as Int
settings_lock_screen_visibility.text = getLockScreenVisibilityText() settingsLockScreenVisibility.text = getLockScreenVisibilityText()
} }
} }
} }
@ -306,9 +313,9 @@ class SettingsActivity : SimpleActivity() {
} }
) )
private fun setupMMSFileSizeLimit() { private fun setupMMSFileSizeLimit() = binding.apply {
settings_mms_file_size_limit.text = getMMSFileLimitText() settingsMmsFileSizeLimit.text = getMMSFileLimitText()
settings_mms_file_size_limit_holder.setOnClickListener { settingsMmsFileSizeLimitHolder.setOnClickListener {
val items = arrayListOf( val items = arrayListOf(
RadioItem(7, getString(R.string.mms_file_size_limit_none), FILE_SIZE_NONE), RadioItem(7, getString(R.string.mms_file_size_limit_none), FILE_SIZE_NONE),
RadioItem(6, getString(R.string.mms_file_size_limit_2mb), FILE_SIZE_2_MB), RadioItem(6, getString(R.string.mms_file_size_limit_2mb), FILE_SIZE_2_MB),
@ -322,58 +329,58 @@ class SettingsActivity : SimpleActivity() {
val checkedItemId = items.find { it.value == config.mmsFileSizeLimit }?.id ?: 7 val checkedItemId = items.find { it.value == config.mmsFileSizeLimit }?.id ?: 7
RadioGroupDialog(this@SettingsActivity, items, checkedItemId) { RadioGroupDialog(this@SettingsActivity, items, checkedItemId) {
config.mmsFileSizeLimit = it as Long config.mmsFileSizeLimit = it as Long
settings_mms_file_size_limit.text = getMMSFileLimitText() settingsMmsFileSizeLimit.text = getMMSFileLimitText()
} }
} }
} }
private fun setupUseRecycleBin() { private fun setupUseRecycleBin() = binding.apply {
updateRecycleBinButtons() updateRecycleBinButtons()
settings_use_recycle_bin.isChecked = config.useRecycleBin settingsUseRecycleBin.isChecked = config.useRecycleBin
settings_use_recycle_bin_holder.setOnClickListener { settingsUseRecycleBinHolder.setOnClickListener {
settings_use_recycle_bin.toggle() settingsUseRecycleBin.toggle()
config.useRecycleBin = settings_use_recycle_bin.isChecked config.useRecycleBin = settingsUseRecycleBin.isChecked
updateRecycleBinButtons() updateRecycleBinButtons()
} }
} }
private fun updateRecycleBinButtons() { private fun updateRecycleBinButtons() = binding.apply {
settings_empty_recycle_bin_holder.beVisibleIf(config.useRecycleBin) settingsEmptyRecycleBinHolder.beVisibleIf(config.useRecycleBin)
} }
private fun setupEmptyRecycleBin() { private fun setupEmptyRecycleBin() = binding.apply {
ensureBackgroundThread { ensureBackgroundThread {
recycleBinMessages = messagesDB.getArchivedCount() recycleBinMessages = messagesDB.getArchivedCount()
runOnUiThread { runOnUiThread {
settings_empty_recycle_bin_size.text = settingsEmptyRecycleBinSize.text =
resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages) resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages)
} }
} }
settings_empty_recycle_bin_holder.setOnClickListener { settingsEmptyRecycleBinHolder.setOnClickListener {
if (recycleBinMessages == 0) { if (recycleBinMessages == 0) {
toast(R.string.recycle_bin_empty) toast(R.string.recycle_bin_empty)
} else { } else {
ConfirmationDialog(this, "", R.string.empty_recycle_bin_messages_confirmation, R.string.yes, R.string.no) { ConfirmationDialog(this@SettingsActivity, "", R.string.empty_recycle_bin_messages_confirmation, R.string.yes, R.string.no) {
ensureBackgroundThread { ensureBackgroundThread {
emptyMessagesRecycleBin() emptyMessagesRecycleBin()
} }
recycleBinMessages = 0 recycleBinMessages = 0
settings_empty_recycle_bin_size.text = settingsEmptyRecycleBinSize.text =
resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages) resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages)
} }
} }
} }
} }
private fun setupAppPasswordProtection() { private fun setupAppPasswordProtection() = binding.apply {
settings_app_password_protection.isChecked = config.isAppPasswordProtectionOn settingsAppPasswordProtection.isChecked = config.isAppPasswordProtectionOn
settings_app_password_protection_holder.setOnClickListener { settingsAppPasswordProtectionHolder.setOnClickListener {
val tabToShow = if (config.isAppPasswordProtectionOn) config.appProtectionType else SHOW_ALL_TABS val tabToShow = if (config.isAppPasswordProtectionOn) config.appProtectionType else SHOW_ALL_TABS
SecurityDialog(this, config.appPasswordHash, tabToShow) { hash, type, success -> SecurityDialog(this@SettingsActivity, config.appPasswordHash, tabToShow) { hash, type, success ->
if (success) { if (success) {
val hasPasswordProtection = config.isAppPasswordProtectionOn val hasPasswordProtection = config.isAppPasswordProtectionOn
settings_app_password_protection.isChecked = !hasPasswordProtection settingsAppPasswordProtection.isChecked = !hasPasswordProtection
config.isAppPasswordProtectionOn = !hasPasswordProtection config.isAppPasswordProtectionOn = !hasPasswordProtection
config.appPasswordHash = if (hasPasswordProtection) "" else hash config.appPasswordHash = if (hasPasswordProtection) "" else hash
config.appProtectionType = type config.appProtectionType = type
@ -381,7 +388,7 @@ class SettingsActivity : SimpleActivity() {
if (config.isAppPasswordProtectionOn) { if (config.isAppPasswordProtectionOn) {
val confirmationTextId = if (config.appProtectionType == PROTECTION_FINGERPRINT) val confirmationTextId = if (config.appProtectionType == PROTECTION_FINGERPRINT)
R.string.fingerprint_setup_successfully else R.string.protection_setup_successfully R.string.fingerprint_setup_successfully else R.string.protection_setup_successfully
ConfirmationDialog(this, "", confirmationTextId, R.string.ok, 0) { } ConfirmationDialog(this@SettingsActivity, "", confirmationTextId, R.string.ok, 0) { }
} }
} }
} }

View File

@ -58,6 +58,9 @@ import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.AttachmentsAdapter import com.simplemobiletools.smsmessenger.adapters.AttachmentsAdapter
import com.simplemobiletools.smsmessenger.adapters.AutoCompleteTextViewAdapter import com.simplemobiletools.smsmessenger.adapters.AutoCompleteTextViewAdapter
import com.simplemobiletools.smsmessenger.adapters.ThreadAdapter import com.simplemobiletools.smsmessenger.adapters.ThreadAdapter
import com.simplemobiletools.smsmessenger.databinding.ActivityThreadBinding
import com.simplemobiletools.smsmessenger.databinding.ItemSelectedContactBinding
import com.simplemobiletools.smsmessenger.databinding.LayoutThreadSendMessageHolderBinding
import com.simplemobiletools.smsmessenger.dialogs.InvalidNumberDialog import com.simplemobiletools.smsmessenger.dialogs.InvalidNumberDialog
import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog
import com.simplemobiletools.smsmessenger.dialogs.ScheduleMessageDialog import com.simplemobiletools.smsmessenger.dialogs.ScheduleMessageDialog
@ -66,11 +69,6 @@ import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.messaging.* import com.simplemobiletools.smsmessenger.messaging.*
import com.simplemobiletools.smsmessenger.models.* import com.simplemobiletools.smsmessenger.models.*
import com.simplemobiletools.smsmessenger.models.ThreadItem.* import com.simplemobiletools.smsmessenger.models.ThreadItem.*
import kotlinx.android.synthetic.main.activity_thread.*
import kotlinx.android.synthetic.main.item_selected_contact.view.*
import kotlinx.android.synthetic.main.layout_attachment_picker.*
import kotlinx.android.synthetic.main.layout_invalid_short_code_info.*
import kotlinx.android.synthetic.main.layout_thread_send_message_holder.*
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
@ -114,6 +112,9 @@ class ThreadActivity : SimpleActivity() {
private var isAttachmentPickerVisible = false private var isAttachmentPickerVisible = false
private val binding by viewBinding(ActivityThreadBinding::inflate)
private lateinit var messageHolderBinding: LayoutThreadSendMessageHolderBinding
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent) super.onNewIntent(intent)
finish() finish()
@ -123,12 +124,13 @@ class ThreadActivity : SimpleActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_thread) messageHolderBinding = binding.threadSendMessageHolder
setContentView(binding.root)
setupOptionsMenu() setupOptionsMenu()
refreshMenuItems() refreshMenuItems()
updateMaterialActivityViews(thread_coordinator, null, useTransparentNavigation = false, useTopSearchMenu = false) updateMaterialActivityViews(binding.threadCoordinator, null, useTransparentNavigation = false, useTopSearchMenu = false)
setupMaterialScrollListener(null, thread_toolbar) setupMaterialScrollListener(null, binding.threadToolbar)
val extras = intent.extras val extras = intent.extras
if (extras == null) { if (extras == null) {
@ -140,7 +142,7 @@ class ThreadActivity : SimpleActivity() {
clearAllMessagesIfNeeded() clearAllMessagesIfNeeded()
threadId = intent.getLongExtra(THREAD_ID, 0L) threadId = intent.getLongExtra(THREAD_ID, 0L)
intent.getStringExtra(THREAD_TITLE)?.let { intent.getStringExtra(THREAD_TITLE)?.let {
thread_toolbar.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) wasProtectionHandled = intent.getBooleanExtra(WAS_PROTECTION_HANDLED, false)
@ -171,11 +173,11 @@ class ThreadActivity : SimpleActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(thread_toolbar, NavigationIcon.Arrow, statusBarColor = getProperBackgroundColor()) setupToolbar(binding.threadToolbar, NavigationIcon.Arrow, statusBarColor = getProperBackgroundColor())
val smsDraft = getSmsDraft(threadId) val smsDraft = getSmsDraft(threadId)
if (smsDraft != null) { if (smsDraft != null) {
thread_type_message.setText(smsDraft) messageHolderBinding.threadTypeMessage.setText(smsDraft)
} }
isActivityVisible = true isActivityVisible = true
@ -192,16 +194,16 @@ class ThreadActivity : SimpleActivity() {
} }
val bottomBarColor = getBottomBarColor() val bottomBarColor = getBottomBarColor()
thread_send_message_holder.setBackgroundColor(bottomBarColor) messageHolderBinding.root.setBackgroundColor(bottomBarColor)
reply_disabled_info_holder.setBackgroundColor(bottomBarColor) binding.shortCodeHolder.root.setBackgroundColor(bottomBarColor)
updateNavigationBarColor(bottomBarColor) updateNavigationBarColor(bottomBarColor)
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
if (thread_type_message.value != "" && getAttachmentSelections().isEmpty()) { if (messageHolderBinding.threadTypeMessage.value != "" && getAttachmentSelections().isEmpty()) {
saveSmsDraft(thread_type_message.value, threadId) saveSmsDraft(messageHolderBinding.threadTypeMessage.value, threadId)
} else { } else {
deleteSmsDraft(threadId) deleteSmsDraft(threadId)
} }
@ -212,7 +214,7 @@ class ThreadActivity : SimpleActivity() {
override fun onBackPressed() { override fun onBackPressed() {
isAttachmentPickerVisible = false isAttachmentPickerVisible = false
if (attachment_picker_holder.isVisible()) { if (messageHolderBinding.attachmentPickerHolder.isVisible()) {
hideAttachmentPicker() hideAttachmentPicker()
} else { } else {
super.onBackPressed() super.onBackPressed()
@ -249,7 +251,7 @@ class ThreadActivity : SimpleActivity() {
private fun refreshMenuItems() { private fun refreshMenuItems() {
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
thread_toolbar.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 findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin
@ -270,7 +272,7 @@ class ThreadActivity : SimpleActivity() {
} }
private fun setupOptionsMenu() { private fun setupOptionsMenu() {
thread_toolbar.setOnMenuItemClickListener { menuItem -> binding.threadToolbar.setOnMenuItemClickListener { menuItem ->
if (participants.isEmpty()) { if (participants.isEmpty()) {
return@setOnMenuItemClickListener true return@setOnMenuItemClickListener true
} }
@ -339,7 +341,7 @@ class ThreadActivity : SimpleActivity() {
runOnUiThread { runOnUiThread {
if (messages.isEmpty()) { if (messages.isEmpty()) {
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
thread_type_message.requestFocus() messageHolderBinding.threadTypeMessage.requestFocus()
} }
setupThreadTitle() setupThreadTitle()
@ -426,18 +428,18 @@ class ThreadActivity : SimpleActivity() {
} }
private fun getOrCreateThreadAdapter(): ThreadAdapter { private fun getOrCreateThreadAdapter(): ThreadAdapter {
var currAdapter = thread_messages_list.adapter var currAdapter = binding.threadMessagesList.adapter
if (currAdapter == null) { if (currAdapter == null) {
currAdapter = ThreadAdapter( currAdapter = ThreadAdapter(
activity = this, activity = this,
recyclerView = thread_messages_list, 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) }
) )
thread_messages_list.adapter = currAdapter binding.threadMessagesList.adapter = currAdapter
thread_messages_list.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener { binding.threadMessagesList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
override fun updateBottom() {} override fun updateBottom() {}
override fun updateTop() { override fun updateTop() {
@ -454,7 +456,7 @@ class ThreadActivity : SimpleActivity() {
runOnUiThread { runOnUiThread {
refreshMenuItems() refreshMenuItems()
getOrCreateThreadAdapter().apply { getOrCreateThreadAdapter().apply {
val layoutManager = thread_messages_list.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
@ -466,23 +468,23 @@ class ThreadActivity : SimpleActivity() {
contacts.addAll(privateContacts) contacts.addAll(privateContacts)
runOnUiThread { runOnUiThread {
val adapter = AutoCompleteTextViewAdapter(this, contacts) val adapter = AutoCompleteTextViewAdapter(this, contacts)
add_contact_or_number.setAdapter(adapter) binding.addContactOrNumber.setAdapter(adapter)
add_contact_or_number.imeOptions = EditorInfo.IME_ACTION_NEXT binding.addContactOrNumber.imeOptions = EditorInfo.IME_ACTION_NEXT
add_contact_or_number.setOnItemClickListener { _, _, position, _ -> binding.addContactOrNumber.setOnItemClickListener { _, _, position, _ ->
val currContacts = (add_contact_or_number.adapter as AutoCompleteTextViewAdapter).resultList val currContacts = (binding.addContactOrNumber.adapter as AutoCompleteTextViewAdapter).resultList
val selectedContact = currContacts[position] val selectedContact = currContacts[position]
addSelectedContact(selectedContact) addSelectedContact(selectedContact)
} }
add_contact_or_number.onTextChangeListener { binding.addContactOrNumber.onTextChangeListener {
confirm_inserted_number.beVisibleIf(it.length > 2) binding.confirmInsertedNumber.beVisibleIf(it.length > 2)
} }
} }
} }
runOnUiThread { runOnUiThread {
confirm_inserted_number?.setOnClickListener { binding.confirmInsertedNumber.setOnClickListener {
val number = add_contact_or_number.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(number.hashCode(), number.hashCode(), number, "", arrayListOf(phoneNumber), ArrayList(), ArrayList())
addSelectedContact(contact) addSelectedContact(contact)
@ -493,21 +495,21 @@ class ThreadActivity : SimpleActivity() {
private fun scrollToBottom() { private fun scrollToBottom() {
val position = getOrCreateThreadAdapter().currentList.lastIndex val position = getOrCreateThreadAdapter().currentList.lastIndex
if (position >= 0) { if (position >= 0) {
thread_messages_list.smoothScrollToPosition(position) binding.threadMessagesList.smoothScrollToPosition(position)
} }
} }
private fun setupScrollFab() { private fun setupScrollFab() {
thread_messages_list.addOnScrollListener(object : RecyclerView.OnScrollListener() { binding.threadMessagesList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
val layoutManager = thread_messages_list.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) {
scroll_to_bottom_fab.hide() binding.scrollToBottomFab.hide()
} else { } else {
scroll_to_bottom_fab.show() binding.scrollToBottomFab.show()
} }
} }
}) })
@ -517,7 +519,7 @@ class ThreadActivity : SimpleActivity() {
when { when {
any is Message && any.isScheduled -> showScheduledMessageInfo(any) any is Message && any.isScheduled -> showScheduledMessageInfo(any)
any is ThreadError -> { any is ThreadError -> {
thread_type_message.setText(any.messageText) messageHolderBinding.threadTypeMessage.setText(any.messageText)
messageToResend = any.messageId messageToResend = any.messageId
} }
} }
@ -616,7 +618,7 @@ class ThreadActivity : SimpleActivity() {
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) {
thread_messages_list.smoothScrollToPosition(index) binding.threadMessagesList.smoothScrollToPosition(index)
} }
} }
@ -635,39 +637,41 @@ class ThreadActivity : SimpleActivity() {
} }
} }
private fun setupButtons() { private fun setupButtons() = binding.apply {
updateTextColors(thread_holder) updateTextColors(threadHolder)
val textColor = getProperTextColor() val textColor = getProperTextColor()
thread_send_message.apply {
messageHolderBinding.apply {
threadSendMessage.apply {
setTextColor(textColor) setTextColor(textColor)
compoundDrawables.forEach { compoundDrawables.forEach {
it?.applyColorFilter(textColor) it?.applyColorFilter(textColor)
} }
} }
confirm_manage_contacts.applyColorFilter(textColor) confirmManageContacts.applyColorFilter(textColor)
thread_add_attachment.applyColorFilter(textColor) threadAddAttachment.applyColorFilter(textColor)
val properPrimaryColor = getProperPrimaryColor() val properPrimaryColor = getProperPrimaryColor()
thread_messages_fastscroller.updateColors(properPrimaryColor) threadMessagesFastscroller.updateColors(properPrimaryColor)
thread_character_counter.beVisibleIf(config.showCharacterCounter) threadCharacterCounter.beVisibleIf(config.showCharacterCounter)
thread_character_counter.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize()) threadCharacterCounter.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize())
thread_type_message.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize()) threadTypeMessage.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize())
thread_send_message.setOnClickListener { threadSendMessage.setOnClickListener {
sendMessage() sendMessage()
} }
thread_send_message.setOnLongClickListener { threadSendMessage.setOnLongClickListener {
if (!isScheduledMessage) { if (!isScheduledMessage) {
launchScheduleSendDialog() launchScheduleSendDialog()
} }
true true
} }
thread_send_message.isClickable = false threadSendMessage.isClickable = false
thread_type_message.onTextChangeListener { threadTypeMessage.onTextChangeListener {
messageToResend = null messageToResend = null
checkSendMessageAvailability() checkSendMessageAvailability()
val messageString = if (config.useSimpleCharacters) { val messageString = if (config.useSimpleCharacters) {
@ -676,14 +680,13 @@ class ThreadActivity : SimpleActivity() {
it it
} }
val messageLength = SmsMessage.calculateLength(messageString, false) val messageLength = SmsMessage.calculateLength(messageString, false)
thread_character_counter.text = "${messageLength[2]}/${messageLength[0]}" threadCharacterCounter.text = "${messageLength[2]}/${messageLength[0]}"
} }
if (config.sendOnEnter) { if (config.sendOnEnter) {
thread_type_message.inputType = EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES threadTypeMessage.inputType = EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
thread_type_message.imeOptions = EditorInfo.IME_ACTION_SEND threadTypeMessage.imeOptions = EditorInfo.IME_ACTION_SEND
threadTypeMessage.setOnEditorActionListener { _, action, _ ->
thread_type_message.setOnEditorActionListener { _, action, _ ->
if (action == EditorInfo.IME_ACTION_SEND) { if (action == EditorInfo.IME_ACTION_SEND) {
dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER)) dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER))
return@setOnEditorActionListener true return@setOnEditorActionListener true
@ -691,7 +694,7 @@ class ThreadActivity : SimpleActivity() {
false false
} }
thread_type_message.setOnKeyListener { _, keyCode, event -> threadTypeMessage.setOnKeyListener { _, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) { if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) {
sendMessage() sendMessage()
return@setOnKeyListener true return@setOnKeyListener true
@ -700,9 +703,9 @@ class ThreadActivity : SimpleActivity() {
} }
} }
confirm_manage_contacts.setOnClickListener { confirmManageContacts.setOnClickListener {
hideKeyboard() hideKeyboard()
thread_add_contacts.beGone() threadAddContacts.beGone()
val numbers = HashSet<String>() val numbers = HashSet<String>()
participants.forEach { contact -> participants.forEach { contact ->
@ -713,7 +716,7 @@ class ThreadActivity : SimpleActivity() {
val newThreadId = getThreadId(numbers) val newThreadId = getThreadId(numbers)
if (threadId != newThreadId) { if (threadId != newThreadId) {
hideKeyboard() hideKeyboard()
Intent(this, ThreadActivity::class.java).apply { Intent(this@ThreadActivity, ThreadActivity::class.java).apply {
putExtra(THREAD_ID, newThreadId) putExtra(THREAD_ID, newThreadId)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(this) startActivity(this)
@ -721,15 +724,15 @@ class ThreadActivity : SimpleActivity() {
} }
} }
thread_type_message.setText(intent.getStringExtra(THREAD_TEXT)) threadTypeMessage.setText(intent.getStringExtra(THREAD_TEXT))
thread_add_attachment.setOnClickListener { threadAddAttachment.setOnClickListener {
if (attachment_picker_holder.isVisible()) { if (attachmentPickerHolder.isVisible()) {
isAttachmentPickerVisible = false isAttachmentPickerVisible = false
WindowCompat.getInsetsController(window, thread_type_message).show(WindowInsetsCompat.Type.ime()) WindowCompat.getInsetsController(window, threadTypeMessage).show(WindowInsetsCompat.Type.ime())
} else { } else {
isAttachmentPickerVisible = true isAttachmentPickerVisible = true
showOrHideAttachmentPicker() showOrHideAttachmentPicker()
WindowCompat.getInsetsController(window, thread_type_message).hide(WindowInsetsCompat.Type.ime()) WindowCompat.getInsetsController(window, threadTypeMessage).hide(WindowInsetsCompat.Type.ime())
} }
window.decorView.requestApplyInsets() window.decorView.requestApplyInsets()
} }
@ -742,11 +745,12 @@ class ThreadActivity : SimpleActivity() {
addAttachment(it) addAttachment(it)
} }
} }
scroll_to_bottom_fab.setOnClickListener { scrollToBottomFab.setOnClickListener {
scrollToBottom() scrollToBottom()
} }
scroll_to_bottom_fab.backgroundTintList = ColorStateList.valueOf(getBottomBarColor()) scrollToBottomFab.backgroundTintList = ColorStateList.valueOf(getBottomBarColor())
scroll_to_bottom_fab.applyColorFilter(textColor) scrollToBottomFab.applyColorFilter(textColor)
}
setupScheduleSendUi() setupScheduleSendUi()
} }
@ -822,11 +826,11 @@ class ThreadActivity : SimpleActivity() {
private fun maybeDisableShortCodeReply() { private fun maybeDisableShortCodeReply() {
if (isSpecialNumber() && !isRecycleBin) { if (isSpecialNumber() && !isRecycleBin) {
thread_send_message_holder.beGone() messageHolderBinding.root.beGone()
reply_disabled_info_holder.beVisible() binding.shortCodeHolder.root.beVisible()
val textColor = getProperTextColor() val textColor = getProperTextColor()
reply_disabled_text.setTextColor(textColor) binding.shortCodeHolder.replyDisabledText.setTextColor(textColor)
reply_disabled_info.apply { binding.shortCodeHolder.replyDisabledInfo.apply {
applyColorFilter(textColor) applyColorFilter(textColor)
setOnClickListener { setOnClickListener {
InvalidNumberDialog( InvalidNumberDialog(
@ -843,7 +847,7 @@ class ThreadActivity : SimpleActivity() {
private fun setupThreadTitle() { private fun setupThreadTitle() {
val title = conversation?.title val title = conversation?.title
thread_toolbar.title = if (!title.isNullOrEmpty()) { binding.threadToolbar.title = if (!title.isNullOrEmpty()) {
title title
} else { } else {
participants.getThreadTitle() participants.getThreadTitle()
@ -875,15 +879,15 @@ class ThreadActivity : SimpleActivity() {
} }
currentSIMCardIndex = getProperSimIndex(availableSIMs, numbers) currentSIMCardIndex = getProperSimIndex(availableSIMs, numbers)
thread_select_sim_icon.applyColorFilter(getProperTextColor()) messageHolderBinding.threadSelectSimIcon.applyColorFilter(getProperTextColor())
thread_select_sim_icon.beVisible() messageHolderBinding.threadSelectSimIcon.beVisible()
thread_select_sim_number.beVisible() messageHolderBinding.threadSelectSimNumber.beVisible()
if (availableSIMCards.isNotEmpty()) { if (availableSIMCards.isNotEmpty()) {
thread_select_sim_icon.setOnClickListener { messageHolderBinding.threadSelectSimIcon.setOnClickListener {
currentSIMCardIndex = (currentSIMCardIndex + 1) % availableSIMCards.size currentSIMCardIndex = (currentSIMCardIndex + 1) % availableSIMCards.size
val currentSIMCard = availableSIMCards[currentSIMCardIndex] val currentSIMCard = availableSIMCards[currentSIMCardIndex]
thread_select_sim_number.text = currentSIMCard.id.toString() messageHolderBinding.threadSelectSimNumber.text = currentSIMCard.id.toString()
val currentSubscriptionId = currentSIMCard.subscriptionId val currentSubscriptionId = currentSIMCard.subscriptionId
numbers.forEach { numbers.forEach {
config.saveUseSIMIdAtNumber(it, currentSubscriptionId) config.saveUseSIMIdAtNumber(it, currentSubscriptionId)
@ -892,9 +896,9 @@ class ThreadActivity : SimpleActivity() {
} }
} }
thread_select_sim_number.setTextColor(getProperTextColor().getContrastColor()) messageHolderBinding.threadSelectSimNumber.setTextColor(getProperTextColor().getContrastColor())
try { try {
thread_select_sim_number.text = (availableSIMCards[currentSIMCardIndex].id).toString() messageHolderBinding.threadSelectSimNumber.text = (availableSIMCards[currentSIMCardIndex].id).toString()
} catch (e: Exception) { } catch (e: Exception) {
showErrorToast(e) showErrorToast(e)
} }
@ -1002,14 +1006,14 @@ class ThreadActivity : SimpleActivity() {
} }
private fun managePeople() { private fun managePeople() {
if (thread_add_contacts.isVisible()) { if (binding.threadAddContacts.isVisible()) {
hideKeyboard() hideKeyboard()
thread_add_contacts.beGone() binding.threadAddContacts.beGone()
} else { } else {
showSelectedContacts() showSelectedContacts()
thread_add_contacts.beVisible() binding.threadAddContacts.beVisible()
add_contact_or_number.requestFocus() binding.addContactOrNumber.requestFocus()
showKeyboard(add_contact_or_number) showKeyboard(binding.addContactOrNumber)
} }
} }
@ -1018,28 +1022,28 @@ class ThreadActivity : SimpleActivity() {
val views = ArrayList<View>() val views = ArrayList<View>()
participants.forEach { contact -> participants.forEach { contact ->
layoutInflater.inflate(R.layout.item_selected_contact, null).apply { ItemSelectedContactBinding.inflate(layoutInflater).apply {
val selectedContactBg = resources.getDrawable(R.drawable.item_selected_contact_background) val selectedContactBg = resources.getDrawable(R.drawable.item_selected_contact_background)
(selectedContactBg as LayerDrawable).findDrawableByLayerId(R.id.selected_contact_bg).applyColorFilter(properPrimaryColor) (selectedContactBg as LayerDrawable).findDrawableByLayerId(R.id.selected_contact_bg).applyColorFilter(properPrimaryColor)
selected_contact_holder.background = selectedContactBg selectedContactHolder.background = selectedContactBg
selected_contact_name.text = contact.name selectedContactName.text = contact.name
selected_contact_name.setTextColor(properPrimaryColor.getContrastColor()) selectedContactName.setTextColor(properPrimaryColor.getContrastColor())
selected_contact_remove.applyColorFilter(properPrimaryColor.getContrastColor()) selectedContactRemove.applyColorFilter(properPrimaryColor.getContrastColor())
selected_contact_remove.setOnClickListener { selectedContactRemove.setOnClickListener {
if (contact.rawId != participants.first().rawId) { if (contact.rawId != participants.first().rawId) {
removeSelectedContact(contact.rawId) removeSelectedContact(contact.rawId)
} }
} }
views.add(this) views.add(root)
} }
} }
showSelectedContact(views) showSelectedContact(views)
} }
private fun addSelectedContact(contact: SimpleContact) { private fun addSelectedContact(contact: SimpleContact) {
add_contact_or_number.setText("") binding.addContactOrNumber.setText("")
if (participants.map { it.rawId }.contains(contact.rawId)) { if (participants.map { it.rawId }.contains(contact.rawId)) {
return return
} }
@ -1234,7 +1238,7 @@ class ThreadActivity : SimpleActivity() {
} }
private fun getAttachmentsAdapter(): AttachmentsAdapter? { private fun getAttachmentsAdapter(): AttachmentsAdapter? {
val adapter = thread_attachments_recyclerview.adapter val adapter = messageHolderBinding.threadAttachmentsRecyclerview.adapter
return adapter as? AttachmentsAdapter return adapter as? AttachmentsAdapter
} }
@ -1268,17 +1272,17 @@ class ThreadActivity : SimpleActivity() {
if (adapter == null) { if (adapter == null) {
adapter = AttachmentsAdapter( adapter = AttachmentsAdapter(
activity = this, activity = this,
recyclerView = thread_attachments_recyclerview, recyclerView = messageHolderBinding.threadAttachmentsRecyclerview,
onAttachmentsRemoved = { onAttachmentsRemoved = {
thread_attachments_recyclerview.beGone() messageHolderBinding.threadAttachmentsRecyclerview.beGone()
checkSendMessageAvailability() checkSendMessageAvailability()
}, },
onReady = { checkSendMessageAvailability() } onReady = { checkSendMessageAvailability() }
) )
thread_attachments_recyclerview.adapter = adapter messageHolderBinding.threadAttachmentsRecyclerview.adapter = adapter
} }
thread_attachments_recyclerview.beVisible() messageHolderBinding.threadAttachmentsRecyclerview.beVisible()
val attachment = AttachmentSelection( val attachment = AttachmentSelection(
id = id, id = id,
uri = uri, uri = uri,
@ -1311,20 +1315,23 @@ class ThreadActivity : SimpleActivity() {
} }
private fun checkSendMessageAvailability() { private fun checkSendMessageAvailability() {
if (thread_type_message.text!!.isNotEmpty() || (getAttachmentSelections().isNotEmpty() && !getAttachmentSelections().any { it.isPending })) { messageHolderBinding.apply {
thread_send_message.isEnabled = true if (threadTypeMessage.text!!.isNotEmpty() || (getAttachmentSelections().isNotEmpty() && !getAttachmentSelections().any { it.isPending })) {
thread_send_message.isClickable = true threadSendMessage.isEnabled = true
thread_send_message.alpha = 0.9f threadSendMessage.isClickable = true
threadSendMessage.alpha = 0.9f
} else { } else {
thread_send_message.isEnabled = false threadSendMessage.isEnabled = false
thread_send_message.isClickable = false threadSendMessage.isClickable = false
thread_send_message.alpha = 0.4f threadSendMessage.alpha = 0.4f
} }
}
updateMessageType() updateMessageType()
} }
private fun sendMessage() { private fun sendMessage() {
var text = thread_type_message.value var text = messageHolderBinding.threadTypeMessage.value
if (text.isEmpty() && getAttachmentSelections().isEmpty()) { if (text.isEmpty() && getAttachmentSelections().isEmpty()) {
showErrorToast(getString(R.string.unknown_error_occurred)) showErrorToast(getString(R.string.unknown_error_occurred))
return return
@ -1403,7 +1410,7 @@ class ThreadActivity : SimpleActivity() {
} }
private fun clearCurrentMessage() { private fun clearCurrentMessage() {
thread_type_message.setText("") messageHolderBinding.threadTypeMessage.setText("")
getAttachmentsAdapter()?.clear() getAttachmentsAdapter()?.clear()
checkSendMessageAvailability() checkSendMessageAvailability()
} }
@ -1430,12 +1437,12 @@ class ThreadActivity : SimpleActivity() {
// show selected contacts, properly split to new lines when appropriate // show selected contacts, properly split to new lines when appropriate
// based on https://stackoverflow.com/a/13505029/1967672 // based on https://stackoverflow.com/a/13505029/1967672
private fun showSelectedContact(views: ArrayList<View>) { private fun showSelectedContact(views: ArrayList<View>) {
selected_contacts.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 = (selected_contacts.layoutParams as RelativeLayout.LayoutParams).leftMargin val sideMargin = (binding.selectedContacts.layoutParams as RelativeLayout.LayoutParams).leftMargin
val mediumMargin = resources.getDimension(R.dimen.medium_margin).toInt() val mediumMargin = resources.getDimension(R.dimen.medium_margin).toInt()
val parentWidth = realScreenSize.x - sideMargin * 2 val parentWidth = realScreenSize.x - sideMargin * 2
val firstRowWidth = parentWidth - resources.getDimension(R.dimen.normal_icon_size).toInt() + sideMargin / 2 val firstRowWidth = parentWidth - resources.getDimension(R.dimen.normal_icon_size).toInt() + sideMargin / 2
@ -1458,7 +1465,7 @@ class ThreadActivity : SimpleActivity() {
val checkWidth = if (isFirstRow) firstRowWidth else parentWidth val checkWidth = if (isFirstRow) firstRowWidth else parentWidth
if (widthSoFar >= checkWidth) { if (widthSoFar >= checkWidth) {
isFirstRow = false isFirstRow = false
selected_contacts.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
@ -1473,7 +1480,7 @@ class ThreadActivity : SimpleActivity() {
newLinearLayout.addView(layout) newLinearLayout.addView(layout)
} }
} }
selected_contacts.addView(newLinearLayout) binding.selectedContacts.addView(newLinearLayout)
} }
private fun removeSelectedContact(id: Int) { private fun removeSelectedContact(id: Int) {
@ -1579,13 +1586,13 @@ class ThreadActivity : SimpleActivity() {
} }
private fun updateMessageType() { private fun updateMessageType() {
val text = thread_type_message.text.toString() val text = messageHolderBinding.threadTypeMessage.text.toString()
val stringId = if (isMmsMessage(text)) { val stringId = if (isMmsMessage(text)) {
R.string.mms R.string.mms
} else { } else {
R.string.sms R.string.sms
} }
thread_send_message.setText(stringId) messageHolderBinding.threadSendMessage.setText(stringId)
} }
private fun showScheduledMessageInfo(message: Message) { private fun showScheduledMessageInfo(message: Message) {
@ -1620,7 +1627,7 @@ class ThreadActivity : SimpleActivity() {
private fun editScheduledMessage(message: Message) { private fun editScheduledMessage(message: Message) {
scheduledMessage = message scheduledMessage = message
clearCurrentMessage() clearCurrentMessage()
thread_type_message.setText(message.body) messageHolderBinding.threadTypeMessage.setText(message.body)
extractAttachments(message) extractAttachments(message)
scheduledDateTime = DateTime(message.millis()) scheduledDateTime = DateTime(message.millis())
showScheduleMessageDialog() showScheduleMessageDialog()
@ -1645,18 +1652,18 @@ class ThreadActivity : SimpleActivity() {
} }
} }
private fun setupScheduleSendUi() { private fun setupScheduleSendUi() = messageHolderBinding.apply {
val textColor = getProperTextColor() val textColor = getProperTextColor()
scheduled_message_holder.background.applyColorFilter(getProperPrimaryColor().darkenColor()) scheduledMessageHolder.background.applyColorFilter(getProperPrimaryColor().darkenColor())
scheduled_message_icon.applyColorFilter(textColor) scheduledMessageIcon.applyColorFilter(textColor)
scheduled_message_button.apply { scheduledMessageButton.apply {
setTextColor(textColor) setTextColor(textColor)
setOnClickListener { setOnClickListener {
launchScheduleSendDialog(scheduledDateTime) launchScheduleSendDialog(scheduledDateTime)
} }
} }
discard_scheduled_message.apply { discardScheduledMessage.apply {
applyColorFilter(textColor) applyColorFilter(textColor)
setOnClickListener { setOnClickListener {
hideScheduleSendUi() hideScheduleSendUi()
@ -1671,11 +1678,11 @@ class ThreadActivity : SimpleActivity() {
private fun showScheduleMessageDialog() { private fun showScheduleMessageDialog() {
isScheduledMessage = true isScheduledMessage = true
updateSendButtonDrawable() updateSendButtonDrawable()
scheduled_message_holder.beVisible() messageHolderBinding.scheduledMessageHolder.beVisible()
val dateTime = scheduledDateTime val dateTime = scheduledDateTime
val millis = dateTime.millis val millis = dateTime.millis
scheduled_message_button.text = if (dateTime.yearOfCentury().get() > DateTime.now().yearOfCentury().get()) { messageHolderBinding.scheduledMessageButton.text = if (dateTime.yearOfCentury().get() > DateTime.now().yearOfCentury().get()) {
millis.formatDate(this) millis.formatDate(this)
} else { } else {
val flags = FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or FORMAT_NO_YEAR val flags = FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or FORMAT_NO_YEAR
@ -1685,7 +1692,7 @@ class ThreadActivity : SimpleActivity() {
private fun hideScheduleSendUi() { private fun hideScheduleSendUi() {
isScheduledMessage = false isScheduledMessage = false
scheduled_message_holder.beGone() messageHolderBinding.scheduledMessageHolder.beGone()
updateSendButtonDrawable() updateSendButtonDrawable()
} }
@ -1697,7 +1704,7 @@ class ThreadActivity : SimpleActivity() {
} }
ResourcesCompat.getDrawable(resources, drawableResId, theme)?.apply { ResourcesCompat.getDrawable(resources, drawableResId, theme)?.apply {
applyColorFilter(getProperTextColor()) applyColorFilter(getProperTextColor())
thread_send_message.setCompoundDrawablesWithIntrinsicBounds(null, this, null, null) messageHolderBinding.threadSendMessage.setCompoundDrawablesWithIntrinsicBounds(null, this, null, null)
} }
} }
@ -1726,7 +1733,7 @@ class ThreadActivity : SimpleActivity() {
.map { Attachment(null, messageId, it.uri.toString(), it.mimetype, 0, 0, it.filename) } .map { Attachment(null, messageId, it.uri.toString(), it.mimetype, 0, 0, it.filename) }
.toArrayList() .toArrayList()
private fun setupAttachmentPickerView() { private fun setupAttachmentPickerView() = messageHolderBinding.attachmentPicker.apply {
val buttonColors = arrayOf( val buttonColors = arrayOf(
R.color.md_red_500, R.color.md_red_500,
R.color.md_brown_500, R.color.md_brown_500,
@ -1738,14 +1745,14 @@ class ThreadActivity : SimpleActivity() {
R.color.md_blue_500 R.color.md_blue_500
).map { ResourcesCompat.getColor(resources, it, theme) } ).map { ResourcesCompat.getColor(resources, it, theme) }
arrayOf( arrayOf(
choose_photo_icon, choosePhotoIcon,
choose_video_icon, chooseVideoIcon,
take_photo_icon, takePhotoIcon,
record_video_icon, recordVideoIcon,
record_audio_icon, recordAudioIcon,
pick_file_icon, pickFileIcon,
pick_contact_icon, pickContactIcon,
schedule_message_icon scheduleMessageIcon
).forEachIndexed { index, icon -> ).forEachIndexed { index, icon ->
val iconColor = buttonColors[index] val iconColor = buttonColors[index]
icon.background.applyColorFilter(iconColor) icon.background.applyColorFilter(iconColor)
@ -1754,38 +1761,38 @@ class ThreadActivity : SimpleActivity() {
val textColor = getProperTextColor() val textColor = getProperTextColor()
arrayOf( arrayOf(
choose_photo_text, choosePhotoText,
choose_video_text, chooseVideoText,
take_photo_text, takePhotoText,
record_video_text, recordVideoText,
record_audio_text, recordAudioText,
pick_file_text, pickFileText,
pick_contact_text, pickContactText,
schedule_message_text scheduleMessageText
).forEach { it.setTextColor(textColor) } ).forEach { it.setTextColor(textColor) }
choose_photo.setOnClickListener { choosePhoto.setOnClickListener {
launchGetContentIntent(arrayOf("image/*"), PICK_PHOTO_INTENT) launchGetContentIntent(arrayOf("image/*"), PICK_PHOTO_INTENT)
} }
choose_video.setOnClickListener { chooseVideo.setOnClickListener {
launchGetContentIntent(arrayOf("video/*"), PICK_VIDEO_INTENT) launchGetContentIntent(arrayOf("video/*"), PICK_VIDEO_INTENT)
} }
take_photo.setOnClickListener { takePhoto.setOnClickListener {
launchCapturePhotoIntent() launchCapturePhotoIntent()
} }
record_video.setOnClickListener { recordVideo.setOnClickListener {
launchCaptureVideoIntent() launchCaptureVideoIntent()
} }
record_audio.setOnClickListener { recordAudio.setOnClickListener {
launchCaptureAudioIntent() launchCaptureAudioIntent()
} }
pick_file.setOnClickListener { pickFile.setOnClickListener {
launchGetContentIntent(arrayOf("*/*"), PICK_DOCUMENT_INTENT) launchGetContentIntent(arrayOf("*/*"), PICK_DOCUMENT_INTENT)
} }
pick_contact.setOnClickListener { pickContact.setOnClickListener {
launchPickContactIntent() launchPickContactIntent()
} }
schedule_message.setOnClickListener { scheduleMessage.setOnClickListener {
if (isScheduledMessage) { if (isScheduledMessage) {
launchScheduleSendDialog(scheduledDateTime) launchScheduleSendDialog(scheduledDateTime)
} else { } else {
@ -1795,20 +1802,20 @@ class ThreadActivity : SimpleActivity() {
} }
private fun showAttachmentPicker() { private fun showAttachmentPicker() {
attachment_picker_divider.showWithAnimation() messageHolderBinding.attachmentPickerDivider.showWithAnimation()
attachment_picker_holder.showWithAnimation() messageHolderBinding.attachmentPickerHolder.showWithAnimation()
animateAttachmentButton(rotation = -135f) animateAttachmentButton(rotation = -135f)
} }
private fun maybeSetupRecycleBinView() { private fun maybeSetupRecycleBinView() {
if (isRecycleBin) { if (isRecycleBin) {
thread_send_message_holder.beGone() messageHolderBinding.root.beGone()
} }
} }
private fun hideAttachmentPicker() { private fun hideAttachmentPicker() {
attachment_picker_divider.beGone() messageHolderBinding.attachmentPickerDivider.beGone()
attachment_picker_holder.apply { messageHolderBinding.attachmentPickerHolder.apply {
beGone() beGone()
updateLayoutParams<ConstraintLayout.LayoutParams> { updateLayoutParams<ConstraintLayout.LayoutParams> {
height = config.keyboardHeight height = config.keyboardHeight
@ -1818,7 +1825,7 @@ class ThreadActivity : SimpleActivity() {
} }
private fun animateAttachmentButton(rotation: Float) { private fun animateAttachmentButton(rotation: Float) {
thread_add_attachment.animate() messageHolderBinding.threadAddAttachment.animate()
.rotation(rotation) .rotation(rotation)
.setDuration(500L) .setDuration(500L)
.setInterpolator(OvershootInterpolator()) .setInterpolator(OvershootInterpolator())

View File

@ -5,9 +5,11 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import com.simplemobiletools.commons.extensions.normalizePhoneNumber import com.simplemobiletools.commons.extensions.normalizePhoneNumber
import com.simplemobiletools.commons.extensions.sendEmailIntent import com.simplemobiletools.commons.extensions.sendEmailIntent
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.NavigationIcon import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.VCardViewerAdapter import com.simplemobiletools.smsmessenger.adapters.VCardViewerAdapter
import com.simplemobiletools.smsmessenger.databinding.ActivityVcardViewerBinding
import com.simplemobiletools.smsmessenger.extensions.dialNumber import com.simplemobiletools.smsmessenger.extensions.dialNumber
import com.simplemobiletools.smsmessenger.helpers.EXTRA_VCARD_URI import com.simplemobiletools.smsmessenger.helpers.EXTRA_VCARD_URI
import com.simplemobiletools.smsmessenger.helpers.parseVCardFromUri import com.simplemobiletools.smsmessenger.helpers.parseVCardFromUri
@ -16,17 +18,18 @@ import com.simplemobiletools.smsmessenger.models.VCardWrapper
import ezvcard.VCard import ezvcard.VCard
import ezvcard.property.Email import ezvcard.property.Email
import ezvcard.property.Telephone import ezvcard.property.Telephone
import kotlinx.android.synthetic.main.activity_vcard_viewer.*
class VCardViewerActivity : SimpleActivity() { class VCardViewerActivity : SimpleActivity() {
private val binding by viewBinding(ActivityVcardViewerBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_vcard_viewer) setContentView(binding.root)
updateMaterialActivityViews(vcard_viewer_coordinator, contacts_list, useTransparentNavigation = true, useTopSearchMenu = false) updateMaterialActivityViews(binding.vcardViewerCoordinator, binding.contactsList, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(contacts_list, vcard_toolbar) setupMaterialScrollListener(binding.contactsList, binding.vcardToolbar)
val vCardUri = intent.getParcelableExtra(EXTRA_VCARD_URI) as? Uri val vCardUri = intent.getParcelableExtra(EXTRA_VCARD_URI) as? Uri
if (vCardUri != null) { if (vCardUri != null) {
@ -41,11 +44,11 @@ class VCardViewerActivity : SimpleActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(vcard_toolbar, NavigationIcon.Arrow) setupToolbar(binding.vcardToolbar, NavigationIcon.Arrow)
} }
private fun setupOptionsMenu(vCardUri: Uri) { private fun setupOptionsMenu(vCardUri: Uri) {
vcard_toolbar.setOnMenuItemClickListener { menuItem -> binding.vcardToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.add_contact -> { R.id.add_contact -> {
val intent = Intent(Intent.ACTION_VIEW).apply { val intent = Intent(Intent.ACTION_VIEW).apply {
@ -55,6 +58,7 @@ class VCardViewerActivity : SimpleActivity() {
} }
startActivity(intent) startActivity(intent)
} }
else -> return@setOnMenuItemClickListener false else -> return@setOnMenuItemClickListener false
} }
return@setOnMenuItemClickListener true return@setOnMenuItemClickListener true
@ -69,7 +73,7 @@ class VCardViewerActivity : SimpleActivity() {
handleClick(item) handleClick(item)
} }
} }
contacts_list.adapter = adapter binding.contactsList.adapter = adapter
} }
private fun handleClick(property: VCardPropertyWrapper) { private fun handleClick(property: VCardPropertyWrapper) {

View File

@ -2,11 +2,12 @@ package com.simplemobiletools.smsmessenger.adapters
import android.content.Intent import android.content.Intent
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.View import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
@ -21,11 +22,12 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity
import com.simplemobiletools.smsmessenger.databinding.ItemAttachmentDocumentPreviewBinding
import com.simplemobiletools.smsmessenger.databinding.ItemAttachmentMediaPreviewBinding
import com.simplemobiletools.smsmessenger.databinding.ItemAttachmentVcardPreviewBinding
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.models.AttachmentSelection import com.simplemobiletools.smsmessenger.models.AttachmentSelection
import kotlinx.android.synthetic.main.item_attachment_media_preview.view.*
import kotlinx.android.synthetic.main.item_remove_attachment_button.view.*
class AttachmentsAdapter( class AttachmentsAdapter(
val activity: BaseSimpleActivity, val activity: BaseSimpleActivity,
@ -46,36 +48,34 @@ class AttachmentsAdapter(
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutRes = when (viewType) { val inflater = LayoutInflater.from(parent.context)
ATTACHMENT_DOCUMENT -> R.layout.item_attachment_document_preview val binding = when (viewType) {
ATTACHMENT_VCARD -> R.layout.item_attachment_vcard_preview ATTACHMENT_DOCUMENT -> ItemAttachmentDocumentPreviewBinding.inflate(inflater, parent, false)
ATTACHMENT_MEDIA -> R.layout.item_attachment_media_preview ATTACHMENT_VCARD -> ItemAttachmentVcardPreviewBinding.inflate(inflater, parent, false)
ATTACHMENT_MEDIA -> ItemAttachmentMediaPreviewBinding.inflate(inflater, parent, false)
else -> throw IllegalArgumentException("Unknown view type: $viewType") else -> throw IllegalArgumentException("Unknown view type: $viewType")
} }
val view = activity.layoutInflater.inflate(layoutRes, parent, false) return ViewHolder(binding)
return ViewHolder(view)
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val attachment = getItem(position) val attachment = getItem(position)
holder.bindView() { view, _ -> holder.bindView { binding, _ ->
when (attachment.viewType) { when (attachment.viewType) {
ATTACHMENT_DOCUMENT -> { ATTACHMENT_DOCUMENT -> {
view.setupDocumentPreview( (binding as ItemAttachmentDocumentPreviewBinding).setupDocumentPreview(
uri = attachment.uri, uri = attachment.uri,
title = attachment.filename, title = attachment.filename,
mimeType = attachment.mimetype, mimeType = attachment.mimetype,
attachment = true,
onClick = { activity.launchViewIntent(attachment.uri, attachment.mimetype, attachment.filename) }, onClick = { activity.launchViewIntent(attachment.uri, attachment.mimetype, attachment.filename) },
onRemoveButtonClicked = { removeAttachment(attachment) } onRemoveButtonClicked = { removeAttachment(attachment) }
) )
} }
ATTACHMENT_VCARD -> { ATTACHMENT_VCARD -> {
view.setupVCardPreview( (binding as ItemAttachmentVcardPreviewBinding).setupVCardPreview(
activity = activity, activity = activity,
uri = attachment.uri, uri = attachment.uri,
attachment = true,
onClick = { onClick = {
val intent = Intent(activity, VCardViewerActivity::class.java).also { val intent = Intent(activity, VCardViewerActivity::class.java).also {
it.putExtra(EXTRA_VCARD_URI, attachment.uri) it.putExtra(EXTRA_VCARD_URI, attachment.uri)
@ -85,7 +85,10 @@ class AttachmentsAdapter(
onRemoveButtonClicked = { removeAttachment(attachment) } onRemoveButtonClicked = { removeAttachment(attachment) }
) )
} }
ATTACHMENT_MEDIA -> setupMediaPreview(view, attachment) ATTACHMENT_MEDIA -> setupMediaPreview(
binding = binding as ItemAttachmentMediaPreviewBinding,
attachment = attachment
)
} }
} }
} }
@ -113,13 +116,14 @@ class AttachmentsAdapter(
} }
} }
private fun setupMediaPreview(view: View, attachment: AttachmentSelection) { private fun setupMediaPreview(binding: ItemAttachmentMediaPreviewBinding, attachment: AttachmentSelection) {
view.apply { binding.apply {
media_attachment_holder.background.applyColorFilter(primaryColor.darkenColor()) mediaAttachmentHolder.background.applyColorFilter(primaryColor.darkenColor())
media_attachment_holder.setOnClickListener { mediaAttachmentHolder.setOnClickListener {
activity.launchViewIntent(attachment.uri, attachment.mimetype, attachment.filename) activity.launchViewIntent(attachment.uri, attachment.mimetype, attachment.filename)
} }
remove_attachment_button.apply {
removeAttachmentButtonHolder.removeAttachmentButton.apply {
beVisible() beVisible()
background.applyColorFilter(primaryColor) background.applyColorFilter(primaryColor)
setOnClickListener { setOnClickListener {
@ -130,19 +134,21 @@ class AttachmentsAdapter(
val compressImage = attachment.mimetype.isImageMimeType() && !attachment.mimetype.isGifMimeType() val compressImage = attachment.mimetype.isImageMimeType() && !attachment.mimetype.isGifMimeType()
if (compressImage && attachment.isPending && config.mmsFileSizeLimit != FILE_SIZE_NONE) { if (compressImage && attachment.isPending && config.mmsFileSizeLimit != FILE_SIZE_NONE) {
thumbnail.beGone() thumbnail.beGone()
compression_progress.beVisible() compressionProgress.beVisible()
imageCompressor.compressImage(attachment.uri, config.mmsFileSizeLimit) { compressedUri -> imageCompressor.compressImage(attachment.uri, config.mmsFileSizeLimit) { compressedUri ->
activity.runOnUiThread { activity.runOnUiThread {
when (compressedUri) { when (compressedUri) {
attachment.uri -> { attachment.uri -> {
attachments.find { it.uri == attachment.uri }?.isPending = false attachments.find { it.uri == attachment.uri }?.isPending = false
loadMediaPreview(view, attachment) loadMediaPreview(this, attachment)
} }
null -> { null -> {
activity.toast(R.string.compress_error) activity.toast(R.string.compress_error)
removeAttachment(attachment) removeAttachment(attachment)
} }
else -> { else -> {
attachments.remove(attachment) attachments.remove(attachment)
addAttachment(attachment.copy(uri = compressedUri, isPending = false)) addAttachment(attachment.copy(uri = compressedUri, isPending = false))
@ -152,12 +158,12 @@ class AttachmentsAdapter(
} }
} }
} else { } else {
loadMediaPreview(view, attachment) loadMediaPreview(this, attachment)
} }
} }
} }
private fun loadMediaPreview(view: View, attachment: AttachmentSelection) { private fun loadMediaPreview(binding: ItemAttachmentMediaPreviewBinding, attachment: AttachmentSelection) {
val roundedCornersRadius = resources.getDimension(R.dimen.activity_margin).toInt() val roundedCornersRadius = resources.getDimension(R.dimen.activity_margin).toInt()
val size = resources.getDimension(R.dimen.attachment_preview_size).toInt() val size = resources.getDimension(R.dimen.attachment_preview_size).toInt()
@ -165,7 +171,7 @@ class AttachmentsAdapter(
.diskCacheStrategy(DiskCacheStrategy.NONE) .diskCacheStrategy(DiskCacheStrategy.NONE)
.transform(CenterCrop(), RoundedCorners(roundedCornersRadius)) .transform(CenterCrop(), RoundedCorners(roundedCornersRadius))
Glide.with(view.thumbnail) Glide.with(binding.thumbnail)
.load(attachment.uri) .load(attachment.uri)
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.override(size, size) .override(size, size)
@ -178,20 +184,18 @@ class AttachmentsAdapter(
} }
override fun onResourceReady(dr: Drawable?, a: Any?, t: Target<Drawable>?, d: DataSource?, i: Boolean): Boolean { override fun onResourceReady(dr: Drawable?, a: Any?, t: Target<Drawable>?, d: DataSource?, i: Boolean): Boolean {
view.thumbnail.beVisible() binding.thumbnail.beVisible()
view.play_icon.beVisibleIf(attachment.mimetype.isVideoMimeType()) binding.playIcon.beVisibleIf(attachment.mimetype.isVideoMimeType())
view.compression_progress.beGone() binding.compressionProgress.beGone()
return false return false
} }
}) })
.into(view.thumbnail) .into(binding.thumbnail)
} }
open inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class ViewHolder(val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindView(callback: (itemView: View, adapterPosition: Int) -> Unit): View { fun bindView(callback: (binding: ViewBinding, adapterPosition: Int) -> Unit) {
return itemView.apply { callback(binding, adapterPosition)
callback(this, adapterPosition)
}
} }
} }
} }

View File

@ -15,7 +15,6 @@ import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.extensions.config
class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: ArrayList<SimpleContact>) : ArrayAdapter<SimpleContact>(activity, 0, contacts) { class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: ArrayList<SimpleContact>) : ArrayAdapter<SimpleContact>(activity, 0, contacts) {
var resultList = ArrayList<SimpleContact>() var resultList = ArrayList<SimpleContact>()
@ -72,7 +71,7 @@ class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: Ar
} }
override fun publishResults(constraint: CharSequence?, results: FilterResults?) { override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
if (results?.count ?: -1 > 0) { if ((results?.count ?: -1) > 0) {
notifyDataSetChanged() notifyDataSetChanged()
} else { } else {
notifyDataSetInvalidated() notifyDataSetInvalidated()

View File

@ -5,7 +5,6 @@ import android.os.Parcelable
import android.util.TypedValue import android.util.TypedValue
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
@ -15,11 +14,10 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.databinding.ItemConversationBinding
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Conversation
import kotlinx.android.synthetic.main.item_conversation.view.*
@Suppress("LeakingThis") @Suppress("LeakingThis")
abstract class BaseConversationsAdapter( abstract class BaseConversationsAdapter(
@ -82,7 +80,10 @@ abstract class BaseConversationsAdapter(
override fun onActionModeDestroyed() {} override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_conversation, parent) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemConversationBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val conversation = getItem(position) val conversation = getItem(position)
@ -97,7 +98,8 @@ abstract class BaseConversationsAdapter(
override fun onViewRecycled(holder: ViewHolder) { override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder) super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing) { if (!activity.isDestroyed && !activity.isFinishing) {
Glide.with(activity).clear(holder.itemView.conversation_image) val itemView = ItemConversationBinding.bind(holder.itemView)
Glide.with(activity).clear(itemView.conversationImage)
} }
} }
@ -109,55 +111,55 @@ abstract class BaseConversationsAdapter(
} }
private fun setupView(view: View, conversation: Conversation) { private fun setupView(view: View, conversation: Conversation) {
view.apply { ItemConversationBinding.bind(view).apply {
setupViewBackground(activity) root.setupViewBackground(activity)
val smsDraft = drafts[conversation.threadId] val smsDraft = drafts[conversation.threadId]
draft_indicator.beVisibleIf(smsDraft != null) draftIndicator.beVisibleIf(smsDraft != null)
draft_indicator.setTextColor(properPrimaryColor) draftIndicator.setTextColor(properPrimaryColor)
pin_indicator.beVisibleIf(activity.config.pinnedConversations.contains(conversation.threadId.toString())) pinIndicator.beVisibleIf(activity.config.pinnedConversations.contains(conversation.threadId.toString()))
pin_indicator.applyColorFilter(textColor) pinIndicator.applyColorFilter(textColor)
conversation_frame.isSelected = selectedKeys.contains(conversation.hashCode()) conversationFrame.isSelected = selectedKeys.contains(conversation.hashCode())
conversation_address.apply { conversationAddress.apply {
text = conversation.title text = conversation.title
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f)
} }
conversation_body_short.apply { conversationBodyShort.apply {
text = smsDraft ?: conversation.snippet text = smsDraft ?: conversation.snippet
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f)
} }
conversation_date.apply { conversationDate.apply {
text = conversation.date.formatDateOrTime(context, true, false) text = conversation.date.formatDateOrTime(context, true, false)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
} }
val style = if (conversation.read) { val style = if (conversation.read) {
conversation_body_short.alpha = 0.7f conversationBodyShort.alpha = 0.7f
if (conversation.isScheduled) Typeface.ITALIC else Typeface.NORMAL if (conversation.isScheduled) Typeface.ITALIC else Typeface.NORMAL
} else { } else {
conversation_body_short.alpha = 1f conversationBodyShort.alpha = 1f
if (conversation.isScheduled) Typeface.BOLD_ITALIC else Typeface.BOLD if (conversation.isScheduled) Typeface.BOLD_ITALIC else Typeface.BOLD
} }
conversation_address.setTypeface(null, style) conversationAddress.setTypeface(null, style)
conversation_body_short.setTypeface(null, style) conversationBodyShort.setTypeface(null, style)
arrayListOf<TextView>(conversation_address, conversation_body_short, conversation_date).forEach { arrayListOf(conversationAddress, conversationBodyShort, conversationDate).forEach {
it.setTextColor(textColor) it.setTextColor(textColor)
} }
// at group conversations we use an icon as the placeholder, not any letter // at group conversations we use an icon as the placeholder, not any letter
val placeholder = if (conversation.isGroupConversation) { val placeholder = if (conversation.isGroupConversation) {
SimpleContactsHelper(context).getColoredGroupIcon(conversation.title) SimpleContactsHelper(activity).getColoredGroupIcon(conversation.title)
} else { } else {
null null
} }
SimpleContactsHelper(context).loadContactImage(conversation.photoUri, conversation_image, conversation.title, placeholder) SimpleContactsHelper(activity).loadContactImage(conversation.photoUri, conversationImage, conversation.title, placeholder)
} }
} }

View File

@ -5,17 +5,14 @@ import android.util.TypedValue
import android.view.Menu import android.view.Menu
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.databinding.ItemContactWithNumberBinding
import com.simplemobiletools.commons.extensions.getTextSize import com.simplemobiletools.commons.extensions.getTextSize
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import java.util.*
class ContactsAdapter( class ContactsAdapter(
activity: SimpleActivity, var contacts: ArrayList<SimpleContact>, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit activity: SimpleActivity, var contacts: ArrayList<SimpleContact>, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit
@ -40,11 +37,14 @@ class ContactsAdapter(
override fun onActionModeDestroyed() {} override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_contact_with_number, parent) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemContactWithNumberBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val contact = contacts[position] val contact = contacts[position]
holder.bindView(contact, true, false) { itemView, layoutPosition -> holder.bindView(contact, allowSingleClick = true, allowLongClick = false) { itemView, _ ->
setupView(itemView, contact) setupView(itemView, contact)
} }
bindViewHolder(holder) bindViewHolder(holder)
@ -62,27 +62,28 @@ class ContactsAdapter(
} }
private fun setupView(view: View, contact: SimpleContact) { private fun setupView(view: View, contact: SimpleContact) {
view.apply { ItemContactWithNumberBinding.bind(view).apply {
findViewById<TextView>(R.id.item_contact_name).apply { itemContactName.apply {
text = contact.name text = contact.name
setTextColor(textColor) setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f)
} }
findViewById<TextView>(R.id.item_contact_number).apply { itemContactNumber.apply {
text = TextUtils.join(", ", contact.phoneNumbers.map { it.normalizedNumber }) text = TextUtils.join(", ", contact.phoneNumbers.map { it.normalizedNumber })
setTextColor(textColor) setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
} }
SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.name) SimpleContactsHelper(activity).loadContactImage(contact.photoUri, itemContactImage, contact.name)
} }
} }
override fun onViewRecycled(holder: ViewHolder) { override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder) super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing) { if (!activity.isDestroyed && !activity.isFinishing) {
Glide.with(activity).clear(holder.itemView.findViewById<ImageView>(R.id.item_contact_image)) val binding = ItemContactWithNumberBinding.bind(holder.itemView)
Glide.with(activity).clear(binding.itemContactImage)
} }
} }
} }

View File

@ -10,10 +10,9 @@ import com.simplemobiletools.commons.extensions.getTextSize
import com.simplemobiletools.commons.extensions.highlightTextPart import com.simplemobiletools.commons.extensions.highlightTextPart
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.databinding.ItemSearchResultBinding
import com.simplemobiletools.smsmessenger.models.SearchResult import com.simplemobiletools.smsmessenger.models.SearchResult
import kotlinx.android.synthetic.main.item_search_result.view.*
class SearchResultsAdapter( class SearchResultsAdapter(
activity: SimpleActivity, var searchResults: ArrayList<SearchResult>, recyclerView: MyRecyclerView, highlightText: String, itemClick: (Any) -> Unit activity: SimpleActivity, var searchResults: ArrayList<SearchResult>, recyclerView: MyRecyclerView, highlightText: String, itemClick: (Any) -> Unit
@ -40,11 +39,14 @@ class SearchResultsAdapter(
override fun onActionModeDestroyed() {} override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_search_result, parent) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemSearchResultBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val searchResult = searchResults[position] val searchResult = searchResults[position]
holder.bindView(searchResult, true, false) { itemView, layoutPosition -> holder.bindView(searchResult, allowSingleClick = true, allowLongClick = false) { itemView, _ ->
setupView(itemView, searchResult) setupView(itemView, searchResult)
} }
bindViewHolder(holder) bindViewHolder(holder)
@ -64,33 +66,34 @@ class SearchResultsAdapter(
} }
private fun setupView(view: View, searchResult: SearchResult) { private fun setupView(view: View, searchResult: SearchResult) {
view.apply { ItemSearchResultBinding.bind(view).apply {
search_result_title.apply { searchResultTitle.apply {
text = searchResult.title.highlightTextPart(textToHighlight, properPrimaryColor) text = searchResult.title.highlightTextPart(textToHighlight, properPrimaryColor)
setTextColor(textColor) setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f)
} }
search_result_snippet.apply { searchResultSnippet.apply {
text = searchResult.snippet.highlightTextPart(textToHighlight, properPrimaryColor) text = searchResult.snippet.highlightTextPart(textToHighlight, properPrimaryColor)
setTextColor(textColor) setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f)
} }
search_result_date.apply { searchResultDate.apply {
text = searchResult.date text = searchResult.date
setTextColor(textColor) setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
} }
SimpleContactsHelper(context).loadContactImage(searchResult.photoUri, search_result_image, searchResult.title) SimpleContactsHelper(activity).loadContactImage(searchResult.photoUri, searchResultImage, searchResult.title)
} }
} }
override fun onViewRecycled(holder: ViewHolder) { override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder) super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.search_result_image != null) { if (!activity.isDestroyed && !activity.isFinishing) {
Glide.with(activity).clear(holder.itemView.search_result_image) val binding = ItemSearchResultBinding.bind(holder.itemView)
Glide.with(activity).clear(binding.searchResultImage)
} }
} }
} }

View File

@ -12,7 +12,13 @@ import android.util.TypedValue
import android.view.Menu import android.view.Menu
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.viewbinding.ViewBinding
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
@ -33,6 +39,7 @@ import com.simplemobiletools.smsmessenger.activities.NewConversationActivity
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.activities.ThreadActivity import com.simplemobiletools.smsmessenger.activities.ThreadActivity
import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity
import com.simplemobiletools.smsmessenger.databinding.*
import com.simplemobiletools.smsmessenger.dialogs.DeleteConfirmationDialog import com.simplemobiletools.smsmessenger.dialogs.DeleteConfirmationDialog
import com.simplemobiletools.smsmessenger.dialogs.MessageDetailsDialog import com.simplemobiletools.smsmessenger.dialogs.MessageDetailsDialog
import com.simplemobiletools.smsmessenger.dialogs.SelectTextDialog import com.simplemobiletools.smsmessenger.dialogs.SelectTextDialog
@ -42,18 +49,6 @@ import com.simplemobiletools.smsmessenger.models.Attachment
import com.simplemobiletools.smsmessenger.models.Message import com.simplemobiletools.smsmessenger.models.Message
import com.simplemobiletools.smsmessenger.models.ThreadItem import com.simplemobiletools.smsmessenger.models.ThreadItem
import com.simplemobiletools.smsmessenger.models.ThreadItem.* import com.simplemobiletools.smsmessenger.models.ThreadItem.*
import kotlinx.android.synthetic.main.item_attachment_image.view.*
import kotlinx.android.synthetic.main.item_received_message.view.*
import kotlinx.android.synthetic.main.item_received_message.view.thread_mesage_attachments_holder
import kotlinx.android.synthetic.main.item_received_message.view.thread_message_body
import kotlinx.android.synthetic.main.item_received_message.view.thread_message_holder
import kotlinx.android.synthetic.main.item_received_message.view.thread_message_play_outline
import kotlinx.android.synthetic.main.item_sent_message.view.*
import kotlinx.android.synthetic.main.item_thread_date_time.view.*
import kotlinx.android.synthetic.main.item_thread_error.view.*
import kotlinx.android.synthetic.main.item_thread_loading.view.*
import kotlinx.android.synthetic.main.item_thread_sending.view.*
import kotlinx.android.synthetic.main.item_thread_success.view.*
class ThreadAdapter( class ThreadAdapter(
activity: SimpleActivity, activity: SimpleActivity,
@ -121,16 +116,16 @@ class ThreadAdapter(
override fun onActionModeDestroyed() {} override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layout = when (viewType) { val binding = when (viewType) {
THREAD_LOADING -> R.layout.item_thread_loading THREAD_LOADING -> ItemThreadLoadingBinding.inflate(layoutInflater, parent, false)
THREAD_DATE_TIME -> R.layout.item_thread_date_time THREAD_DATE_TIME -> ItemThreadDateTimeBinding.inflate(layoutInflater, parent, false)
THREAD_RECEIVED_MESSAGE -> R.layout.item_received_message THREAD_SENT_MESSAGE_ERROR -> ItemThreadErrorBinding.inflate(layoutInflater, parent, false)
THREAD_SENT_MESSAGE_ERROR -> R.layout.item_thread_error THREAD_SENT_MESSAGE_SENT -> ItemThreadSuccessBinding.inflate(layoutInflater, parent, false)
THREAD_SENT_MESSAGE_SENT -> R.layout.item_thread_success THREAD_SENT_MESSAGE_SENDING -> ItemThreadSendingBinding.inflate(layoutInflater, parent, false)
THREAD_SENT_MESSAGE_SENDING -> R.layout.item_thread_sending else -> ItemMessageBinding.inflate(layoutInflater, parent, false)
else -> R.layout.item_sent_message
} }
return createViewHolder(layout, parent)
return ThreadViewHolder(binding)
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
@ -278,115 +273,134 @@ class ThreadAdapter(
} }
private fun setupView(holder: ViewHolder, view: View, message: Message) { private fun setupView(holder: ViewHolder, view: View, message: Message) {
view.apply { ItemMessageBinding.bind(view).apply {
thread_message_holder.isSelected = selectedKeys.contains(message.hashCode()) threadMessageHolder.isSelected = selectedKeys.contains(message.hashCode())
thread_message_body.apply { threadMessageBody.apply {
text = message.body text = message.body
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
} beVisibleIf(message.body.isNotEmpty())
thread_message_body.beVisibleIf(message.body.isNotEmpty()) setOnLongClickListener {
if (message.isReceivedMessage()) {
setupReceivedMessageView(view, message)
} else {
setupSentMessageView(view, message)
}
thread_message_body.setOnLongClickListener {
holder.viewLongClicked() holder.viewLongClicked()
true true
} }
thread_message_body.setOnClickListener { setOnClickListener {
holder.viewClicked(message) holder.viewClicked(message)
} }
}
if (message.isReceivedMessage()) {
setupReceivedMessageView(messageBinding = this, message = message)
} else {
setupSentMessageView(messageBinding = this, message = message)
}
if (message.attachment?.attachments?.isNotEmpty() == true) { if (message.attachment?.attachments?.isNotEmpty() == true) {
thread_mesage_attachments_holder.beVisible() threadMessageAttachmentsHolder.beVisible()
thread_mesage_attachments_holder.removeAllViews() threadMessageAttachmentsHolder.removeAllViews()
for (attachment in message.attachment.attachments) { for (attachment in message.attachment.attachments) {
val mimetype = attachment.mimetype val mimetype = attachment.mimetype
when { when {
mimetype.isImageMimeType() || mimetype.isVideoMimeType() -> setupImageView(holder, view, message, attachment) mimetype.isImageMimeType() || mimetype.isVideoMimeType() -> setupImageView(holder, binding = this, message, attachment)
mimetype.isVCardMimeType() -> setupVCardView(holder, view, message, attachment) mimetype.isVCardMimeType() -> setupVCardView(holder, threadMessageAttachmentsHolder, message, attachment)
else -> setupFileView(holder, view, message, attachment) else -> setupFileView(holder, threadMessageAttachmentsHolder, message, attachment)
} }
thread_message_play_outline.beVisibleIf(mimetype.startsWith("video/")) threadMessagePlayOutline.beVisibleIf(mimetype.startsWith("video/"))
} }
} else { } else {
thread_mesage_attachments_holder.beGone() threadMessageAttachmentsHolder.beGone()
threadMessagePlayOutline.beGone()
} }
} }
} }
private fun setupReceivedMessageView(view: View, message: Message) { private fun setupReceivedMessageView(messageBinding: ItemMessageBinding, message: Message) {
view.apply { messageBinding.apply {
thread_message_sender_photo.beVisible() with(ConstraintSet()) {
thread_message_sender_photo.setOnClickListener { clone(threadMessageHolder)
clear(threadMessageWrapper.id, ConstraintSet.END)
connect(threadMessageWrapper.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START)
applyTo(threadMessageHolder)
}
threadMessageSenderPhoto.beVisible()
threadMessageSenderPhoto.setOnClickListener {
val contact = message.getSender()!! val contact = message.getSender()!!
context.getContactFromAddress(contact.phoneNumbers.first().normalizedNumber) { activity.getContactFromAddress(contact.phoneNumbers.first().normalizedNumber) {
if (it != null) { if (it != null) {
activity.startContactDetailsIntent(it) activity.startContactDetailsIntent(it)
} }
} }
} }
thread_message_body.setTextColor(textColor)
thread_message_body.setLinkTextColor(context.getProperPrimaryColor()) threadMessageBody.apply {
background = AppCompatResources.getDrawable(activity, R.drawable.item_received_background)
setTextColor(textColor)
setLinkTextColor(activity.getProperPrimaryColor())
}
if (!activity.isFinishing && !activity.isDestroyed) { if (!activity.isFinishing && !activity.isDestroyed) {
val contactLetterIcon = SimpleContactsHelper(context).getContactLetterIcon(message.senderName) val contactLetterIcon = SimpleContactsHelper(activity).getContactLetterIcon(message.senderName)
val placeholder = BitmapDrawable(context.resources, contactLetterIcon) val placeholder = BitmapDrawable(activity.resources, contactLetterIcon)
val options = RequestOptions() val options = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.RESOURCE) .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.error(placeholder) .error(placeholder)
.centerCrop() .centerCrop()
Glide.with(context) Glide.with(activity)
.load(message.senderPhotoUri) .load(message.senderPhotoUri)
.placeholder(placeholder) .placeholder(placeholder)
.apply(options) .apply(options)
.apply(RequestOptions.circleCropTransform()) .apply(RequestOptions.circleCropTransform())
.into(thread_message_sender_photo) .into(threadMessageSenderPhoto)
} }
} }
} }
private fun setupSentMessageView(view: View, message: Message) { private fun setupSentMessageView(messageBinding: ItemMessageBinding, message: Message) {
view.apply { messageBinding.apply {
thread_message_sender_photo?.beGone() with(ConstraintSet()) {
val background = context.getProperPrimaryColor() clone(threadMessageHolder)
thread_message_body.background.applyColorFilter(background) clear(threadMessageWrapper.id, ConstraintSet.START)
connect(threadMessageWrapper.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END)
applyTo(threadMessageHolder)
}
val contrastColor = background.getContrastColor() val primaryColor = activity.getProperPrimaryColor()
thread_message_body.setTextColor(contrastColor) val contrastColor = primaryColor.getContrastColor()
thread_message_body.setLinkTextColor(contrastColor)
threadMessageBody.apply {
updateLayoutParams<RelativeLayout.LayoutParams> {
removeRule(RelativeLayout.END_OF)
addRule(RelativeLayout.ALIGN_PARENT_END)
}
background = AppCompatResources.getDrawable(activity, R.drawable.item_sent_background)
background.applyColorFilter(primaryColor)
setTextColor(contrastColor)
setLinkTextColor(contrastColor)
val padding = thread_message_body.paddingStart
if (message.isScheduled) { if (message.isScheduled) {
thread_message_scheduled_icon.beVisible() typeface = Typeface.create(Typeface.DEFAULT, Typeface.ITALIC)
thread_message_scheduled_icon.applyColorFilter(contrastColor) val scheduledDrawable = AppCompatResources.getDrawable(activity, R.drawable.scheduled_message_icon)
scheduledDrawable?.applyColorFilter(contrastColor)
val iconWidth = resources.getDimensionPixelSize(R.dimen.small_icon_size) setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, scheduledDrawable, null)
val rightPadding = padding + iconWidth
thread_message_body.setPadding(padding, padding, rightPadding, padding)
thread_message_body.typeface = Typeface.create(Typeface.DEFAULT, Typeface.ITALIC)
} else { } else {
thread_message_scheduled_icon.beGone() typeface = Typeface.DEFAULT
setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null)
thread_message_body.setPadding(padding, padding, padding, padding) }
thread_message_body.typeface = Typeface.DEFAULT
} }
} }
} }
private fun setupImageView(holder: ViewHolder, parent: View, message: Message, attachment: Attachment) { private fun setupImageView(holder: ViewHolder, binding: ItemMessageBinding, message: Message, attachment: Attachment) = binding.apply {
val mimetype = attachment.mimetype val mimetype = attachment.mimetype
val uri = attachment.getUri() val uri = attachment.getUri()
parent.apply {
val imageView = layoutInflater.inflate(R.layout.item_attachment_image, null) val imageView = ItemAttachmentImageBinding.inflate(layoutInflater)
thread_mesage_attachments_holder.addView(imageView) threadMessageAttachmentsHolder.addView(imageView.root)
val placeholderDrawable = ColorDrawable(Color.TRANSPARENT) val placeholderDrawable = ColorDrawable(Color.TRANSPARENT)
val isTallImage = attachment.height > attachment.width val isTallImage = attachment.height > attachment.width
@ -396,13 +410,13 @@ class ThreadAdapter(
.placeholder(placeholderDrawable) .placeholder(placeholderDrawable)
.transform(transformation) .transform(transformation)
var builder = Glide.with(context) var builder = Glide.with(root.context)
.load(uri) .load(uri)
.apply(options) .apply(options)
.listener(object : RequestListener<Drawable> { .listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean { override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
thread_message_play_outline.beGone() threadMessagePlayOutline.beGone()
thread_mesage_attachments_holder.removeView(imageView) threadMessageAttachmentsHolder.removeView(imageView.root)
return false return false
} }
@ -423,28 +437,26 @@ class ThreadAdapter(
} }
try { try {
builder.into(imageView.attachment_image) builder.into(imageView.attachmentImage)
} catch (ignore: Exception) { } catch (ignore: Exception) {
} }
imageView.attachment_image.setOnClickListener { imageView.attachmentImage.setOnClickListener {
if (actModeCallback.isSelectable) { if (actModeCallback.isSelectable) {
holder.viewClicked(message) holder.viewClicked(message)
} else { } else {
activity.launchViewIntent(uri, mimetype, attachment.filename) activity.launchViewIntent(uri, mimetype, attachment.filename)
} }
} }
imageView.setOnLongClickListener { imageView.root.setOnLongClickListener {
holder.viewLongClicked() holder.viewLongClicked()
true true
} }
} }
}
private fun setupVCardView(holder: ViewHolder, parent: View, message: Message, attachment: Attachment) { private fun setupVCardView(holder: ViewHolder, parent: LinearLayout, message: Message, attachment: Attachment) {
val uri = attachment.getUri() val uri = attachment.getUri()
parent.apply { val vCardView = ItemAttachmentVcardBinding.inflate(layoutInflater).apply {
val vCardView = layoutInflater.inflate(R.layout.item_attachment_vcard, null).apply {
setupVCardPreview( setupVCardPreview(
activity = activity, activity = activity,
uri = uri, uri = uri,
@ -452,24 +464,23 @@ class ThreadAdapter(
if (actModeCallback.isSelectable) { if (actModeCallback.isSelectable) {
holder.viewClicked(message) holder.viewClicked(message)
} else { } else {
val intent = Intent(context, VCardViewerActivity::class.java).also { val intent = Intent(activity, VCardViewerActivity::class.java).also {
it.putExtra(EXTRA_VCARD_URI, uri) it.putExtra(EXTRA_VCARD_URI, uri)
} }
context.startActivity(intent) activity.startActivity(intent)
} }
}, },
onLongClick = { holder.viewLongClicked() } onLongClick = { holder.viewLongClicked() }
) )
} }.root
thread_mesage_attachments_holder.addView(vCardView)
} parent.addView(vCardView)
} }
private fun setupFileView(holder: ViewHolder, parent: View, message: Message, attachment: Attachment) { private fun setupFileView(holder: ViewHolder, parent: LinearLayout, message: Message, attachment: Attachment) {
val mimetype = attachment.mimetype val mimetype = attachment.mimetype
val uri = attachment.getUri() val uri = attachment.getUri()
parent.apply { val attachmentView = ItemAttachmentDocumentBinding.inflate(layoutInflater).apply {
val attachmentView = layoutInflater.inflate(R.layout.item_attachment_document, null).apply {
setupDocumentPreview( setupDocumentPreview(
uri = uri, uri = uri,
title = attachment.filename, title = attachment.filename,
@ -483,53 +494,64 @@ class ThreadAdapter(
}, },
onLongClick = { holder.viewLongClicked() }, onLongClick = { holder.viewLongClicked() },
) )
} }.root
thread_mesage_attachments_holder.addView(attachmentView)
} parent.addView(attachmentView)
} }
private fun setupDateTime(view: View, dateTime: ThreadDateTime) { private fun setupDateTime(view: View, dateTime: ThreadDateTime) {
view.apply { ItemThreadDateTimeBinding.bind(view).apply {
thread_date_time.apply { threadDateTime.apply {
text = dateTime.date.formatDateOrTime(context, false, false) text = dateTime.date.formatDateOrTime(context, hideTimeAtOtherDays = false, showYearEvenIfCurrent = false)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
} }
thread_date_time.setTextColor(textColor) threadDateTime.setTextColor(textColor)
thread_sim_icon.beVisibleIf(hasMultipleSIMCards) threadSimIcon.beVisibleIf(hasMultipleSIMCards)
thread_sim_number.beVisibleIf(hasMultipleSIMCards) threadSimNumber.beVisibleIf(hasMultipleSIMCards)
if (hasMultipleSIMCards) { if (hasMultipleSIMCards) {
thread_sim_number.text = dateTime.simID threadSimNumber.text = dateTime.simID
thread_sim_number.setTextColor(textColor.getContrastColor()) threadSimNumber.setTextColor(textColor.getContrastColor())
thread_sim_icon.applyColorFilter(textColor) threadSimIcon.applyColorFilter(textColor)
} }
} }
} }
private fun setupThreadSuccess(view: View, isDelivered: Boolean) { private fun setupThreadSuccess(view: View, isDelivered: Boolean) {
view.thread_success.setImageResource(if (isDelivered) R.drawable.ic_check_double_vector else R.drawable.ic_check_vector) ItemThreadSuccessBinding.bind(view).apply {
view.thread_success.applyColorFilter(textColor) threadSuccess.setImageResource(if (isDelivered) R.drawable.ic_check_double_vector else R.drawable.ic_check_vector)
threadSuccess.applyColorFilter(textColor)
}
} }
private fun setupThreadError(view: View) { private fun setupThreadError(view: View) {
view.thread_error.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize - 4) val binding = ItemThreadErrorBinding.bind(view)
binding.threadError.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize - 4)
} }
private fun setupThreadSending(view: View) { private fun setupThreadSending(view: View) {
view.thread_sending.apply { ItemThreadSendingBinding.bind(view).threadSending.apply {
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
setTextColor(textColor) setTextColor(textColor)
} }
} }
private fun setupThreadLoading(view: View) = view.thread_loading.setIndicatorColor(properPrimaryColor) private fun setupThreadLoading(view: View) {
val binding = ItemThreadLoadingBinding.bind(view)
binding.threadLoading.setIndicatorColor(properPrimaryColor)
}
override fun onViewRecycled(holder: ViewHolder) { override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder) super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.thread_message_sender_photo != null) { if (!activity.isDestroyed && !activity.isFinishing) {
Glide.with(activity).clear(holder.itemView.thread_message_sender_photo) val binding = (holder as ThreadViewHolder).binding
if (binding is ItemMessageBinding) {
Glide.with(activity).clear(binding.threadMessageSenderPhoto)
} }
} }
}
inner class ThreadViewHolder(val binding: ViewBinding) : ViewHolder(binding.root)
} }
private class ThreadItemDiffCallback : DiffUtil.ItemCallback<ThreadItem>() { private class ThreadItemDiffCallback : DiffUtil.ItemCallback<ThreadItem>() {

View File

@ -1,7 +1,6 @@
package com.simplemobiletools.smsmessenger.adapters package com.simplemobiletools.smsmessenger.adapters
import android.util.TypedValue import android.util.TypedValue
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -14,14 +13,17 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.databinding.ItemVcardContactBinding
import com.simplemobiletools.smsmessenger.databinding.ItemVcardContactPropertyBinding
import com.simplemobiletools.smsmessenger.models.VCardPropertyWrapper import com.simplemobiletools.smsmessenger.models.VCardPropertyWrapper
import com.simplemobiletools.smsmessenger.models.VCardWrapper import com.simplemobiletools.smsmessenger.models.VCardWrapper
import kotlinx.android.synthetic.main.item_vcard_contact.view.*
import kotlinx.android.synthetic.main.item_vcard_contact_property.view.* private const val TYPE_VCARD_CONTACT = 1
private const val TYPE_VCARD_CONTACT_PROPERTY = 2
class VCardViewerAdapter( class VCardViewerAdapter(
activity: SimpleActivity, private var items: MutableList<Any>, private val itemClick: (Any) -> Unit activity: SimpleActivity, private var items: MutableList<Any>, private val itemClick: (Any) -> Unit
) : RecyclerView.Adapter<VCardViewerAdapter.VCardViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var fontSize = activity.getTextSize() private var fontSize = activity.getTextSize()
private var textColor = activity.getProperTextColor() private var textColor = activity.getProperTextColor()
@ -31,36 +33,42 @@ class VCardViewerAdapter(
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return when (val item = items[position]) { return when (val item = items[position]) {
is VCardWrapper -> R.layout.item_vcard_contact is VCardWrapper -> TYPE_VCARD_CONTACT
is VCardPropertyWrapper -> R.layout.item_vcard_contact_property is VCardPropertyWrapper -> TYPE_VCARD_CONTACT_PROPERTY
else -> throw IllegalArgumentException("Unexpected type: ${item::class.simpleName}") else -> throw IllegalArgumentException("Unexpected type: ${item::class.simpleName}")
} }
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VCardViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = layoutInflater.inflate(viewType, parent, false) return when (viewType) {
return VCardViewHolder(view) TYPE_VCARD_CONTACT -> VCardContactViewHolder(
binding = ItemVcardContactBinding.inflate(layoutInflater, parent, false)
)
TYPE_VCARD_CONTACT_PROPERTY -> VCardPropertyViewHolder(
binding = ItemVcardContactPropertyBinding.inflate(layoutInflater, parent, false)
)
else -> throw IllegalArgumentException("Unexpected type: $viewType")
}
} }
override fun onBindViewHolder(holder: VCardViewerAdapter.VCardViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = items[position] val item = items[position]
val itemView = holder.bindView() when (holder) {
when (item) { is VCardContactViewHolder -> holder.bindView(item as VCardWrapper)
is VCardWrapper -> setupVCardView(itemView, item) is VCardPropertyViewHolder -> holder.bindView(item as VCardPropertyWrapper)
is VCardPropertyWrapper -> setupVCardPropertyView(itemView, item)
else -> throw IllegalArgumentException("Unexpected type: ${item::class.simpleName}")
} }
} }
private fun setupVCardView(view: View, item: VCardWrapper) { inner class VCardContactViewHolder(val binding: ItemVcardContactBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindView(item: VCardWrapper) {
val name = item.fullName val name = item.fullName
view.apply { binding.apply {
item_contact_name.apply { itemContactName.apply {
text = name text = name
setTextColor(textColor) setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.1f) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.1f)
} }
item_contact_image.apply { itemContactImage.apply {
val photo = item.vCard.photos.firstOrNull() val photo = item.vCard.photos.firstOrNull()
val placeholder = if (name != null) { val placeholder = if (name != null) {
SimpleContactsHelper(context).getContactLetterIcon(name).toDrawable(resources) SimpleContactsHelper(context).getContactLetterIcon(name).toDrawable(resources)
@ -79,7 +87,7 @@ class VCardViewerAdapter(
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.into(this) .into(this)
} }
expand_collapse_icon.apply { expandCollapseIcon.apply {
val expandCollapseDrawable = if (item.expanded) { val expandCollapseDrawable = if (item.expanded) {
R.drawable.ic_collapse_up R.drawable.ic_collapse_up
} else { } else {
@ -90,64 +98,63 @@ class VCardViewerAdapter(
} }
if (items.size > 1) { if (items.size > 1) {
setOnClickListener { root.setOnClickListener {
expandOrCollapseRow(view, item) expandOrCollapseRow(item)
} }
} }
onGlobalLayout { root.onGlobalLayout {
if (items.size == 1) { if (items.size == 1) {
expandOrCollapseRow(view, item) expandOrCollapseRow(item)
view.expand_collapse_icon.beGone() expandCollapseIcon.beGone()
} }
} }
} }
} }
private fun setupVCardPropertyView(view: View, property: VCardPropertyWrapper) { private fun expandOrCollapseRow(item: VCardWrapper) {
view.apply {
item_vcard_property_title.apply {
text = property.value
setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.1f)
}
item_vcard_property_subtitle.apply {
text = property.type
setTextColor(textColor)
}
view.setOnClickListener {
itemClick(property)
}
}
}
private fun expandOrCollapseRow(view: View, item: VCardWrapper) {
val properties = item.properties val properties = item.properties
if (item.expanded) { if (item.expanded) {
collapseRow(view, properties, item) collapseRow(properties, item)
} else { } else {
expandRow(view, properties, item) expandRow(properties, item)
} }
} }
private fun expandRow(view: View, properties: List<VCardPropertyWrapper>, vCardWrapper: VCardWrapper) { private fun expandRow(properties: List<VCardPropertyWrapper>, vCardWrapper: VCardWrapper) {
vCardWrapper.expanded = true vCardWrapper.expanded = true
val nextPosition = items.indexOf(vCardWrapper) + 1 val nextPosition = items.indexOf(vCardWrapper) + 1
items.addAll(nextPosition, properties) items.addAll(nextPosition, properties)
notifyItemRangeInserted(nextPosition, properties.size) notifyItemRangeInserted(nextPosition, properties.size)
view.expand_collapse_icon.setImageResource(R.drawable.ic_collapse_up) binding.expandCollapseIcon.setImageResource(R.drawable.ic_collapse_up)
} }
private fun collapseRow(view: View, properties: List<VCardPropertyWrapper>, vCardWrapper: VCardWrapper) { private fun collapseRow(properties: List<VCardPropertyWrapper>, vCardWrapper: VCardWrapper) {
vCardWrapper.expanded = false vCardWrapper.expanded = false
val nextPosition = items.indexOf(vCardWrapper) + 1 val nextPosition = items.indexOf(vCardWrapper) + 1
repeat(properties.size) { repeat(properties.size) {
items.removeAt(nextPosition) items.removeAt(nextPosition)
} }
notifyItemRangeRemoved(nextPosition, properties.size) notifyItemRangeRemoved(nextPosition, properties.size)
view.expand_collapse_icon.setImageResource(R.drawable.ic_expand_down) binding.expandCollapseIcon.setImageResource(R.drawable.ic_expand_down)
}
} }
inner class VCardViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class VCardPropertyViewHolder(val binding: ItemVcardContactPropertyBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindView() = itemView fun bindView(item: VCardPropertyWrapper) {
binding.apply {
itemVcardPropertyTitle.apply {
text = item.value
setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.1f)
}
itemVcardPropertySubtitle.apply {
text = item.type
setTextColor(textColor)
}
root.setOnClickListener {
itemClick(item)
}
}
}
} }
} }

View File

@ -7,14 +7,14 @@ import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.showKeyboard import com.simplemobiletools.commons.extensions.showKeyboard
import com.simplemobiletools.commons.extensions.value import com.simplemobiletools.commons.extensions.value
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.databinding.DialogAddBlockedKeywordBinding
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import kotlinx.android.synthetic.main.dialog_add_blocked_keyword.view.add_blocked_keyword_edittext
class AddBlockedKeywordDialog(val activity: BaseSimpleActivity, private val originalKeyword: String? = null, val callback: () -> Unit) { class AddBlockedKeywordDialog(val activity: BaseSimpleActivity, private val originalKeyword: String? = null, val callback: () -> Unit) {
init { init {
val view = activity.layoutInflater.inflate(R.layout.dialog_add_blocked_keyword, null).apply { val binding = DialogAddBlockedKeywordBinding.inflate(activity.layoutInflater).apply {
if (originalKeyword != null) { if (originalKeyword != null) {
add_blocked_keyword_edittext.setText(originalKeyword) addBlockedKeywordEdittext.setText(originalKeyword)
} }
} }
@ -22,10 +22,10 @@ class AddBlockedKeywordDialog(val activity: BaseSimpleActivity, private val orig
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.apply { .apply {
activity.setupDialogStuff(view, this) { alertDialog -> activity.setupDialogStuff(binding.root, this) { alertDialog ->
alertDialog.showKeyboard(view.add_blocked_keyword_edittext) alertDialog.showKeyboard(binding.addBlockedKeywordEdittext)
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val newBlockedKeyword = view.add_blocked_keyword_edittext.value val newBlockedKeyword = binding.addBlockedKeywordEdittext.value
if (originalKeyword != null && newBlockedKeyword != originalKeyword) { if (originalKeyword != null && newBlockedKeyword != originalKeyword) {
activity.config.removeBlockedKeyword(originalKeyword) activity.config.removeBlockedKeyword(originalKeyword)
} }

View File

@ -6,8 +6,7 @@ import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.delete_remember_title import com.simplemobiletools.smsmessenger.databinding.DialogDeleteConfirmationBinding
import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.skip_the_recycle_bin_checkbox
class DeleteConfirmationDialog( class DeleteConfirmationDialog(
private val activity: Activity, private val activity: Activity,
@ -17,16 +16,16 @@ class DeleteConfirmationDialog(
) { ) {
private var dialog: AlertDialog? = null private var dialog: AlertDialog? = null
val view = activity.layoutInflater.inflate(R.layout.dialog_delete_confirmation, null)!! val binding = DialogDeleteConfirmationBinding.inflate(activity.layoutInflater)
init { init {
view.delete_remember_title.text = message binding.deleteRememberTitle.text = message
view.skip_the_recycle_bin_checkbox.beGoneIf(!showSkipRecycleBinOption) binding.skipTheRecycleBinCheckbox.beGoneIf(!showSkipRecycleBinOption)
activity.getAlertDialogBuilder() activity.getAlertDialogBuilder()
.setPositiveButton(R.string.yes) { _, _ -> dialogConfirmed() } .setPositiveButton(R.string.yes) { _, _ -> dialogConfirmed() }
.setNegativeButton(R.string.no, null) .setNegativeButton(R.string.no, null)
.apply { .apply {
activity.setupDialogStuff(view, this) { alertDialog -> activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog dialog = alertDialog
} }
} }
@ -34,6 +33,6 @@ class DeleteConfirmationDialog(
private fun dialogConfirmed() { private fun dialogConfirmed() {
dialog?.dismiss() dialog?.dismiss()
callback(view.skip_the_recycle_bin_checkbox.isChecked) callback(binding.skipTheRecycleBinCheckbox.isChecked)
} }
} }

View File

@ -1,14 +1,11 @@
package com.simplemobiletools.smsmessenger.dialogs package com.simplemobiletools.smsmessenger.dialogs
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.databinding.DialogExportMessagesBinding
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import kotlinx.android.synthetic.main.dialog_export_messages.view.export_messages_filename
import kotlinx.android.synthetic.main.dialog_export_messages.view.export_mms_checkbox
import kotlinx.android.synthetic.main.dialog_export_messages.view.export_sms_checkbox
class ExportMessagesDialog( class ExportMessagesDialog(
private val activity: SimpleActivity, private val activity: SimpleActivity,
@ -17,10 +14,10 @@ class ExportMessagesDialog(
private val config = activity.config private val config = activity.config
init { init {
val view = (activity.layoutInflater.inflate(R.layout.dialog_export_messages, null) as ViewGroup).apply { val binding = DialogExportMessagesBinding.inflate(activity.layoutInflater).apply {
export_sms_checkbox.isChecked = config.exportSms exportSmsCheckbox.isChecked = config.exportSms
export_mms_checkbox.isChecked = config.exportMms exportMmsCheckbox.isChecked = config.exportMms
export_messages_filename.setText( exportMessagesFilename.setText(
activity.getString(R.string.messages) + "_" + activity.getCurrentFormattedDateTime() activity.getString(R.string.messages) + "_" + activity.getCurrentFormattedDateTime()
) )
} }
@ -29,11 +26,11 @@ class ExportMessagesDialog(
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.apply { .apply {
activity.setupDialogStuff(view, this, R.string.export_messages) { alertDialog -> activity.setupDialogStuff(binding.root, this, R.string.export_messages) { alertDialog ->
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
config.exportSms = view.export_sms_checkbox.isChecked config.exportSms = binding.exportSmsCheckbox.isChecked
config.exportMms = view.export_mms_checkbox.isChecked config.exportMms = binding.exportMmsCheckbox.isChecked
val filename = view.export_messages_filename.value val filename = binding.exportMessagesFilename.value
when { when {
filename.isEmpty() -> activity.toast(R.string.empty_name) filename.isEmpty() -> activity.toast(R.string.empty_name)
filename.isAValidFilename() -> { filename.isAValidFilename() -> {

View File

@ -1,6 +1,5 @@
package com.simplemobiletools.smsmessenger.dialogs package com.simplemobiletools.smsmessenger.dialogs
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
@ -8,11 +7,11 @@ import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.databinding.DialogImportMessagesBinding
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.helpers.MessagesImporter import com.simplemobiletools.smsmessenger.helpers.MessagesImporter
import com.simplemobiletools.smsmessenger.models.MessagesBackup
import com.simplemobiletools.smsmessenger.models.ImportResult import com.simplemobiletools.smsmessenger.models.ImportResult
import kotlinx.android.synthetic.main.dialog_import_messages.view.* import com.simplemobiletools.smsmessenger.models.MessagesBackup
class ImportMessagesDialog( class ImportMessagesDialog(
private val activity: SimpleActivity, private val activity: SimpleActivity,
@ -23,30 +22,30 @@ class ImportMessagesDialog(
init { init {
var ignoreClicks = false var ignoreClicks = false
val view = (activity.layoutInflater.inflate(R.layout.dialog_import_messages, null) as ViewGroup).apply { val binding = DialogImportMessagesBinding.inflate(activity.layoutInflater).apply {
import_sms_checkbox.isChecked = config.importSms importSmsCheckbox.isChecked = config.importSms
import_mms_checkbox.isChecked = config.importMms importMmsCheckbox.isChecked = config.importMms
} }
activity.getAlertDialogBuilder() activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.apply { .apply {
activity.setupDialogStuff(view, this, R.string.import_messages) { alertDialog -> activity.setupDialogStuff(binding.root, this, R.string.import_messages) { alertDialog ->
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
if (ignoreClicks) { if (ignoreClicks) {
return@setOnClickListener return@setOnClickListener
} }
if (!view.import_sms_checkbox.isChecked && !view.import_mms_checkbox.isChecked) { if (!binding.importSmsCheckbox.isChecked && !binding.importMmsCheckbox.isChecked) {
activity.toast(R.string.no_option_selected) activity.toast(R.string.no_option_selected)
return@setOnClickListener return@setOnClickListener
} }
ignoreClicks = true ignoreClicks = true
activity.toast(R.string.importing) activity.toast(R.string.importing)
config.importSms = view.import_sms_checkbox.isChecked config.importSms = binding.importSmsCheckbox.isChecked
config.importMms = view.import_mms_checkbox.isChecked config.importMms = binding.importMmsCheckbox.isChecked
ensureBackgroundThread { ensureBackgroundThread {
MessagesImporter(activity).restoreMessages(messages) { MessagesImporter(activity).restoreMessages(messages) {
handleParseResult(it) handleParseResult(it)

View File

@ -4,18 +4,18 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import kotlinx.android.synthetic.main.dialog_invalid_number.view.* import com.simplemobiletools.smsmessenger.databinding.DialogInvalidNumberBinding
class InvalidNumberDialog(val activity: BaseSimpleActivity, val text: String) { class InvalidNumberDialog(val activity: BaseSimpleActivity, val text: String) {
init { init {
val view = activity.layoutInflater.inflate(R.layout.dialog_invalid_number, null).apply { val binding = DialogInvalidNumberBinding.inflate(activity.layoutInflater).apply {
dialog_invalid_number_desc.text = text dialogInvalidNumberDesc.text = text
} }
activity.getAlertDialogBuilder() activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { _, _ -> { } } .setPositiveButton(R.string.ok) { _, _ -> { } }
.apply { .apply {
activity.setupDialogStuff(view, this) activity.setupDialogStuff(binding.root, this)
} }
} }
} }

View File

@ -11,11 +11,8 @@ import com.simplemobiletools.commons.extensions.setupViewBackground
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.databinding.ItemManageBlockedKeywordBinding
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import kotlinx.android.synthetic.main.item_manage_blocked_keyword.view.manage_blocked_keyword_holder
import kotlinx.android.synthetic.main.item_manage_blocked_keyword.view.manage_blocked_keyword_title
import kotlinx.android.synthetic.main.item_manage_blocked_keyword.view.overflow_menu_anchor
import kotlinx.android.synthetic.main.item_manage_blocked_keyword.view.overflow_menu_icon
class ManageBlockedKeywordsAdapter( class ManageBlockedKeywordsAdapter(
activity: BaseSimpleActivity, var blockedKeywords: ArrayList<String>, val listener: RefreshRecyclerViewListener?, activity: BaseSimpleActivity, var blockedKeywords: ArrayList<String>, val listener: RefreshRecyclerViewListener?,
@ -56,11 +53,14 @@ class ManageBlockedKeywordsAdapter(
override fun onActionModeDestroyed() {} override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_manage_blocked_keyword, parent) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemManageBlockedKeywordBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val blockedKeyword = blockedKeywords[position] val blockedKeyword = blockedKeywords[position]
holder.bindView(blockedKeyword, true, true) { itemView, _ -> holder.bindView(blockedKeyword, allowSingleClick = true, allowLongClick = true) { itemView, _ ->
setupView(itemView, blockedKeyword) setupView(itemView, blockedKeyword)
} }
bindViewHolder(holder) bindViewHolder(holder)
@ -71,21 +71,21 @@ class ManageBlockedKeywordsAdapter(
private fun getSelectedItems() = blockedKeywords.filter { selectedKeys.contains(it.hashCode()) } private fun getSelectedItems() = blockedKeywords.filter { selectedKeys.contains(it.hashCode()) }
private fun setupView(view: View, blockedKeyword: String) { private fun setupView(view: View, blockedKeyword: String) {
view.apply { ItemManageBlockedKeywordBinding.bind(view).apply {
setupViewBackground(activity) root.setupViewBackground(activity)
manage_blocked_keyword_holder?.isSelected = selectedKeys.contains(blockedKeyword.hashCode()) manageBlockedKeywordHolder.isSelected = selectedKeys.contains(blockedKeyword.hashCode())
manage_blocked_keyword_title.apply { manageBlockedKeywordTitle.apply {
text = blockedKeyword text = blockedKeyword
setTextColor(textColor) setTextColor(textColor)
} }
overflow_menu_icon.drawable.apply { overflowMenuIcon.drawable.apply {
mutate() mutate()
setTint(activity.getProperTextColor()) setTint(activity.getProperTextColor())
} }
overflow_menu_icon.setOnClickListener { overflowMenuIcon.setOnClickListener {
showPopupMenu(overflow_menu_anchor, blockedKeyword) showPopupMenu(overflowMenuAnchor, blockedKeyword)
} }
} }
} }

View File

@ -25,7 +25,7 @@ class MessageDetailsDialog(val activity: BaseSimpleActivity, val message: Messag
activity.getAlertDialogBuilder() activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { _, _ -> } .setPositiveButton(R.string.ok) { _, _ -> }
.apply { .apply {
activity.setupDialogStuff(mDialogView, this, R.string.message_details) activity.setupDialogStuff(mDialogView.root, this, R.string.message_details)
} }
} }

View File

@ -2,15 +2,14 @@ package com.simplemobiletools.smsmessenger.dialogs
import android.app.Activity import android.app.Activity
import android.content.DialogInterface.BUTTON_POSITIVE import android.content.DialogInterface.BUTTON_POSITIVE
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.showKeyboard import com.simplemobiletools.commons.extensions.showKeyboard
import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.databinding.DialogRenameConversationBinding
import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Conversation
import kotlinx.android.synthetic.main.dialog_rename_conversation.view.*
class RenameConversationDialog( class RenameConversationDialog(
private val activity: Activity, private val activity: Activity,
@ -20,8 +19,8 @@ class RenameConversationDialog(
private var dialog: AlertDialog? = null private var dialog: AlertDialog? = null
init { init {
val view = (activity.layoutInflater.inflate(R.layout.dialog_rename_conversation, null) as ViewGroup).apply { val binding = DialogRenameConversationBinding.inflate(activity.layoutInflater).apply {
rename_conv_edit_text.apply { renameConvEditText.apply {
if (conversation.usesCustomTitle) { if (conversation.usesCustomTitle) {
setText(conversation.title) setText(conversation.title)
} }
@ -34,12 +33,12 @@ class RenameConversationDialog(
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.apply { .apply {
activity.setupDialogStuff(view, this, R.string.rename_conversation) { alertDialog -> activity.setupDialogStuff(binding.root, this, R.string.rename_conversation) { alertDialog ->
dialog = alertDialog dialog = alertDialog
alertDialog.showKeyboard(view.rename_conv_edit_text) alertDialog.showKeyboard(binding.renameConvEditText)
alertDialog.getButton(BUTTON_POSITIVE).apply { alertDialog.getButton(BUTTON_POSITIVE).apply {
setOnClickListener { setOnClickListener {
val newTitle = view.rename_conv_edit_text.text.toString() val newTitle = binding.renameConvEditText.text.toString()
if (newTitle.isEmpty()) { if (newTitle.isEmpty()) {
activity.toast(R.string.empty_name) activity.toast(R.string.empty_name)
return@setOnClickListener return@setOnClickListener

View File

@ -11,18 +11,18 @@ import com.google.android.material.timepicker.TimeFormat
import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.databinding.ScheduleMessageDialogBinding
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.extensions.roundToClosestMultipleOf import com.simplemobiletools.smsmessenger.extensions.roundToClosestMultipleOf
import kotlinx.android.synthetic.main.schedule_message_dialog.view.*
import org.joda.time.DateTime import org.joda.time.DateTime
import java.util.* import java.util.Calendar
class ScheduleMessageDialog( class ScheduleMessageDialog(
private val activity: BaseSimpleActivity, private val activity: BaseSimpleActivity,
private var dateTime: DateTime? = null, private var dateTime: DateTime? = null,
private val callback: (dateTime: DateTime?) -> Unit private val callback: (dateTime: DateTime?) -> Unit
) { ) {
private val view = activity.layoutInflater.inflate(R.layout.schedule_message_dialog, null) private val binding = ScheduleMessageDialogBinding.inflate(activity.layoutInflater)
private val textColor = activity.getProperTextColor() private val textColor = activity.getProperTextColor()
private var previewDialog: AlertDialog? = null private var previewDialog: AlertDialog? = null
@ -32,16 +32,16 @@ class ScheduleMessageDialog(
private val calendar = Calendar.getInstance() private val calendar = Calendar.getInstance()
init { init {
arrayOf(view.subtitle, view.edit_time, view.edit_date).forEach { arrayOf(binding.subtitle, binding.editTime, binding.editDate).forEach {
it.setTextColor(textColor) it.setTextColor(textColor)
} }
arrayOf(view.date_image, view.time_image).forEach { arrayOf(binding.dateImage, binding.timeImage).forEach {
it.applyColorFilter(textColor) it.applyColorFilter(textColor)
} }
view.edit_date.setOnClickListener { showDatePicker() } binding.editDate.setOnClickListener { showDatePicker() }
view.edit_time.setOnClickListener { showTimePicker() } binding.editTime.setOnClickListener { showTimePicker() }
val targetDateTime = dateTime ?: DateTime.now().plusHours(1) val targetDateTime = dateTime ?: DateTime.now().plusHours(1)
updateTexts(targetDateTime) updateTexts(targetDateTime)
@ -56,8 +56,8 @@ class ScheduleMessageDialog(
private fun updateTexts(dateTime: DateTime) { private fun updateTexts(dateTime: DateTime) {
val dateFormat = activity.config.dateFormat val dateFormat = activity.config.dateFormat
val timeFormat = activity.getTimeFormat() val timeFormat = activity.getTimeFormat()
view.edit_date.text = dateTime.toString(dateFormat) binding.editDate.text = dateTime.toString(dateFormat)
view.edit_time.text = dateTime.toString(timeFormat) binding.editTime.text = dateTime.toString(timeFormat)
} }
private fun showPreview() { private fun showPreview() {
@ -70,7 +70,7 @@ class ScheduleMessageDialog(
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.apply { .apply {
previewShown = true previewShown = true
activity.setupDialogStuff(view, this, R.string.schedule_message) { dialog -> activity.setupDialogStuff(binding.root, this, R.string.schedule_message) { dialog ->
previewDialog = dialog previewDialog = dialog
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
if (validateDateTime()) { if (validateDateTime()) {

View File

@ -4,19 +4,19 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import kotlinx.android.synthetic.main.dialog_select_text.view.* import com.simplemobiletools.smsmessenger.databinding.DialogSelectTextBinding
// helper dialog for selecting just a part of a message, not copying the whole into clipboard // helper dialog for selecting just a part of a message, not copying the whole into clipboard
class SelectTextDialog(val activity: BaseSimpleActivity, val text: String) { class SelectTextDialog(val activity: BaseSimpleActivity, val text: String) {
init { init {
val view = activity.layoutInflater.inflate(R.layout.dialog_select_text, null).apply { val binding = DialogSelectTextBinding.inflate(activity.layoutInflater).apply {
dialog_select_text_value.text = text dialogSelectTextValue.text = text
} }
activity.getAlertDialogBuilder() activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> { } } .setPositiveButton(R.string.ok) { _, _ -> { } }
.apply { .apply {
activity.setupDialogStuff(view, this) activity.setupDialogStuff(binding.root, this)
} }
} }
} }

View File

@ -2,26 +2,44 @@ package com.simplemobiletools.smsmessenger.helpers
import android.app.Activity import android.app.Activity
import android.net.Uri import android.net.Uri
import android.view.View
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.databinding.ItemAttachmentDocumentBinding
import com.simplemobiletools.smsmessenger.databinding.ItemAttachmentDocumentPreviewBinding
import com.simplemobiletools.smsmessenger.databinding.ItemAttachmentVcardBinding
import com.simplemobiletools.smsmessenger.databinding.ItemAttachmentVcardPreviewBinding
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import kotlinx.android.synthetic.main.item_attachment_document.view.*
import kotlinx.android.synthetic.main.item_attachment_vcard.view.*
import kotlinx.android.synthetic.main.item_attachment_vcard_preview.view.*
import kotlinx.android.synthetic.main.item_remove_attachment_button.view.*
fun View.setupDocumentPreview( fun ItemAttachmentDocumentPreviewBinding.setupDocumentPreview(
uri: Uri, uri: Uri,
title: String, title: String,
mimeType: String, mimeType: String,
attachment: Boolean = false,
onClick: (() -> Unit)? = null, onClick: (() -> Unit)? = null,
onLongClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null,
onRemoveButtonClicked: (() -> Unit)? = null onRemoveButtonClicked: (() -> Unit)? = null
) { ) {
documentAttachmentHolder.setupDocumentPreview(uri, title, mimeType, onClick, onLongClick)
removeAttachmentButtonHolder.removeAttachmentButton.apply {
beVisible()
background.applyColorFilter(context.getProperPrimaryColor())
if (onRemoveButtonClicked != null) {
setOnClickListener {
onRemoveButtonClicked.invoke()
}
}
}
}
fun ItemAttachmentDocumentBinding.setupDocumentPreview(
uri: Uri,
title: String,
mimeType: String,
onClick: (() -> Unit)? = null,
onLongClick: (() -> Unit)? = null
) {
val context = root.context
if (title.isNotEmpty()) { if (title.isNotEmpty()) {
filename.text = title filename.text = title
} }
@ -29,13 +47,13 @@ fun View.setupDocumentPreview(
ensureBackgroundThread { ensureBackgroundThread {
try { try {
val size = context.getFileSizeFromUri(uri) val size = context.getFileSizeFromUri(uri)
post { root.post {
file_size.beVisible() fileSize.beVisible()
file_size.text = size.formatSize() fileSize.text = size.formatSize()
} }
} catch (e: Exception) { } catch (e: Exception) {
post { root.post {
file_size.beGone() fileSize.beGone()
} }
} }
} }
@ -43,18 +61,35 @@ fun View.setupDocumentPreview(
val textColor = context.getProperTextColor() val textColor = context.getProperTextColor()
val primaryColor = context.getProperPrimaryColor() val primaryColor = context.getProperPrimaryColor()
document_attachment_holder.background.applyColorFilter(textColor)
filename.setTextColor(textColor) filename.setTextColor(textColor)
file_size.setTextColor(textColor) fileSize.setTextColor(textColor)
icon.setImageResource(getIconResourceForMimeType(mimeType)) icon.setImageResource(getIconResourceForMimeType(mimeType))
icon.background.setTint(primaryColor) icon.background.setTint(primaryColor)
document_attachment_holder.background.applyColorFilter(primaryColor.darkenColor()) root.background.applyColorFilter(primaryColor.darkenColor())
if (attachment) { root.setOnClickListener {
remove_attachment_button.apply { onClick?.invoke()
}
root.setOnLongClickListener {
onLongClick?.invoke()
true
}
}
fun ItemAttachmentVcardPreviewBinding.setupVCardPreview(
activity: Activity,
uri: Uri,
onClick: (() -> Unit)? = null,
onLongClick: (() -> Unit)? = null,
onRemoveButtonClicked: (() -> Unit)? = null,
) {
vcardProgress.beVisible()
vcardAttachmentHolder.setupVCardPreview(activity = activity, uri = uri, attachment = true, onClick = onClick, onLongClick = onLongClick) {
vcardProgress.beGone()
removeAttachmentButtonHolder.removeAttachmentButton.apply {
beVisible() beVisible()
background.applyColorFilter(primaryColor) background.applyColorFilter(activity.getProperPrimaryColor())
if (onRemoveButtonClicked != null) { if (onRemoveButtonClicked != null) {
setOnClickListener { setOnClickListener {
onRemoveButtonClicked.invoke() onRemoveButtonClicked.invoke()
@ -62,45 +97,36 @@ fun View.setupDocumentPreview(
} }
} }
} }
document_attachment_holder.setOnClickListener {
onClick?.invoke()
}
document_attachment_holder.setOnLongClickListener {
onLongClick?.invoke()
true
}
} }
fun View.setupVCardPreview( fun ItemAttachmentVcardBinding.setupVCardPreview(
activity: Activity, activity: Activity,
uri: Uri, uri: Uri,
attachment: Boolean = false, attachment: Boolean = false,
onClick: (() -> Unit)? = null, onClick: (() -> Unit)? = null,
onLongClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null,
onRemoveButtonClicked: (() -> Unit)? = null, onVCardLoaded: (() -> Unit)? = null,
) { ) {
val context = root.context
val textColor = activity.getProperTextColor() val textColor = activity.getProperTextColor()
val primaryColor = activity.getProperPrimaryColor() val primaryColor = activity.getProperPrimaryColor()
vcard_attachment_holder.background.applyColorFilter(primaryColor.darkenColor()) root.background.applyColorFilter(primaryColor.darkenColor())
vcard_title.setTextColor(textColor) vcardTitle.setTextColor(textColor)
vcard_subtitle.setTextColor(textColor) vcardSubtitle.setTextColor(textColor)
if (attachment) { arrayOf(vcardPhoto, vcardTitle, vcardSubtitle, viewContactDetails).forEach {
vcard_progress.beVisible()
}
arrayOf(vcard_photo, vcard_title, vcard_subtitle, view_contact_details).forEach {
it.beGone() it.beGone()
} }
parseVCardFromUri(activity, uri) { vCards -> parseVCardFromUri(activity, uri) { vCards ->
activity.runOnUiThread { activity.runOnUiThread {
if (vCards.isEmpty()) { if (vCards.isEmpty()) {
vcard_title.beVisible() vcardTitle.beVisible()
vcard_title.text = context.getString(R.string.unknown_error_occurred) vcardTitle.text = context.getString(R.string.unknown_error_occurred)
return@runOnUiThread return@runOnUiThread
} }
val title = vCards.firstOrNull()?.parseNameFromVCard() val title = vCards.firstOrNull()?.parseNameFromVCard()
val imageIcon = if (title != null) { val imageIcon = if (title != null) {
SimpleContactsHelper(activity).getContactLetterIcon(title) SimpleContactsHelper(activity).getContactLetterIcon(title)
@ -108,41 +134,32 @@ fun View.setupVCardPreview(
null null
} }
arrayOf(vcard_photo, vcard_title).forEach { arrayOf(vcardPhoto, vcardTitle).forEach {
it.beVisible() it.beVisible()
} }
vcard_photo.setImageBitmap(imageIcon) vcardPhoto.setImageBitmap(imageIcon)
vcard_title.text = title vcardTitle.text = title
if (vCards.size > 1) { if (vCards.size > 1) {
vcard_subtitle.beVisible() vcardSubtitle.beVisible()
val quantity = vCards.size - 1 val quantity = vCards.size - 1
vcard_subtitle.text = resources.getQuantityString(R.plurals.and_other_contacts, quantity, quantity) vcardSubtitle.text = context.resources.getQuantityString(R.plurals.and_other_contacts, quantity, quantity)
} else { } else {
vcard_subtitle.beGone() vcardSubtitle.beGone()
} }
if (attachment) { if (attachment) {
vcard_progress.beGone() onVCardLoaded?.invoke()
remove_attachment_button.apply {
beVisible()
background.applyColorFilter(primaryColor)
if (onRemoveButtonClicked != null) {
setOnClickListener {
onRemoveButtonClicked.invoke()
}
}
}
} else { } else {
view_contact_details.setTextColor(primaryColor) viewContactDetails.setTextColor(primaryColor)
view_contact_details.beVisible() viewContactDetails.beVisible()
} }
vcard_attachment_holder.setOnClickListener { vcardAttachmentHolder.setOnClickListener {
onClick?.invoke() onClick?.invoke()
} }
vcard_attachment_holder.setOnLongClickListener { vcardAttachmentHolder.setOnLongClickListener {
onLongClick?.invoke() onLongClick?.invoke()
true true
} }

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="@dimen/small_icon_size"
android:height="@dimen/small_icon_size"
android:drawable="@drawable/ic_clock_vector" />
</layer-list>

View File

@ -102,7 +102,7 @@
android:id="@+id/thread_messages_fastscroller" android:id="@+id/thread_messages_fastscroller"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/reply_disabled_info_holder" app:layout_constraintBottom_toTopOf="@id/short_code_holder"
app:layout_constraintTop_toBottomOf="@id/thread_add_contacts" app:layout_constraintTop_toBottomOf="@id/thread_add_contacts"
app:supportSwipeToRefresh="true"> app:supportSwipeToRefresh="true">
@ -117,7 +117,7 @@
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager"
app:stackFromEnd="true" app:stackFromEnd="true"
tools:itemCount="3" tools:itemCount="3"
tools:listitem="@layout/item_sent_message" /> tools:listitem="@layout/item_message" />
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller> </com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
@ -134,6 +134,7 @@
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<include <include
android:id="@+id/short_code_holder"
layout="@layout/layout_invalid_short_code_info" layout="@layout/layout_invalid_short_code_info"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -145,6 +146,7 @@
tools:visibility="visible" /> tools:visibility="visible" />
<include <include
android:id="@+id/thread_send_message_holder"
layout="@layout/layout_thread_send_message_holder" layout="@layout/layout_thread_send_message_holder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -6,6 +6,7 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<include <include
android:id="@+id/document_attachment_holder"
layout="@layout/item_attachment_document" layout="@layout/item_attachment_document"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -19,6 +20,7 @@
app:layout_constraintWidth_max="@dimen/attachment_preview_max_width" /> app:layout_constraintWidth_max="@dimen/attachment_preview_max_width" />
<include <include
android:id="@+id/remove_attachment_button_holder"
layout="@layout/item_remove_attachment_button" layout="@layout/item_remove_attachment_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -44,6 +44,7 @@
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
<include <include
android:id="@+id/remove_attachment_button_holder"
layout="@layout/item_remove_attachment_button" layout="@layout/item_remove_attachment_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -6,6 +6,7 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<include <include
android:id="@+id/vcard_attachment_holder"
layout="@layout/item_attachment_vcard" layout="@layout/item_attachment_vcard"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -28,6 +29,7 @@
app:layout_constraintTop_toTopOf="@id/vcard_attachment_holder" /> app:layout_constraintTop_toTopOf="@id/vcard_attachment_holder" />
<include <include
android:id="@+id/remove_attachment_button_holder"
layout="@layout/item_remove_attachment_button" layout="@layout/item_remove_attachment_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -5,11 +5,9 @@
android:id="@+id/thread_message_holder" android:id="@+id/thread_message_holder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin" android:layout_marginTop="@dimen/small_margin"
android:layout_marginBottom="@dimen/medium_margin"
android:foreground="@drawable/selector" android:foreground="@drawable/selector"
android:paddingStart="@dimen/activity_margin" android:paddingHorizontal="@dimen/activity_margin">
android:paddingEnd="@dimen/activity_margin">
<RelativeLayout <RelativeLayout
android:id="@+id/thread_message_wrapper" android:id="@+id/thread_message_wrapper"
@ -27,13 +25,14 @@
android:layout_alignBottom="@+id/thread_message_body" android:layout_alignBottom="@+id/thread_message_body"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_marginEnd="@dimen/medium_margin" android:layout_marginEnd="@dimen/medium_margin"
android:visibility="gone" /> android:src="@drawable/ic_person_vector"
android:visibility="gone"
tools:visibility="visible" />
<LinearLayout <LinearLayout
android:id="@+id/thread_mesage_attachments_holder" android:id="@+id/thread_message_attachments_holder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toEndOf="@+id/thread_message_sender_photo"
android:divider="@drawable/linear_layout_vertical_divider" android:divider="@drawable/linear_layout_vertical_divider"
android:orientation="vertical" android:orientation="vertical"
android:showDividers="middle" /> android:showDividers="middle" />
@ -42,23 +41,26 @@
android:id="@+id/thread_message_play_outline" android:id="@+id/thread_message_play_outline"
android:layout_width="@dimen/play_outline_size" android:layout_width="@dimen/play_outline_size"
android:layout_height="@dimen/play_outline_size" android:layout_height="@dimen/play_outline_size"
android:layout_alignEnd="@+id/thread_mesage_attachments_holder" android:layout_alignEnd="@+id/thread_message_attachments_holder"
android:layout_alignBottom="@+id/thread_mesage_attachments_holder" android:layout_alignBottom="@+id/thread_message_attachments_holder"
android:layout_marginStart="@dimen/medium_margin" android:layout_marginEnd="@dimen/medium_margin"
android:layout_marginBottom="@dimen/activity_margin" android:layout_marginBottom="@dimen/activity_margin"
android:src="@drawable/ic_play_outline_vector" android:src="@drawable/ic_play_outline_vector"
android:visibility="gone" /> android:visibility="gone" />
<TextView <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/thread_message_body" android:id="@+id/thread_message_body"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/thread_mesage_attachments_holder" android:layout_below="@+id/thread_message_attachments_holder"
android:layout_toEndOf="@+id/thread_message_sender_photo" android:layout_marginVertical="@dimen/tiny_margin"
android:layout_toEndOf="@id/thread_message_sender_photo"
android:autoLink="email|web" android:autoLink="email|web"
android:background="@drawable/item_received_background" android:background="@drawable/item_received_background"
android:drawablePadding="8dp"
android:padding="@dimen/normal_margin" android:padding="@dimen/normal_margin"
android:textSize="@dimen/normal_text_size" android:textSize="@dimen/normal_text_size"
tools:text="Received message" /> tools:drawableEndCompat="@drawable/scheduled_message_icon"
tools:text="Message content" />
</RelativeLayout> </RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/thread_message_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/small_margin"
android:foreground="@drawable/selector"
android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin">
<RelativeLayout
android:id="@+id/thread_message_wrapper"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.8">
<LinearLayout
android:id="@+id/thread_mesage_attachments_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/tiny_margin"
android:divider="@drawable/linear_layout_vertical_divider"
android:orientation="vertical"
android:showDividers="middle" />
<ImageView
android:id="@+id/thread_message_play_outline"
android:layout_width="@dimen/play_outline_size"
android:layout_height="@dimen/play_outline_size"
android:layout_alignEnd="@+id/thread_mesage_attachments_holder"
android:layout_alignBottom="@+id/thread_mesage_attachments_holder"
android:layout_marginEnd="@dimen/medium_margin"
android:layout_marginBottom="@dimen/activity_margin"
android:src="@drawable/ic_play_outline_vector"
android:visibility="gone" />
<TextView
android:id="@+id/thread_message_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/thread_mesage_attachments_holder"
android:layout_alignParentEnd="true"
android:layout_marginVertical="@dimen/tiny_margin"
android:autoLink="email|web"
android:background="@drawable/item_sent_background"
android:padding="@dimen/normal_margin"
android:textSize="@dimen/normal_text_size"
tools:text="Sent message" />
</RelativeLayout>
<ImageView
android:id="@+id/thread_message_scheduled_icon"
android:layout_width="@dimen/small_icon_size"
android:layout_height="@dimen/small_icon_size"
android:layout_margin="@dimen/tiny_margin"
android:src="@drawable/ic_clock_vector"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/reply_disabled_info_holder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"

View File

@ -29,7 +29,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignTop="@+id/scheduled_message_button" android:layout_alignTop="@+id/scheduled_message_button"
android:layout_alignBottom="@+id/scheduled_message_button" android:layout_alignBottom="@+id/scheduled_message_button"
android:paddingStart="@dimen/medium_margin"
android:paddingTop="@dimen/medium_margin" android:paddingTop="@dimen/medium_margin"
android:paddingEnd="@dimen/small_margin"
android:paddingBottom="@dimen/medium_margin" android:paddingBottom="@dimen/medium_margin"
android:src="@drawable/ic_clock_vector" /> android:src="@drawable/ic_clock_vector" />
@ -202,6 +204,7 @@
tools:visibility="visible"> tools:visibility="visible">
<include <include
android:id="@+id/attachment_picker"
layout="@layout/layout_attachment_picker" layout="@layout/layout_attachment_picker"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />