diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 24c62f3e..00000000 --- a/app/build.gradle +++ /dev/null @@ -1,82 +0,0 @@ -plugins { - id 'com.android.application' - id 'kotlin-android' - id 'kotlin-android-extensions' - id 'kotlin-kapt' - id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version" -} - -def keystorePropertiesFile = rootProject.file("keystore.properties") -def keystoreProperties = new Properties() -if (keystorePropertiesFile.exists()) { - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) -} - -android { - compileSdkVersion 33 - - defaultConfig { - applicationId "com.simplemobiletools.smsmessenger" - minSdkVersion 23 - targetSdkVersion 33 - versionCode 79 - versionName "5.18.2" - setProperty("archivesBaseName", "sms-messenger") - } - - signingConfigs { - if (keystorePropertiesFile.exists()) { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile file(keystoreProperties['storeFile']) - storePassword keystoreProperties['storePassword'] - } - } - } - - buildTypes { - debug { - applicationIdSuffix ".debug" - } - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - if (keystorePropertiesFile.exists()) { - signingConfig signingConfigs.release - } - } - } - - flavorDimensions "variants" - productFlavors { - core {} - fdroid {} - prepaid {} - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - lintOptions { - checkReleaseBuilds false - abortOnError false - } -} - -dependencies { - implementation 'com.github.SimpleMobileTools:Simple-Commons:8814cd2d4b' - implementation 'org.greenrobot:eventbus:3.3.1' - implementation 'com.github.tibbi:IndicatorFastScroll:4524cd0b61' - implementation 'com.github.tibbi:android-smsmms:5657799572' - implementation "me.leolin:ShortcutBadger:1.1.22" - implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' - implementation 'com.googlecode.ez-vcard:ez-vcard:0.11.3' - implementation 'androidx.lifecycle:lifecycle-process:2.5.1' - implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1" - - kapt "androidx.room:room-compiler:2.5.2" - implementation "androidx.room:room-runtime:2.5.2" - annotationProcessor "androidx.room:room-compiler:2.5.2" -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 00000000..fa4382cc --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,105 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.konan.properties.Properties +import java.io.FileInputStream + +plugins { + alias(libs.plugins.android) + alias(libs.plugins.kotlinAndroid) + alias(libs.plugins.kotlinSerialization) + alias(libs.plugins.parcelize) + alias(libs.plugins.ksp) +} + +val keystorePropertiesFile: File = rootProject.file("keystore.properties") +val keystoreProperties = Properties() +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(FileInputStream(keystorePropertiesFile)) +} + +android { + compileSdk = project.libs.versions.app.build.compileSDKVersion.get().toInt() + + defaultConfig { + applicationId = libs.versions.app.version.appId.get() + minSdk = project.libs.versions.app.build.minimumSDK.get().toInt() + targetSdk = project.libs.versions.app.build.targetSDK.get().toInt() + versionName = project.libs.versions.app.version.versionName.get() + versionCode = project.libs.versions.app.version.versionCode.get().toInt() + setProperty("archivesBaseName", "sms-messenger") + } + + signingConfigs { + create("release") { + if (keystorePropertiesFile.exists()) { + keyAlias = keystoreProperties["keyAlias"] as String + keyPassword = keystoreProperties["keyPassword"] as String + storeFile = file(keystoreProperties["storeFile"] as String) + storePassword = keystoreProperties["storePassword"] as String + } + } + } + + buildFeatures { + viewBinding = true + buildConfig = true + } + + buildTypes { + debug { + applicationIdSuffix = ".debug" + } + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + if (keystorePropertiesFile.exists()) { + signingConfig = signingConfigs.getByName("release") + } + } + } + + flavorDimensions.add("variants") + productFlavors { + register("core") + register("fdroid") + register("prepaid") + } + + sourceSets { + getByName("main").java.srcDirs("src/main/kotlin") + } + + compileOptions { + val currentJavaVersionFromLibs = JavaVersion.valueOf(libs.versions.app.build.javaVersion.get().toString()) + sourceCompatibility = currentJavaVersionFromLibs + targetCompatibility = currentJavaVersionFromLibs + } + + tasks.withType { + kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get() + } + + namespace = libs.versions.app.version.appId.get() + + lint { + checkReleaseBuilds = false + abortOnError = false + } +} + +dependencies { + implementation(libs.simple.mobile.tools.commons) + implementation(libs.eventbus) + implementation(libs.indicator.fast.scroll) + implementation(libs.android.smsmms) + implementation(libs.shortcut.badger) + implementation(libs.androidx.swiperefreshlayout) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.lifecycle.process) + implementation(libs.ez.vcard) + implementation(libs.kotlinx.serialization.json) + implementation(libs.bundles.room) + ksp(libs.androidx.room.compiler) +} diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ArchivedConversationsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ArchivedConversationsActivity.kt index 27b52fe3..f0bd876f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ArchivedConversationsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ArchivedConversationsActivity.kt @@ -8,34 +8,40 @@ import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.adapters.ArchivedConversationsAdapter +import com.simplemobiletools.smsmessenger.databinding.ActivityArchivedConversationsBinding import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Events -import kotlinx.android.synthetic.main.activity_archived_conversations.* import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode class ArchivedConversationsActivity : SimpleActivity() { private var bus: EventBus? = null + private val binding by viewBinding(ActivityArchivedConversationsBinding::inflate) @SuppressLint("InlinedApi") override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_archived_conversations) + setContentView(binding.root) setupOptionsMenu() - updateMaterialActivityViews(archive_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = false) - setupMaterialScrollListener(conversations_list, archive_toolbar) + updateMaterialActivityViews( + mainCoordinatorLayout = binding.archiveCoordinator, + nestedView = binding.conversationsList, + useTransparentNavigation = true, + useTopSearchMenu = false + ) + setupMaterialScrollListener(scrollingView = binding.conversationsList, toolbar = binding.archiveToolbar) loadArchivedConversations() } override fun onResume() { super.onResume() - setupToolbar(archive_toolbar, NavigationIcon.Arrow) + setupToolbar(binding.archiveToolbar, NavigationIcon.Arrow) updateMenuColors() loadArchivedConversations() @@ -47,9 +53,8 @@ class ArchivedConversationsActivity : SimpleActivity() { } private fun setupOptionsMenu() { - archive_toolbar.inflateMenu(R.menu.archive_menu) - - archive_toolbar.setOnMenuItemClickListener { menuItem -> + binding.archiveToolbar.inflateMenu(R.menu.archive_menu) + binding.archiveToolbar.setOnMenuItemClickListener { menuItem -> when (menuItem.itemId) { R.id.empty_archive -> removeAll() else -> return@setOnMenuItemClickListener false @@ -59,7 +64,7 @@ class ArchivedConversationsActivity : SimpleActivity() { } private fun updateOptionsMenu(conversations: ArrayList) { - archive_toolbar.menu.apply { + binding.archiveToolbar.menu.apply { findItem(R.id.empty_archive).isVisible = conversations.isNotEmpty() } } @@ -84,7 +89,7 @@ class ArchivedConversationsActivity : SimpleActivity() { bus = EventBus.getDefault() try { bus!!.register(this) - } catch (e: Exception) { + } catch (ignored: Exception) { } } @@ -97,19 +102,19 @@ class ArchivedConversationsActivity : SimpleActivity() { } private fun getOrCreateConversationsAdapter(): ArchivedConversationsAdapter { - var currAdapter = conversations_list.adapter + var currAdapter = binding.conversationsList.adapter if (currAdapter == null) { hideKeyboard() currAdapter = ArchivedConversationsAdapter( activity = this, - recyclerView = conversations_list, + recyclerView = binding.conversationsList, onRefresh = { notifyDatasetChanged() }, itemClick = { handleConversationClick(it) } ) - conversations_list.adapter = currAdapter + binding.conversationsList.adapter = currAdapter if (areSystemAnimationsEnabled) { - conversations_list.scheduleLayoutAnimation() + binding.conversationsList.scheduleLayoutAnimation() } } return currAdapter as ArchivedConversationsAdapter @@ -133,9 +138,9 @@ class ArchivedConversationsActivity : SimpleActivity() { } private fun showOrHidePlaceholder(show: Boolean) { - conversations_fastscroller.beGoneIf(show) - no_conversations_placeholder.beVisibleIf(show) - no_conversations_placeholder.text = getString(R.string.no_archived_conversations) + binding.conversationsFastscroller.beGoneIf(show) + binding.noConversationsPlaceholder.beVisibleIf(show) + binding.noConversationsPlaceholder.text = getString(R.string.no_archived_conversations) } @SuppressLint("NotifyDataSetChanged") diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ConversationDetailsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ConversationDetailsActivity.kt index 59f115a5..561c7ceb 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ConversationDetailsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ConversationDetailsActivity.kt @@ -2,20 +2,17 @@ package com.simplemobiletools.smsmessenger.activities import android.os.Bundle import androidx.core.content.res.ResourcesCompat -import com.simplemobiletools.commons.extensions.applyColorFilter -import com.simplemobiletools.commons.extensions.getProperPrimaryColor -import com.simplemobiletools.commons.extensions.getProperTextColor -import com.simplemobiletools.commons.extensions.updateTextColors +import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.NavigationIcon import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.adapters.ContactsAdapter +import com.simplemobiletools.smsmessenger.databinding.ActivityConversationDetailsBinding import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.helpers.THREAD_ID import com.simplemobiletools.smsmessenger.models.Conversation -import kotlinx.android.synthetic.main.activity_conversation_details.* class ConversationDetailsActivity : SimpleActivity() { @@ -23,13 +20,20 @@ class ConversationDetailsActivity : SimpleActivity() { private var conversation: Conversation? = null private lateinit var participants: ArrayList + private val binding by viewBinding(ActivityConversationDetailsBinding::inflate) + override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_conversation_details) + setContentView(binding.root) - updateMaterialActivityViews(conversation_details_coordinator, participants_recyclerview, useTransparentNavigation = true, useTopSearchMenu = false) - setupMaterialScrollListener(participants_recyclerview, conversation_details_toolbar) + updateMaterialActivityViews( + mainCoordinatorLayout = binding.conversationDetailsCoordinator, + nestedView = binding.participantsRecyclerview, + useTransparentNavigation = true, + useTopSearchMenu = false + ) + setupMaterialScrollListener(scrollingView = binding.participantsRecyclerview, toolbar = binding.conversationDetailsToolbar) threadId = intent.getLongExtra(THREAD_ID, 0L) ensureBackgroundThread { @@ -49,16 +53,16 @@ class ConversationDetailsActivity : SimpleActivity() { override fun onResume() { super.onResume() - setupToolbar(conversation_details_toolbar, NavigationIcon.Arrow) - updateTextColors(conversation_details_holder) + setupToolbar(binding.conversationDetailsToolbar, NavigationIcon.Arrow) + updateTextColors(binding.conversationDetailsHolder) val primaryColor = getProperPrimaryColor() - conversation_name_heading.setTextColor(primaryColor) - members_heading.setTextColor(primaryColor) + binding.conversationNameHeading.setTextColor(primaryColor) + binding.membersHeading.setTextColor(primaryColor) } private fun setupTextViews() { - conversation_name.apply { + binding.conversationName.apply { ResourcesCompat.getDrawable(resources, R.drawable.ic_edit_vector, theme)?.apply { applyColorFilter(getProperTextColor()) setCompoundDrawablesWithIntrinsicBounds(null, null, this, null) @@ -77,7 +81,7 @@ class ConversationDetailsActivity : SimpleActivity() { } private fun setupParticipants() { - val adapter = ContactsAdapter(this, participants, participants_recyclerview) { + val adapter = ContactsAdapter(this, participants, binding.participantsRecyclerview) { val contact = it as SimpleContact val address = contact.phoneNumbers.first().normalizedNumber getContactFromAddress(address) { simpleContact -> @@ -86,6 +90,6 @@ class ConversationDetailsActivity : SimpleActivity() { } } } - participants_recyclerview.adapter = adapter + binding.participantsRecyclerview.adapter = adapter } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt index accbab5c..cc41a769 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt @@ -21,13 +21,13 @@ import com.simplemobiletools.smsmessenger.BuildConfig import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter import com.simplemobiletools.smsmessenger.adapters.SearchResultsAdapter +import com.simplemobiletools.smsmessenger.databinding.ActivityMainBinding import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Events import com.simplemobiletools.smsmessenger.models.Message import com.simplemobiletools.smsmessenger.models.SearchResult -import kotlinx.android.synthetic.main.activity_main.* import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode @@ -41,16 +41,23 @@ class MainActivity : SimpleActivity() { private var bus: EventBus? = null private var wasProtectionHandled = false + private val binding by viewBinding(ActivityMainBinding::inflate) + @SuppressLint("InlinedApi") override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) + setContentView(binding.root) appLaunched(BuildConfig.APPLICATION_ID) setupOptionsMenu() refreshMenuItems() - updateMaterialActivityViews(main_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = true) + updateMaterialActivityViews( + mainCoordinatorLayout = binding.mainCoordinator, + nestedView = binding.conversationsList, + useTransparentNavigation = true, + useTopSearchMenu = true + ) if (savedInstanceState == null) { checkAndDeleteOldRecycleBinMessages() @@ -88,17 +95,17 @@ class MainActivity : SimpleActivity() { updateDrafts() } - updateTextColors(main_coordinator) - search_holder.setBackgroundColor(getProperBackgroundColor()) + updateTextColors(binding.mainCoordinator) + binding.searchHolder.setBackgroundColor(getProperBackgroundColor()) val properPrimaryColor = getProperPrimaryColor() - no_conversations_placeholder_2.setTextColor(properPrimaryColor) - no_conversations_placeholder_2.underlineText() - conversations_fastscroller.updateColors(properPrimaryColor) - conversations_progress_bar.setIndicatorColor(properPrimaryColor) - conversations_progress_bar.trackColor = properPrimaryColor.adjustAlpha(LOWER_ALPHA) + binding.noConversationsPlaceholder2.setTextColor(properPrimaryColor) + binding.noConversationsPlaceholder2.underlineText() + binding.conversationsFastscroller.updateColors(properPrimaryColor) + binding.conversationsProgressBar.setIndicatorColor(properPrimaryColor) + binding.conversationsProgressBar.trackColor = properPrimaryColor.adjustAlpha(LOWER_ALPHA) checkShortcut() - (conversations_fab?.layoutParams as? CoordinatorLayout.LayoutParams)?.bottomMargin = + (binding.conversationsFab.layoutParams as? CoordinatorLayout.LayoutParams)?.bottomMargin = navigationBarHeight + resources.getDimension(R.dimen.activity_margin).toInt() } @@ -113,8 +120,8 @@ class MainActivity : SimpleActivity() { } override fun onBackPressed() { - if (main_menu.isSearchOpen) { - main_menu.closeSearch() + if (binding.mainMenu.isSearchOpen) { + binding.mainMenu.closeSearch() } else { super.onBackPressed() } @@ -144,18 +151,18 @@ class MainActivity : SimpleActivity() { } private fun setupOptionsMenu() { - main_menu.getToolbar().inflateMenu(R.menu.menu_main) - main_menu.toggleHideOnScroll(true) - main_menu.setupMenu() + binding.mainMenu.getToolbar().inflateMenu(R.menu.menu_main) + binding.mainMenu.toggleHideOnScroll(true) + binding.mainMenu.setupMenu() - main_menu.onSearchClosedListener = { + binding.mainMenu.onSearchClosedListener = { fadeOutSearch() } - main_menu.onSearchTextChangedListener = { text -> + binding.mainMenu.onSearchTextChangedListener = { text -> if (text.isNotEmpty()) { - if (search_holder.alpha < 1f) { - search_holder.fadeIn() + if (binding.searchHolder.alpha < 1f) { + binding.searchHolder.fadeIn() } } else { fadeOutSearch() @@ -163,7 +170,7 @@ class MainActivity : SimpleActivity() { searchTextChanged(text) } - main_menu.getToolbar().setOnMenuItemClickListener { menuItem -> + binding.mainMenu.getToolbar().setOnMenuItemClickListener { menuItem -> when (menuItem.itemId) { R.id.more_apps_from_us -> launchMoreAppsFromUsIntent() R.id.show_recycle_bin -> launchRecycleBin() @@ -177,7 +184,7 @@ class MainActivity : SimpleActivity() { } 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.show_recycle_bin).isVisible = config.useRecycleBin } @@ -201,7 +208,7 @@ class MainActivity : SimpleActivity() { private fun updateMenuColors() { updateStatusbarColor(getProperBackgroundColor()) - main_menu.updateColors() + binding.mainMenu.updateColors() } private fun loadMessages() { @@ -249,7 +256,7 @@ class MainActivity : SimpleActivity() { bus = EventBus.getDefault() try { bus!!.register(this) - } catch (e: Exception) { + } catch (ignored: Exception) { } } } else { @@ -267,11 +274,11 @@ class MainActivity : SimpleActivity() { storeStateVariables() getCachedConversations() - no_conversations_placeholder_2.setOnClickListener { + binding.noConversationsPlaceholder2.setOnClickListener { launchNewConversation() } - conversations_fab.setOnClickListener { + binding.conversationsFab.setOnClickListener { launchNewConversation() } } @@ -364,19 +371,19 @@ class MainActivity : SimpleActivity() { } private fun getOrCreateConversationsAdapter(): ConversationsAdapter { - var currAdapter = conversations_list.adapter + var currAdapter = binding.conversationsList.adapter if (currAdapter == null) { hideKeyboard() currAdapter = ConversationsAdapter( activity = this, - recyclerView = conversations_list, + recyclerView = binding.conversationsList, onRefresh = { notifyDatasetChanged() }, itemClick = { handleConversationClick(it) } ) - conversations_list.adapter = currAdapter + binding.conversationsList.adapter = currAdapter if (areSystemAnimationsEnabled) { - conversations_list.scheduleLayoutAnimation() + binding.conversationsList.scheduleLayoutAnimation() } } return currAdapter as ConversationsAdapter @@ -410,25 +417,25 @@ class MainActivity : SimpleActivity() { private fun showOrHideProgress(show: Boolean) { if (show) { - conversations_progress_bar.show() - no_conversations_placeholder.beVisible() - no_conversations_placeholder.text = getString(R.string.loading_messages) + binding.conversationsProgressBar.show() + binding.noConversationsPlaceholder.beVisible() + binding.noConversationsPlaceholder.text = getString(R.string.loading_messages) } else { - conversations_progress_bar.hide() - no_conversations_placeholder.beGone() + binding.conversationsProgressBar.hide() + binding.noConversationsPlaceholder.beGone() } } private fun showOrHidePlaceholder(show: Boolean) { - conversations_fastscroller.beGoneIf(show) - no_conversations_placeholder.beVisibleIf(show) - no_conversations_placeholder.text = getString(R.string.no_conversations_found) - no_conversations_placeholder_2.beVisibleIf(show) + binding.conversationsFastscroller.beGoneIf(show) + binding.noConversationsPlaceholder.beVisibleIf(show) + binding.noConversationsPlaceholder.text = getString(R.string.no_conversations_found) + binding.noConversationsPlaceholder2.beVisibleIf(show) } private fun fadeOutSearch() { - search_holder.animate().alpha(0f).setDuration(SHORT_ANIMATION_DURATION).withEndAction { - search_holder.beGone() + binding.searchHolder.animate().alpha(0f).setDuration(SHORT_ANIMATION_DURATION).withEndAction { + binding.searchHolder.beGone() searchTextChanged("", true) }.start() } @@ -488,12 +495,12 @@ class MainActivity : SimpleActivity() { } private fun searchTextChanged(text: String, forceUpdate: Boolean = false) { - if (!main_menu.isSearchOpen && !forceUpdate) { + if (!binding.mainMenu.isSearchOpen && !forceUpdate) { return } lastSearchedText = text - search_placeholder_2.beGoneIf(text.length >= 2) + binding.searchPlaceholder2.beGoneIf(text.length >= 2) if (text.length >= 2) { ensureBackgroundThread { val searchQuery = "%$text%" @@ -504,8 +511,8 @@ class MainActivity : SimpleActivity() { } } } else { - search_placeholder.beVisible() - search_results_list.beGone() + binding.searchPlaceholder.beVisible() + binding.searchResultsList.beGone() } } @@ -530,12 +537,12 @@ class MainActivity : SimpleActivity() { } runOnUiThread { - search_results_list.beVisibleIf(searchResults.isNotEmpty()) - search_placeholder.beVisibleIf(searchResults.isEmpty()) + binding.searchResultsList.beVisibleIf(searchResults.isNotEmpty()) + binding.searchPlaceholder.beVisibleIf(searchResults.isEmpty()) - val currAdapter = search_results_list.adapter + val currAdapter = binding.searchResultsList.adapter if (currAdapter == null) { - SearchResultsAdapter(this, searchResults, search_results_list, searchedText) { + SearchResultsAdapter(this, searchResults, binding.searchResultsList, searchedText) { hideKeyboard() Intent(this, ThreadActivity::class.java).apply { putExtra(THREAD_ID, (it as SearchResult).threadId) @@ -544,7 +551,7 @@ class MainActivity : SimpleActivity() { startActivity(this) } }.apply { - search_results_list.adapter = this + binding.searchResultsList.adapter = this } } else { (currAdapter as SearchResultsAdapter).updateItems(searchResults, searchedText) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ManageBlockedKeywordsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ManageBlockedKeywordsActivity.kt index c1b1a79b..9334c7bf 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ManageBlockedKeywordsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ManageBlockedKeywordsActivity.kt @@ -6,35 +6,43 @@ import com.simplemobiletools.commons.extensions.beVisibleIf import com.simplemobiletools.commons.extensions.getProperPrimaryColor import com.simplemobiletools.commons.extensions.underlineText 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_LAUNCHER_NAME import com.simplemobiletools.commons.helpers.NavigationIcon import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.databinding.ActivityManageBlockedKeywordsBinding import com.simplemobiletools.smsmessenger.dialogs.AddBlockedKeywordDialog import com.simplemobiletools.smsmessenger.dialogs.ManageBlockedKeywordsAdapter import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.toArrayList -import kotlinx.android.synthetic.main.activity_manage_blocked_keywords.* class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewListener { override fun getAppIconIDs() = intent.getIntegerArrayListExtra(APP_ICON_IDS) ?: ArrayList() override fun getAppLauncherName() = intent.getStringExtra(APP_LAUNCHER_NAME) ?: "" + private val binding by viewBinding(ActivityManageBlockedKeywordsBinding::inflate) + override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_manage_blocked_keywords) + setContentView(binding.root) updateBlockedKeywords() setupOptionsMenu() - updateMaterialActivityViews(block_keywords_coordinator, manage_blocked_keywords_list, useTransparentNavigation = true, useTopSearchMenu = false) - setupMaterialScrollListener(manage_blocked_keywords_list, block_keywords_toolbar) - updateTextColors(manage_blocked_keywords_wrapper) + updateMaterialActivityViews( + mainCoordinatorLayout = binding.blockKeywordsCoordinator, + 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() setTextColor(getProperPrimaryColor()) setOnClickListener { @@ -45,11 +53,11 @@ class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewL override fun onResume() { super.onResume() - setupToolbar(block_keywords_toolbar, NavigationIcon.Arrow) + setupToolbar(binding.blockKeywordsToolbar, NavigationIcon.Arrow) } private fun setupOptionsMenu() { - block_keywords_toolbar.setOnMenuItemClickListener { menuItem -> + binding.blockKeywordsToolbar.setOnMenuItemClickListener { menuItem -> when (menuItem.itemId) { R.id.add_blocked_keyword -> { addOrEditBlockedKeyword() @@ -69,14 +77,14 @@ class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewL ensureBackgroundThread { val blockedKeywords = config.blockedKeywords runOnUiThread { - ManageBlockedKeywordsAdapter(this, blockedKeywords.toArrayList(), this, manage_blocked_keywords_list) { + ManageBlockedKeywordsAdapter(this, blockedKeywords.toArrayList(), this, binding.manageBlockedKeywordsList) { addOrEditBlockedKeyword(it as String) }.apply { - manage_blocked_keywords_list.adapter = this + binding.manageBlockedKeywordsList.adapter = this } - manage_blocked_keywords_placeholder.beVisibleIf(blockedKeywords.isEmpty()) - manage_blocked_keywords_placeholder_2.beVisibleIf(blockedKeywords.isEmpty()) + binding.manageBlockedKeywordsPlaceholder.beVisibleIf(blockedKeywords.isEmpty()) + binding.manageBlockedKeywordsPlaceholder2.beVisibleIf(blockedKeywords.isEmpty()) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/NewConversationActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/NewConversationActivity.kt index 16d1dcd7..78c6e0a9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/NewConversationActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/NewConversationActivity.kt @@ -14,31 +14,38 @@ import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.smsmessenger.R 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.getThreadId import com.simplemobiletools.smsmessenger.helpers.* 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.util.* +import java.util.Locale class NewConversationActivity : SimpleActivity() { private var allContacts = ArrayList() private var privateContacts = ArrayList() + private val binding by viewBinding(ActivityNewConversationBinding::inflate) + override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_new_conversation) + setContentView(binding.root) title = getString(R.string.new_conversation) - updateTextColors(new_conversation_holder) + updateTextColors(binding.newConversationHolder) - updateMaterialActivityViews(new_conversation_coordinator, contacts_list, useTransparentNavigation = true, useTopSearchMenu = false) - setupMaterialScrollListener(contacts_list, new_conversation_toolbar) + updateMaterialActivityViews( + 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) - 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 handlePermission(PERMISSION_READ_CONTACTS) { @@ -48,10 +55,10 @@ class NewConversationActivity : SimpleActivity() { override fun onResume() { super.onResume() - setupToolbar(new_conversation_toolbar, NavigationIcon.Arrow) - no_contacts_placeholder_2.setTextColor(getProperPrimaryColor()) - no_contacts_placeholder_2.underlineText() - suggestions_label.setTextColor(getProperPrimaryColor()) + setupToolbar(binding.newConversationToolbar, NavigationIcon.Arrow) + binding.noContactsPlaceholder2.setTextColor(getProperPrimaryColor()) + binding.noContactsPlaceholder2.underlineText() + binding.suggestionsLabel.setTextColor(getProperPrimaryColor()) } private fun initContacts() { @@ -60,7 +67,7 @@ class NewConversationActivity : SimpleActivity() { } fetchContacts() - new_conversation_address.onTextChangeListener { searchString -> + binding.newConversationAddress.onTextChangeListener { searchString -> val filteredContacts = ArrayList() allContacts.forEach { contact -> if (contact.phoneNumbers.any { it.normalizedNumber.contains(searchString, true) } || @@ -74,21 +81,21 @@ class NewConversationActivity : SimpleActivity() { filteredContacts.sortWith(compareBy { !it.name.startsWith(searchString, true) }) setupAdapter(filteredContacts) - new_conversation_confirm.beVisibleIf(searchString.length > 2) + binding.newConversationConfirm.beVisibleIf(searchString.length > 2) } - new_conversation_confirm.applyColorFilter(getProperTextColor()) - new_conversation_confirm.setOnClickListener { - val number = new_conversation_address.value + binding.newConversationConfirm.applyColorFilter(getProperTextColor()) + binding.newConversationConfirm.setOnClickListener { + val number = binding.newConversationAddress.value if (isShortCodeWithLetters(number)) { - new_conversation_address.setText("") + binding.newConversationAddress.setText("") toast(R.string.invalid_short_code, length = Toast.LENGTH_LONG) return@setOnClickListener } launchThreadActivity(number, number) } - no_contacts_placeholder_2.setOnClickListener { + binding.noContactsPlaceholder2.setOnClickListener { handlePermission(PERMISSION_READ_CONTACTS) { if (it) { fetchContacts() @@ -97,11 +104,11 @@ class NewConversationActivity : SimpleActivity() { } val properPrimaryColor = getProperPrimaryColor() - contacts_letter_fastscroller.textColor = getProperTextColor().getColorStateList() - contacts_letter_fastscroller.pressedTextColor = properPrimaryColor - contacts_letter_fastscroller_thumb.setupWithFastScroller(contacts_letter_fastscroller) - contacts_letter_fastscroller_thumb?.textColor = properPrimaryColor.getContrastColor() - contacts_letter_fastscroller_thumb?.thumbColor = properPrimaryColor.getColorStateList() + binding.contactsLetterFastscroller.textColor = getProperTextColor().getColorStateList() + binding.contactsLetterFastscroller.pressedTextColor = properPrimaryColor + binding.contactsLetterFastscrollerThumb.setupWithFastScroller(binding.contactsLetterFastscroller) + binding.contactsLetterFastscrollerThumb.textColor = properPrimaryColor.getContrastColor() + binding.contactsLetterFastscrollerThumb.thumbColor = properPrimaryColor.getColorStateList() } private fun isThirdPartyIntent(): Boolean { @@ -133,18 +140,18 @@ class NewConversationActivity : SimpleActivity() { private fun setupAdapter(contacts: ArrayList) { val hasContacts = contacts.isNotEmpty() - contacts_list.beVisibleIf(hasContacts) - no_contacts_placeholder.beVisibleIf(!hasContacts) - no_contacts_placeholder_2.beVisibleIf(!hasContacts && !hasPermission(PERMISSION_READ_CONTACTS)) + binding.contactsList.beVisibleIf(hasContacts) + binding.noContactsPlaceholder.beVisibleIf(!hasContacts) + binding.noContactsPlaceholder2.beVisibleIf(!hasContacts && !hasPermission(PERMISSION_READ_CONTACTS)) if (!hasContacts) { 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) { - ContactsAdapter(this, contacts, contacts_list) { + ContactsAdapter(this, contacts, binding.contactsList) { hideKeyboard() val contact = it as SimpleContact val phoneNumbers = contact.phoneNumbers @@ -167,11 +174,11 @@ class NewConversationActivity : SimpleActivity() { launchThreadActivity(phoneNumbers.first().normalizedNumber, contact.name) } }.apply { - contacts_list.adapter = this + binding.contactsList.adapter = this } if (areSystemAnimationsEnabled) { - contacts_list.scheduleLayoutAnimation() + binding.contactsList.scheduleLayoutAnimation() } } else { (currAdapter as ContactsAdapter).updateContacts(contacts) @@ -186,23 +193,23 @@ class NewConversationActivity : SimpleActivity() { privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor) val suggestions = getSuggestedContacts(privateContacts) runOnUiThread { - suggestions_holder.removeAllViews() + binding.suggestionsHolder.removeAllViews() if (suggestions.isEmpty()) { - suggestions_label.beGone() - suggestions_scrollview.beGone() + binding.suggestionsLabel.beGone() + binding.suggestionsScrollview.beGone() } else { - suggestions_label.beVisible() - suggestions_scrollview.beVisible() + binding.suggestionsLabel.beVisible() + binding.suggestionsScrollview.beVisible() suggestions.forEach { val contact = it - layoutInflater.inflate(R.layout.item_suggested_contact, null).apply { - suggested_contact_name.text = contact.name - suggested_contact_name.setTextColor(getProperTextColor()) + ItemSuggestedContactBinding.inflate(layoutInflater).apply { + suggestedContactName.text = contact.name + suggestedContactName.setTextColor(getProperTextColor()) if (!isDestroyed) { - SimpleContactsHelper(this@NewConversationActivity).loadContactImage(contact.photoUri, suggested_contact_image, contact.name) - suggestions_holder.addView(this) - setOnClickListener { + SimpleContactsHelper(this@NewConversationActivity).loadContactImage(contact.photoUri, suggestedContactImage, contact.name) + binding.suggestionsHolder.addView(root) + root.setOnClickListener { launchThreadActivity(contact.phoneNumbers.first().normalizedNumber, contact.name) } } @@ -215,11 +222,11 @@ class NewConversationActivity : SimpleActivity() { } private fun setupLetterFastscroller(contacts: ArrayList) { - contacts_letter_fastscroller.setupWithRecyclerView(contacts_list, { position -> + binding.contactsLetterFastscroller.setupWithRecyclerView(binding.contactsList, { position -> try { val name = contacts[position].name 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) { FastScrollItemIndicator.Text("") } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/RecycleBinConversationsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/RecycleBinConversationsActivity.kt index 22429285..0b6e5208 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/RecycleBinConversationsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/RecycleBinConversationsActivity.kt @@ -7,36 +7,41 @@ import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.smsmessenger.R -import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter import com.simplemobiletools.smsmessenger.adapters.RecycleBinConversationsAdapter +import com.simplemobiletools.smsmessenger.databinding.ActivityRecycleBinConversationsBinding import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Events -import kotlinx.android.synthetic.main.activity_recycle_bin_conversations.* import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode class RecycleBinConversationsActivity : SimpleActivity() { private var bus: EventBus? = null + private val binding by viewBinding(ActivityRecycleBinConversationsBinding::inflate) @SuppressLint("InlinedApi") override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_recycle_bin_conversations) + setContentView(binding.root) setupOptionsMenu() - updateMaterialActivityViews(recycle_bin_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = false) - setupMaterialScrollListener(conversations_list, recycle_bin_toolbar) + updateMaterialActivityViews( + mainCoordinatorLayout = binding.recycleBinCoordinator, + nestedView = binding.conversationsList, + useTransparentNavigation = true, + useTopSearchMenu = false + ) + setupMaterialScrollListener(scrollingView = binding.conversationsList, toolbar = binding.recycleBinToolbar) loadRecycleBinConversations() } override fun onResume() { super.onResume() - setupToolbar(recycle_bin_toolbar, NavigationIcon.Arrow) + setupToolbar(binding.recycleBinToolbar, NavigationIcon.Arrow) updateMenuColors() loadRecycleBinConversations() @@ -48,9 +53,8 @@ class RecycleBinConversationsActivity : SimpleActivity() { } private fun setupOptionsMenu() { - recycle_bin_toolbar.inflateMenu(R.menu.recycle_bin_menu) - - recycle_bin_toolbar.setOnMenuItemClickListener { menuItem -> + binding.recycleBinToolbar.inflateMenu(R.menu.recycle_bin_menu) + binding.recycleBinToolbar.setOnMenuItemClickListener { menuItem -> when (menuItem.itemId) { R.id.empty_recycle_bin -> removeAll() else -> return@setOnMenuItemClickListener false @@ -60,7 +64,7 @@ class RecycleBinConversationsActivity : SimpleActivity() { } private fun updateOptionsMenu(conversations: ArrayList) { - recycle_bin_toolbar.menu.apply { + binding.recycleBinToolbar.menu.apply { findItem(R.id.empty_recycle_bin).isVisible = conversations.isNotEmpty() } } @@ -85,7 +89,7 @@ class RecycleBinConversationsActivity : SimpleActivity() { bus = EventBus.getDefault() try { bus!!.register(this) - } catch (e: Exception) { + } catch (ignored: Exception) { } } @@ -99,19 +103,19 @@ class RecycleBinConversationsActivity : SimpleActivity() { } private fun getOrCreateConversationsAdapter(): RecycleBinConversationsAdapter { - var currAdapter = conversations_list.adapter + var currAdapter = binding.conversationsList.adapter if (currAdapter == null) { hideKeyboard() currAdapter = RecycleBinConversationsAdapter( activity = this, - recyclerView = conversations_list, + recyclerView = binding.conversationsList, onRefresh = { notifyDatasetChanged() }, itemClick = { handleConversationClick(it) } ) - conversations_list.adapter = currAdapter + binding.conversationsList.adapter = currAdapter if (areSystemAnimationsEnabled) { - conversations_list.scheduleLayoutAnimation() + binding.conversationsList.scheduleLayoutAnimation() } } return currAdapter as RecycleBinConversationsAdapter @@ -135,9 +139,9 @@ class RecycleBinConversationsActivity : SimpleActivity() { } private fun showOrHidePlaceholder(show: Boolean) { - conversations_fastscroller.beGoneIf(show) - no_conversations_placeholder.beVisibleIf(show) - no_conversations_placeholder.text = getString(R.string.no_conversations_found) + binding.conversationsFastscroller.beGoneIf(show) + binding.noConversationsPlaceholder.beVisibleIf(show) + binding.noConversationsPlaceholder.text = getString(R.string.no_conversations_found) } @SuppressLint("NotifyDataSetChanged") diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/SettingsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/SettingsActivity.kt index 329bcb06..371de74f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/SettingsActivity.kt @@ -12,13 +12,13 @@ import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.databinding.ActivitySettingsBinding import com.simplemobiletools.smsmessenger.dialogs.ExportMessagesDialog import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.emptyMessagesRecycleBin import com.simplemobiletools.smsmessenger.extensions.messagesDB import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.models.* -import kotlinx.android.synthetic.main.activity_settings.* import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import java.util.* @@ -30,18 +30,25 @@ class SettingsActivity : SimpleActivity() { private val messagesFileType = "application/json" private val messageImportFileTypes = listOf("application/json", "application/xml", "text/xml") + private val binding by viewBinding(ActivitySettingsBinding::inflate) + override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_settings) + setContentView(binding.root) - updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = true, useTopSearchMenu = false) - setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar) + updateMaterialActivityViews( + mainCoordinatorLayout = binding.settingsCoordinator, + nestedView = binding.settingsHolder, + useTransparentNavigation = true, + useTopSearchMenu = false + ) + setupMaterialScrollListener(scrollingView = binding.settingsNestedScrollview, toolbar = binding.settingsToolbar) } override fun onResume() { super.onResume() - setupToolbar(settings_toolbar, NavigationIcon.Arrow) + setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow) setupPurchaseThankYou() setupCustomizeColors() @@ -65,20 +72,20 @@ class SettingsActivity : SimpleActivity() { setupAppPasswordProtection() setupMessagesExport() setupMessagesImport() - updateTextColors(settings_nested_scrollview) + updateTextColors(binding.settingsNestedScrollview) if (blockedNumbersAtPause != -1 && blockedNumbersAtPause != getBlockedNumbers().hashCode()) { refreshMessages() } arrayOf( - settings_color_customization_section_label, - settings_general_settings_label, - settings_outgoing_messages_label, - settings_notifications_label, - settings_recycle_bin_label, - settings_security_label, - settings_migrating_label + binding.settingsColorCustomizationSectionLabel, + binding.settingsGeneralSettingsLabel, + binding.settingsOutgoingMessagesLabel, + binding.settingsNotificationsLabel, + binding.settingsEmptyRecycleBinLabel, + binding.settingsSecurityLabel, + binding.settingsMigratingLabel ).forEach { it.setTextColor(getProperPrimaryColor()) } @@ -98,7 +105,7 @@ class SettingsActivity : SimpleActivity() { } private fun setupMessagesExport() { - settings_export_messages_holder.setOnClickListener { + binding.settingsExportMessagesHolder.setOnClickListener { ExportMessagesDialog(this) { fileName -> saveDocument.launch(fileName) } @@ -106,7 +113,7 @@ class SettingsActivity : SimpleActivity() { } private fun setupMessagesImport() { - settings_import_messages_holder.setOnClickListener { + binding.settingsImportMessagesHolder.setOnClickListener { getContent.launch(messageImportFileTypes.toTypedArray()) } } @@ -139,87 +146,87 @@ class SettingsActivity : SimpleActivity() { blockedNumbersAtPause = getBlockedNumbers().hashCode() } - private fun setupPurchaseThankYou() { - settings_purchase_thank_you_holder.beGoneIf(isOrWasThankYouInstalled()) - settings_purchase_thank_you_holder.setOnClickListener { + private fun setupPurchaseThankYou() = binding.apply { + settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled()) + settingsPurchaseThankYouHolder.setOnClickListener { launchPurchaseThankYouIntent() } } - private fun setupCustomizeColors() { - settings_color_customization_label.text = getCustomizeColorsString() - settings_color_customization_holder.setOnClickListener { + private fun setupCustomizeColors() = binding.apply { + settingsColorCustomizationLabel.text = getCustomizeColorsString() + settingsColorCustomizationHolder.setOnClickListener { handleCustomizeColorsClick() } } - private fun setupCustomizeNotifications() { - settings_customize_notifications_holder.beVisibleIf(isOreoPlus()) - settings_customize_notifications_holder.setOnClickListener { + private fun setupCustomizeNotifications() = binding.apply { + settingsCustomizeNotificationsHolder.beVisibleIf(isOreoPlus()) + settingsCustomizeNotificationsHolder.setOnClickListener { launchCustomizeNotificationsIntent() } } - private fun setupUseEnglish() { - settings_use_english_holder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus()) - settings_use_english.isChecked = config.useEnglish - settings_use_english_holder.setOnClickListener { - settings_use_english.toggle() - config.useEnglish = settings_use_english.isChecked + private fun setupUseEnglish() = binding.apply { + settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus()) + settingsUseEnglish.isChecked = config.useEnglish + settingsUseEnglishHolder.setOnClickListener { + settingsUseEnglish.toggle() + config.useEnglish = settingsUseEnglish.isChecked exitProcess(0) } } - private fun setupLanguage() { - settings_language.text = Locale.getDefault().displayLanguage - settings_language_holder.beVisibleIf(isTiramisuPlus()) - settings_language_holder.setOnClickListener { + private fun setupLanguage() = binding.apply { + settingsLanguage.text = Locale.getDefault().displayLanguage + settingsLanguageHolder.beVisibleIf(isTiramisuPlus()) + settingsLanguageHolder.setOnClickListener { launchChangeAppLanguageIntent() } } // support for device-wise blocking came on Android 7, rely only on that @TargetApi(Build.VERSION_CODES.N) - private fun setupManageBlockedNumbers() { - settings_manage_blocked_numbers.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers) - settings_manage_blocked_numbers_holder.beVisibleIf(isNougatPlus()) + private fun setupManageBlockedNumbers() = binding.apply { + settingsManageBlockedNumbers.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers) + settingsManageBlockedNumbersHolder.beVisibleIf(isNougatPlus()) - settings_manage_blocked_numbers_holder.setOnClickListener { + settingsManageBlockedNumbersHolder.setOnClickListener { if (isOrWasThankYouInstalled()) { - Intent(this, ManageBlockedNumbersActivity::class.java).apply { + Intent(this@SettingsActivity, ManageBlockedNumbersActivity::class.java).apply { startActivity(this) } } else { - FeatureLockedDialog(this) { } + FeatureLockedDialog(this@SettingsActivity) { } } } } - private fun setupManageBlockedKeywords() { - settings_manage_blocked_keywords.text = addLockedLabelIfNeeded(R.string.manage_blocked_keywords) + private fun setupManageBlockedKeywords() = binding.apply { + settingsManageBlockedKeywords.text = addLockedLabelIfNeeded(R.string.manage_blocked_keywords) - settings_manage_blocked_keywords_holder.setOnClickListener { + settingsManageBlockedKeywordsHolder.setOnClickListener { if (isOrWasThankYouInstalled()) { - Intent(this, ManageBlockedKeywordsActivity::class.java).apply { + Intent(this@SettingsActivity, ManageBlockedKeywordsActivity::class.java).apply { startActivity(this) } } else { - FeatureLockedDialog(this) { } + FeatureLockedDialog(this@SettingsActivity) { } } } } - private fun setupChangeDateTimeFormat() { - settings_change_date_time_format_holder.setOnClickListener { - ChangeDateTimeFormatDialog(this) { + private fun setupChangeDateTimeFormat() = binding.apply { + settingsChangeDateTimeFormatHolder.setOnClickListener { + ChangeDateTimeFormatDialog(this@SettingsActivity) { refreshMessages() } } } - private fun setupFontSize() { - settings_font_size.text = getFontSizeText() - settings_font_size_holder.setOnClickListener { + private fun setupFontSize() = binding.apply { + settingsFontSize.text = getFontSizeText() + settingsFontSizeHolder.setOnClickListener { val items = arrayListOf( RadioItem(FONT_SIZE_SMALL, getString(R.string.small)), RadioItem(FONT_SIZE_MEDIUM, getString(R.string.medium)), @@ -229,62 +236,62 @@ class SettingsActivity : SimpleActivity() { RadioGroupDialog(this@SettingsActivity, items, config.fontSize) { config.fontSize = it as Int - settings_font_size.text = getFontSizeText() + settingsFontSize.text = getFontSizeText() } } } - private fun setupShowCharacterCounter() { - settings_show_character_counter.isChecked = config.showCharacterCounter - settings_show_character_counter_holder.setOnClickListener { - settings_show_character_counter.toggle() - config.showCharacterCounter = settings_show_character_counter.isChecked + private fun setupShowCharacterCounter() = binding.apply { + settingsShowCharacterCounter.isChecked = config.showCharacterCounter + settingsShowCharacterCounterHolder.setOnClickListener { + settingsShowCharacterCounter.toggle() + config.showCharacterCounter = settingsShowCharacterCounter.isChecked } } - private fun setupUseSimpleCharacters() { - settings_use_simple_characters.isChecked = config.useSimpleCharacters - settings_use_simple_characters_holder.setOnClickListener { - settings_use_simple_characters.toggle() - config.useSimpleCharacters = settings_use_simple_characters.isChecked + private fun setupUseSimpleCharacters() = binding.apply { + settingsUseSimpleCharacters.isChecked = config.useSimpleCharacters + settingsUseSimpleCharactersHolder.setOnClickListener { + settingsUseSimpleCharacters.toggle() + config.useSimpleCharacters = settingsUseSimpleCharacters.isChecked } } - private fun setupSendOnEnter() { - settings_send_on_enter.isChecked = config.sendOnEnter - settings_send_on_enter_holder.setOnClickListener { - settings_send_on_enter.toggle() - config.sendOnEnter = settings_send_on_enter.isChecked + private fun setupSendOnEnter() = binding.apply { + settingsSendOnEnter.isChecked = config.sendOnEnter + settingsSendOnEnterHolder.setOnClickListener { + settingsSendOnEnter.toggle() + config.sendOnEnter = settingsSendOnEnter.isChecked } } - private fun setupEnableDeliveryReports() { - settings_enable_delivery_reports.isChecked = config.enableDeliveryReports - settings_enable_delivery_reports_holder.setOnClickListener { - settings_enable_delivery_reports.toggle() - config.enableDeliveryReports = settings_enable_delivery_reports.isChecked + private fun setupEnableDeliveryReports() = binding.apply { + settingsEnableDeliveryReports.isChecked = config.enableDeliveryReports + settingsEnableDeliveryReportsHolder.setOnClickListener { + settingsEnableDeliveryReports.toggle() + config.enableDeliveryReports = settingsEnableDeliveryReports.isChecked } } - private fun setupSendLongMessageAsMMS() { - settings_send_long_message_mms.isChecked = config.sendLongMessageMMS - settings_send_long_message_mms_holder.setOnClickListener { - settings_send_long_message_mms.toggle() - config.sendLongMessageMMS = settings_send_long_message_mms.isChecked + private fun setupSendLongMessageAsMMS() = binding.apply { + settingsSendLongMessageMms.isChecked = config.sendLongMessageMMS + settingsSendLongMessageMmsHolder.setOnClickListener { + settingsSendLongMessageMms.toggle() + config.sendLongMessageMMS = settingsSendLongMessageMms.isChecked } } - private fun setupGroupMessageAsMMS() { - settings_send_group_message_mms.isChecked = config.sendGroupMessageMMS - settings_send_group_message_mms_holder.setOnClickListener { - settings_send_group_message_mms.toggle() - config.sendGroupMessageMMS = settings_send_group_message_mms.isChecked + private fun setupGroupMessageAsMMS() = binding.apply { + settingsSendGroupMessageMms.isChecked = config.sendGroupMessageMMS + settingsSendGroupMessageMmsHolder.setOnClickListener { + settingsSendGroupMessageMms.toggle() + config.sendGroupMessageMMS = settingsSendGroupMessageMms.isChecked } } - private fun setupLockScreenVisibility() { - settings_lock_screen_visibility.text = getLockScreenVisibilityText() - settings_lock_screen_visibility_holder.setOnClickListener { + private fun setupLockScreenVisibility() = binding.apply { + settingsLockScreenVisibility.text = getLockScreenVisibilityText() + settingsLockScreenVisibilityHolder.setOnClickListener { val items = arrayListOf( RadioItem(LOCK_SCREEN_SENDER_MESSAGE, getString(R.string.sender_and_message)), RadioItem(LOCK_SCREEN_SENDER, getString(R.string.sender_only)), @@ -293,7 +300,7 @@ class SettingsActivity : SimpleActivity() { RadioGroupDialog(this@SettingsActivity, items, config.lockScreenVisibilitySetting) { config.lockScreenVisibilitySetting = it as Int - settings_lock_screen_visibility.text = getLockScreenVisibilityText() + settingsLockScreenVisibility.text = getLockScreenVisibilityText() } } } @@ -306,9 +313,9 @@ class SettingsActivity : SimpleActivity() { } ) - private fun setupMMSFileSizeLimit() { - settings_mms_file_size_limit.text = getMMSFileLimitText() - settings_mms_file_size_limit_holder.setOnClickListener { + private fun setupMMSFileSizeLimit() = binding.apply { + settingsMmsFileSizeLimit.text = getMMSFileLimitText() + settingsMmsFileSizeLimitHolder.setOnClickListener { val items = arrayListOf( 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), @@ -322,58 +329,58 @@ class SettingsActivity : SimpleActivity() { val checkedItemId = items.find { it.value == config.mmsFileSizeLimit }?.id ?: 7 RadioGroupDialog(this@SettingsActivity, items, checkedItemId) { config.mmsFileSizeLimit = it as Long - settings_mms_file_size_limit.text = getMMSFileLimitText() + settingsMmsFileSizeLimit.text = getMMSFileLimitText() } } } - private fun setupUseRecycleBin() { + private fun setupUseRecycleBin() = binding.apply { updateRecycleBinButtons() - settings_use_recycle_bin.isChecked = config.useRecycleBin - settings_use_recycle_bin_holder.setOnClickListener { - settings_use_recycle_bin.toggle() - config.useRecycleBin = settings_use_recycle_bin.isChecked + settingsUseRecycleBin.isChecked = config.useRecycleBin + settingsUseRecycleBinHolder.setOnClickListener { + settingsUseRecycleBin.toggle() + config.useRecycleBin = settingsUseRecycleBin.isChecked updateRecycleBinButtons() } } - private fun updateRecycleBinButtons() { - settings_empty_recycle_bin_holder.beVisibleIf(config.useRecycleBin) + private fun updateRecycleBinButtons() = binding.apply { + settingsEmptyRecycleBinHolder.beVisibleIf(config.useRecycleBin) } - private fun setupEmptyRecycleBin() { + private fun setupEmptyRecycleBin() = binding.apply { ensureBackgroundThread { recycleBinMessages = messagesDB.getArchivedCount() runOnUiThread { - settings_empty_recycle_bin_size.text = + settingsEmptyRecycleBinSize.text = resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages) } } - settings_empty_recycle_bin_holder.setOnClickListener { + settingsEmptyRecycleBinHolder.setOnClickListener { if (recycleBinMessages == 0) { toast(R.string.recycle_bin_empty) } 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 { emptyMessagesRecycleBin() } recycleBinMessages = 0 - settings_empty_recycle_bin_size.text = + settingsEmptyRecycleBinSize.text = resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages) } } } } - private fun setupAppPasswordProtection() { - settings_app_password_protection.isChecked = config.isAppPasswordProtectionOn - settings_app_password_protection_holder.setOnClickListener { + private fun setupAppPasswordProtection() = binding.apply { + settingsAppPasswordProtection.isChecked = config.isAppPasswordProtectionOn + settingsAppPasswordProtectionHolder.setOnClickListener { 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) { val hasPasswordProtection = config.isAppPasswordProtectionOn - settings_app_password_protection.isChecked = !hasPasswordProtection + settingsAppPasswordProtection.isChecked = !hasPasswordProtection config.isAppPasswordProtectionOn = !hasPasswordProtection config.appPasswordHash = if (hasPasswordProtection) "" else hash config.appProtectionType = type @@ -381,7 +388,7 @@ class SettingsActivity : SimpleActivity() { if (config.isAppPasswordProtectionOn) { val confirmationTextId = if (config.appProtectionType == PROTECTION_FINGERPRINT) 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) { } } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt index 1f867c88..d6f78b4d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt @@ -58,6 +58,9 @@ import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.adapters.AttachmentsAdapter import com.simplemobiletools.smsmessenger.adapters.AutoCompleteTextViewAdapter 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.RenameConversationDialog import com.simplemobiletools.smsmessenger.dialogs.ScheduleMessageDialog @@ -66,11 +69,6 @@ import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.messaging.* import com.simplemobiletools.smsmessenger.models.* 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.Subscribe import org.greenrobot.eventbus.ThreadMode @@ -114,6 +112,8 @@ class ThreadActivity : SimpleActivity() { private var isAttachmentPickerVisible = false + private val binding by viewBinding(ActivityThreadBinding::inflate) + override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) finish() @@ -123,12 +123,12 @@ class ThreadActivity : SimpleActivity() { override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_thread) + setContentView(binding.root) setupOptionsMenu() refreshMenuItems() - updateMaterialActivityViews(thread_coordinator, null, useTransparentNavigation = false, useTopSearchMenu = false) - setupMaterialScrollListener(null, thread_toolbar) + updateMaterialActivityViews(binding.threadCoordinator, null, useTransparentNavigation = false, useTopSearchMenu = false) + setupMaterialScrollListener(null, binding.threadToolbar) val extras = intent.extras if (extras == null) { @@ -140,7 +140,7 @@ class ThreadActivity : SimpleActivity() { clearAllMessagesIfNeeded() threadId = intent.getLongExtra(THREAD_ID, 0L) intent.getStringExtra(THREAD_TITLE)?.let { - thread_toolbar.title = it + binding.threadToolbar.title = it } isRecycleBin = intent.getBooleanExtra(IS_RECYCLE_BIN, false) wasProtectionHandled = intent.getBooleanExtra(WAS_PROTECTION_HANDLED, false) @@ -171,11 +171,11 @@ class ThreadActivity : SimpleActivity() { override fun onResume() { super.onResume() - setupToolbar(thread_toolbar, NavigationIcon.Arrow, statusBarColor = getProperBackgroundColor()) + setupToolbar(binding.threadToolbar, NavigationIcon.Arrow, statusBarColor = getProperBackgroundColor()) val smsDraft = getSmsDraft(threadId) if (smsDraft != null) { - thread_type_message.setText(smsDraft) + binding.messageHolder.threadTypeMessage.setText(smsDraft) } isActivityVisible = true @@ -192,16 +192,16 @@ class ThreadActivity : SimpleActivity() { } val bottomBarColor = getBottomBarColor() - thread_send_message_holder.setBackgroundColor(bottomBarColor) - reply_disabled_info_holder.setBackgroundColor(bottomBarColor) + binding.messageHolder.root.setBackgroundColor(bottomBarColor) + binding.shortCodeHolder.root.setBackgroundColor(bottomBarColor) updateNavigationBarColor(bottomBarColor) } override fun onPause() { super.onPause() - if (thread_type_message.value != "" && getAttachmentSelections().isEmpty()) { - saveSmsDraft(thread_type_message.value, threadId) + if (binding.messageHolder.threadTypeMessage.value != "" && getAttachmentSelections().isEmpty()) { + saveSmsDraft(binding.messageHolder.threadTypeMessage.value, threadId) } else { deleteSmsDraft(threadId) } @@ -212,7 +212,7 @@ class ThreadActivity : SimpleActivity() { override fun onBackPressed() { isAttachmentPickerVisible = false - if (attachment_picker_holder.isVisible()) { + if (binding.messageHolder.attachmentPickerHolder.isVisible()) { hideAttachmentPicker() } else { super.onBackPressed() @@ -249,7 +249,7 @@ class ThreadActivity : SimpleActivity() { private fun refreshMenuItems() { 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.restore).isVisible = threadItems.isNotEmpty() && isRecycleBin findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin @@ -270,7 +270,7 @@ class ThreadActivity : SimpleActivity() { } private fun setupOptionsMenu() { - thread_toolbar.setOnMenuItemClickListener { menuItem -> + binding.threadToolbar.setOnMenuItemClickListener { menuItem -> if (participants.isEmpty()) { return@setOnMenuItemClickListener true } @@ -339,7 +339,7 @@ class ThreadActivity : SimpleActivity() { runOnUiThread { if (messages.isEmpty()) { window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) - thread_type_message.requestFocus() + binding.messageHolder.threadTypeMessage.requestFocus() } setupThreadTitle() @@ -360,7 +360,7 @@ class ThreadActivity : SimpleActivity() { messages = getMessages(threadId, true) if (config.useRecycleBin) { val recycledMessages = messagesDB.getThreadMessagesFromRecycleBin(threadId).map { it.id } - messages = messages.filter { !recycledMessages.contains(it.id) }.toMutableList() as ArrayList + messages = messages.filter { !recycledMessages.contains(it.id) }.toMutableList() as ArrayList } } @@ -426,18 +426,18 @@ class ThreadActivity : SimpleActivity() { } private fun getOrCreateThreadAdapter(): ThreadAdapter { - var currAdapter = thread_messages_list.adapter + var currAdapter = binding.threadMessagesList.adapter if (currAdapter == null) { currAdapter = ThreadAdapter( activity = this, - recyclerView = thread_messages_list, + recyclerView = binding.threadMessagesList, itemClick = { handleItemClick(it) }, isRecycleBin = isRecycleBin, - deleteMessages = { messages, toRecycleBin, fromRecycleBin -> deleteMessages(messages, toRecycleBin, fromRecycleBin) } + deleteMessages = { messages, toRecycleBin, fromRecycleBin -> deleteMessages(messages, toRecycleBin, fromRecycleBin) } ) - thread_messages_list.adapter = currAdapter - thread_messages_list.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener { + binding.threadMessagesList.adapter = currAdapter + binding.threadMessagesList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener { override fun updateBottom() {} override fun updateTop() { @@ -454,7 +454,7 @@ class ThreadActivity : SimpleActivity() { runOnUiThread { refreshMenuItems() getOrCreateThreadAdapter().apply { - val layoutManager = thread_messages_list.layoutManager as LinearLayoutManager + val layoutManager = binding.threadMessagesList.layoutManager as LinearLayoutManager val lastPosition = itemCount - 1 val lastVisiblePosition = layoutManager.findLastVisibleItemPosition() val shouldScrollToBottom = currentList.lastOrNull() != threadItems.lastOrNull() && lastPosition - lastVisiblePosition == 1 @@ -466,23 +466,23 @@ class ThreadActivity : SimpleActivity() { contacts.addAll(privateContacts) runOnUiThread { val adapter = AutoCompleteTextViewAdapter(this, contacts) - add_contact_or_number.setAdapter(adapter) - add_contact_or_number.imeOptions = EditorInfo.IME_ACTION_NEXT - add_contact_or_number.setOnItemClickListener { _, _, position, _ -> - val currContacts = (add_contact_or_number.adapter as AutoCompleteTextViewAdapter).resultList + binding.addContactOrNumber.setAdapter(adapter) + binding.addContactOrNumber.imeOptions = EditorInfo.IME_ACTION_NEXT + binding.addContactOrNumber.setOnItemClickListener { _, _, position, _ -> + val currContacts = (binding.addContactOrNumber.adapter as AutoCompleteTextViewAdapter).resultList val selectedContact = currContacts[position] addSelectedContact(selectedContact) } - add_contact_or_number.onTextChangeListener { - confirm_inserted_number.beVisibleIf(it.length > 2) + binding.addContactOrNumber.onTextChangeListener { + binding.confirmInsertedNumber.beVisibleIf(it.length > 2) } } } runOnUiThread { - confirm_inserted_number?.setOnClickListener { - val number = add_contact_or_number.value + binding.confirmInsertedNumber.setOnClickListener { + val number = binding.addContactOrNumber.value val phoneNumber = PhoneNumber(number, 0, "", number) val contact = SimpleContact(number.hashCode(), number.hashCode(), number, "", arrayListOf(phoneNumber), ArrayList(), ArrayList()) addSelectedContact(contact) @@ -493,21 +493,21 @@ class ThreadActivity : SimpleActivity() { private fun scrollToBottom() { val position = getOrCreateThreadAdapter().currentList.lastIndex if (position >= 0) { - thread_messages_list.smoothScrollToPosition(position) + binding.threadMessagesList.smoothScrollToPosition(position) } } 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) { 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 isCloseToBottom = lastVisibleItemPosition >= getOrCreateThreadAdapter().itemCount - SCROLL_TO_BOTTOM_FAB_LIMIT if (isCloseToBottom) { - scroll_to_bottom_fab.hide() + binding.scrollToBottomFab.hide() } else { - scroll_to_bottom_fab.show() + binding.scrollToBottomFab.show() } } }) @@ -517,7 +517,7 @@ class ThreadActivity : SimpleActivity() { when { any is Message && any.isScheduled -> showScheduledMessageInfo(any) any is ThreadError -> { - thread_type_message.setText(any.messageText) + binding.messageHolder.threadTypeMessage.setText(any.messageText) messageToResend = any.messageId } } @@ -616,7 +616,7 @@ class ThreadActivity : SimpleActivity() { if (searchedMessageId != -1L) { val index = threadItems.indexOfFirst { (it as? Message)?.id == searchedMessageId } if (index != -1) { - thread_messages_list.smoothScrollToPosition(index) + binding.threadMessagesList.smoothScrollToPosition(index) } } @@ -635,118 +635,119 @@ class ThreadActivity : SimpleActivity() { } } - private fun setupButtons() { - updateTextColors(thread_holder) + private fun setupButtons() = binding.apply { + updateTextColors(threadHolder) val textColor = getProperTextColor() - thread_send_message.apply { - setTextColor(textColor) - compoundDrawables.forEach { + + binding.messageHolder.apply { + threadSendMessage.setTextColor(textColor) + threadSendMessage.compoundDrawables.forEach { it?.applyColorFilter(textColor) } - } - confirm_manage_contacts.applyColorFilter(textColor) - thread_add_attachment.applyColorFilter(textColor) + confirmManageContacts.applyColorFilter(textColor) + threadAddAttachment.applyColorFilter(textColor) - val properPrimaryColor = getProperPrimaryColor() - thread_messages_fastscroller.updateColors(properPrimaryColor) + val properPrimaryColor = getProperPrimaryColor() + threadMessagesFastscroller.updateColors(properPrimaryColor) - thread_character_counter.beVisibleIf(config.showCharacterCounter) - thread_character_counter.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize()) + threadCharacterCounter.beVisibleIf(config.showCharacterCounter) + threadCharacterCounter.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize()) - thread_type_message.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize()) - thread_send_message.setOnClickListener { - sendMessage() - } - - thread_send_message.setOnLongClickListener { - if (!isScheduledMessage) { - launchScheduleSendDialog() + threadTypeMessage.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize()) + threadSendMessage.setOnClickListener { + sendMessage() } - true - } - thread_send_message.isClickable = false - thread_type_message.onTextChangeListener { - messageToResend = null - checkSendMessageAvailability() - val messageString = if (config.useSimpleCharacters) { - it.normalizeString() - } else { - it - } - val messageLength = SmsMessage.calculateLength(messageString, false) - thread_character_counter.text = "${messageLength[2]}/${messageLength[0]}" - } - - if (config.sendOnEnter) { - thread_type_message.inputType = EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES - thread_type_message.imeOptions = EditorInfo.IME_ACTION_SEND - - thread_type_message.setOnEditorActionListener { _, action, _ -> - if (action == EditorInfo.IME_ACTION_SEND) { - dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER)) - return@setOnEditorActionListener true + threadSendMessage.setOnLongClickListener { + if (!isScheduledMessage) { + launchScheduleSendDialog() } - false + true } - thread_type_message.setOnKeyListener { _, keyCode, event -> - if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) { - sendMessage() - return@setOnKeyListener true + threadSendMessage.isClickable = false + threadTypeMessage.onTextChangeListener { + messageToResend = null + checkSendMessageAvailability() + val messageString = if (config.useSimpleCharacters) { + it.normalizeString() + } else { + it } - false + val messageLength = SmsMessage.calculateLength(messageString, false) + threadCharacterCounter.text = "${messageLength[2]}/${messageLength[0]}" } - } - confirm_manage_contacts.setOnClickListener { - hideKeyboard() - thread_add_contacts.beGone() + if (config.sendOnEnter) { + threadTypeMessage.inputType = EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES + threadTypeMessage.imeOptions = EditorInfo.IME_ACTION_SEND + threadTypeMessage.setOnEditorActionListener { _, action, _ -> + if (action == EditorInfo.IME_ACTION_SEND) { + dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER)) + return@setOnEditorActionListener true + } + false + } - val numbers = HashSet() - participants.forEach { contact -> - contact.phoneNumbers.forEach { - numbers.add(it.normalizedNumber) + threadTypeMessage.setOnKeyListener { _, keyCode, event -> + if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) { + sendMessage() + return@setOnKeyListener true + } + false } } - val newThreadId = getThreadId(numbers) - if (threadId != newThreadId) { + + confirmManageContacts.setOnClickListener { hideKeyboard() - Intent(this, ThreadActivity::class.java).apply { - putExtra(THREAD_ID, newThreadId) - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) - startActivity(this) + threadAddContacts.beGone() + + val numbers = HashSet() + participants.forEach { contact -> + contact.phoneNumbers.forEach { + numbers.add(it.normalizedNumber) + } + } + + val newThreadId = getThreadId(numbers) + if (threadId != newThreadId) { + hideKeyboard() + Intent(this@ThreadActivity, ThreadActivity::class.java).apply { + putExtra(THREAD_ID, newThreadId) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) + startActivity(this) + } } } - } - thread_type_message.setText(intent.getStringExtra(THREAD_TEXT)) - thread_add_attachment.setOnClickListener { - if (attachment_picker_holder.isVisible()) { - isAttachmentPickerVisible = false - WindowCompat.getInsetsController(window, thread_type_message).show(WindowInsetsCompat.Type.ime()) - } else { - isAttachmentPickerVisible = true - showOrHideAttachmentPicker() - WindowCompat.getInsetsController(window, thread_type_message).hide(WindowInsetsCompat.Type.ime()) + threadTypeMessage.setText(intent.getStringExtra(THREAD_TEXT)) + threadAddAttachment.setOnClickListener { + if (attachmentPickerHolder.isVisible()) { + isAttachmentPickerVisible = false + WindowCompat.getInsetsController(window, threadTypeMessage).show(WindowInsetsCompat.Type.ime()) + } else { + isAttachmentPickerVisible = true + showOrHideAttachmentPicker() + WindowCompat.getInsetsController(window, threadTypeMessage).hide(WindowInsetsCompat.Type.ime()) + } + window.decorView.requestApplyInsets() } - window.decorView.requestApplyInsets() - } - if (intent.extras?.containsKey(THREAD_ATTACHMENT_URI) == true) { - val uri = Uri.parse(intent.getStringExtra(THREAD_ATTACHMENT_URI)) - addAttachment(uri) - } else if (intent.extras?.containsKey(THREAD_ATTACHMENT_URIS) == true) { - (intent.getSerializableExtra(THREAD_ATTACHMENT_URIS) as? ArrayList)?.forEach { - addAttachment(it) + if (intent.extras?.containsKey(THREAD_ATTACHMENT_URI) == true) { + val uri = Uri.parse(intent.getStringExtra(THREAD_ATTACHMENT_URI)) + addAttachment(uri) + } else if (intent.extras?.containsKey(THREAD_ATTACHMENT_URIS) == true) { + (intent.getSerializableExtra(THREAD_ATTACHMENT_URIS) as? ArrayList)?.forEach { + addAttachment(it) + } } + scrollToBottomFab.setOnClickListener { + scrollToBottom() + } + scrollToBottomFab.backgroundTintList = ColorStateList.valueOf(getBottomBarColor()) + scrollToBottomFab.applyColorFilter(textColor) } - scroll_to_bottom_fab.setOnClickListener { - scrollToBottom() - } - scroll_to_bottom_fab.backgroundTintList = ColorStateList.valueOf(getBottomBarColor()) - scroll_to_bottom_fab.applyColorFilter(textColor) setupScheduleSendUi() } @@ -822,11 +823,11 @@ class ThreadActivity : SimpleActivity() { private fun maybeDisableShortCodeReply() { if (isSpecialNumber() && !isRecycleBin) { - thread_send_message_holder.beGone() - reply_disabled_info_holder.beVisible() + binding.messageHolder.root.beGone() + binding.shortCodeHolder.root.beVisible() val textColor = getProperTextColor() - reply_disabled_text.setTextColor(textColor) - reply_disabled_info.apply { + binding.shortCodeHolder.replyDisabledText.setTextColor(textColor) + binding.shortCodeHolder.replyDisabledInfo.apply { applyColorFilter(textColor) setOnClickListener { InvalidNumberDialog( @@ -843,7 +844,7 @@ class ThreadActivity : SimpleActivity() { private fun setupThreadTitle() { val title = conversation?.title - thread_toolbar.title = if (!title.isNullOrEmpty()) { + binding.threadToolbar.title = if (!title.isNullOrEmpty()) { title } else { participants.getThreadTitle() @@ -875,15 +876,15 @@ class ThreadActivity : SimpleActivity() { } currentSIMCardIndex = getProperSimIndex(availableSIMs, numbers) - thread_select_sim_icon.applyColorFilter(getProperTextColor()) - thread_select_sim_icon.beVisible() - thread_select_sim_number.beVisible() + binding.messageHolder.threadSelectSimIcon.applyColorFilter(getProperTextColor()) + binding.messageHolder.threadSelectSimIcon.beVisible() + binding.messageHolder.threadSelectSimNumber.beVisible() if (availableSIMCards.isNotEmpty()) { - thread_select_sim_icon.setOnClickListener { + binding.messageHolder.threadSelectSimIcon.setOnClickListener { currentSIMCardIndex = (currentSIMCardIndex + 1) % availableSIMCards.size val currentSIMCard = availableSIMCards[currentSIMCardIndex] - thread_select_sim_number.text = currentSIMCard.id.toString() + binding.messageHolder.threadSelectSimNumber.text = currentSIMCard.id.toString() val currentSubscriptionId = currentSIMCard.subscriptionId numbers.forEach { config.saveUseSIMIdAtNumber(it, currentSubscriptionId) @@ -892,9 +893,9 @@ class ThreadActivity : SimpleActivity() { } } - thread_select_sim_number.setTextColor(getProperTextColor().getContrastColor()) + binding.messageHolder.threadSelectSimNumber.setTextColor(getProperTextColor().getContrastColor()) try { - thread_select_sim_number.text = (availableSIMCards[currentSIMCardIndex].id).toString() + binding.messageHolder.threadSelectSimNumber.text = (availableSIMCards[currentSIMCardIndex].id).toString() } catch (e: Exception) { showErrorToast(e) } @@ -1002,14 +1003,14 @@ class ThreadActivity : SimpleActivity() { } private fun managePeople() { - if (thread_add_contacts.isVisible()) { + if (binding.threadAddContacts.isVisible()) { hideKeyboard() - thread_add_contacts.beGone() + binding.threadAddContacts.beGone() } else { showSelectedContacts() - thread_add_contacts.beVisible() - add_contact_or_number.requestFocus() - showKeyboard(add_contact_or_number) + binding.threadAddContacts.beVisible() + binding.addContactOrNumber.requestFocus() + showKeyboard(binding.addContactOrNumber) } } @@ -1018,28 +1019,28 @@ class ThreadActivity : SimpleActivity() { val views = ArrayList() 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) (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 - selected_contact_name.setTextColor(properPrimaryColor.getContrastColor()) - selected_contact_remove.applyColorFilter(properPrimaryColor.getContrastColor()) + selectedContactName.text = contact.name + selectedContactName.setTextColor(properPrimaryColor.getContrastColor()) + selectedContactRemove.applyColorFilter(properPrimaryColor.getContrastColor()) - selected_contact_remove.setOnClickListener { + selectedContactRemove.setOnClickListener { if (contact.rawId != participants.first().rawId) { removeSelectedContact(contact.rawId) } } - views.add(this) + views.add(root) } } showSelectedContact(views) } private fun addSelectedContact(contact: SimpleContact) { - add_contact_or_number.setText("") + binding.addContactOrNumber.setText("") if (participants.map { it.rawId }.contains(contact.rawId)) { return } @@ -1234,7 +1235,7 @@ class ThreadActivity : SimpleActivity() { } private fun getAttachmentsAdapter(): AttachmentsAdapter? { - val adapter = thread_attachments_recyclerview.adapter + val adapter = binding.messageHolder.threadAttachmentsRecyclerview.adapter return adapter as? AttachmentsAdapter } @@ -1268,17 +1269,17 @@ class ThreadActivity : SimpleActivity() { if (adapter == null) { adapter = AttachmentsAdapter( activity = this, - recyclerView = thread_attachments_recyclerview, + recyclerView = binding.messageHolder.threadAttachmentsRecyclerview, onAttachmentsRemoved = { - thread_attachments_recyclerview.beGone() + binding.messageHolder.threadAttachmentsRecyclerview.beGone() checkSendMessageAvailability() }, onReady = { checkSendMessageAvailability() } ) - thread_attachments_recyclerview.adapter = adapter + binding.messageHolder.threadAttachmentsRecyclerview.adapter = adapter } - thread_attachments_recyclerview.beVisible() + binding.messageHolder.threadAttachmentsRecyclerview.beVisible() val attachment = AttachmentSelection( id = id, uri = uri, @@ -1311,20 +1312,23 @@ class ThreadActivity : SimpleActivity() { } private fun checkSendMessageAvailability() { - if (thread_type_message.text!!.isNotEmpty() || (getAttachmentSelections().isNotEmpty() && !getAttachmentSelections().any { it.isPending })) { - thread_send_message.isEnabled = true - thread_send_message.isClickable = true - thread_send_message.alpha = 0.9f - } else { - thread_send_message.isEnabled = false - thread_send_message.isClickable = false - thread_send_message.alpha = 0.4f + binding.messageHolder.apply { + if (threadTypeMessage.text!!.isNotEmpty() || (getAttachmentSelections().isNotEmpty() && !getAttachmentSelections().any { it.isPending })) { + threadSendMessage.isEnabled = true + threadSendMessage.isClickable = true + threadSendMessage.alpha = 0.9f + } else { + threadSendMessage.isEnabled = false + threadSendMessage.isClickable = false + threadSendMessage.alpha = 0.4f + } } + updateMessageType() } private fun sendMessage() { - var text = thread_type_message.value + var text = binding.messageHolder.threadTypeMessage.value if (text.isEmpty() && getAttachmentSelections().isEmpty()) { showErrorToast(getString(R.string.unknown_error_occurred)) return @@ -1403,7 +1407,7 @@ class ThreadActivity : SimpleActivity() { } private fun clearCurrentMessage() { - thread_type_message.setText("") + binding.messageHolder.threadTypeMessage.setText("") getAttachmentsAdapter()?.clear() checkSendMessageAvailability() } @@ -1430,12 +1434,12 @@ class ThreadActivity : SimpleActivity() { // show selected contacts, properly split to new lines when appropriate // based on https://stackoverflow.com/a/13505029/1967672 private fun showSelectedContact(views: ArrayList) { - selected_contacts.removeAllViews() + binding.selectedContacts.removeAllViews() var newLinearLayout = LinearLayout(this) newLinearLayout.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) 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 parentWidth = realScreenSize.x - sideMargin * 2 val firstRowWidth = parentWidth - resources.getDimension(R.dimen.normal_icon_size).toInt() + sideMargin / 2 @@ -1458,7 +1462,7 @@ class ThreadActivity : SimpleActivity() { val checkWidth = if (isFirstRow) firstRowWidth else parentWidth if (widthSoFar >= checkWidth) { isFirstRow = false - selected_contacts.addView(newLinearLayout) + binding.selectedContacts.addView(newLinearLayout) newLinearLayout = LinearLayout(this) newLinearLayout.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) newLinearLayout.orientation = LinearLayout.HORIZONTAL @@ -1473,7 +1477,7 @@ class ThreadActivity : SimpleActivity() { newLinearLayout.addView(layout) } } - selected_contacts.addView(newLinearLayout) + binding.selectedContacts.addView(newLinearLayout) } private fun removeSelectedContact(id: Int) { @@ -1579,13 +1583,13 @@ class ThreadActivity : SimpleActivity() { } private fun updateMessageType() { - val text = thread_type_message.text.toString() + val text = binding.messageHolder.threadTypeMessage.text.toString() val stringId = if (isMmsMessage(text)) { R.string.mms } else { R.string.sms } - thread_send_message.setText(stringId) + binding.messageHolder.threadSendMessage.setText(stringId) } private fun showScheduledMessageInfo(message: Message) { @@ -1620,7 +1624,7 @@ class ThreadActivity : SimpleActivity() { private fun editScheduledMessage(message: Message) { scheduledMessage = message clearCurrentMessage() - thread_type_message.setText(message.body) + binding.messageHolder.threadTypeMessage.setText(message.body) extractAttachments(message) scheduledDateTime = DateTime(message.millis()) showScheduleMessageDialog() @@ -1645,18 +1649,18 @@ class ThreadActivity : SimpleActivity() { } } - private fun setupScheduleSendUi() { + private fun setupScheduleSendUi() = binding.messageHolder.apply { val textColor = getProperTextColor() - scheduled_message_holder.background.applyColorFilter(getProperPrimaryColor().darkenColor()) - scheduled_message_icon.applyColorFilter(textColor) - scheduled_message_button.apply { + scheduledMessageHolder.background.applyColorFilter(getProperPrimaryColor().darkenColor()) + scheduledMessageIcon.applyColorFilter(textColor) + scheduledMessageButton.apply { setTextColor(textColor) setOnClickListener { launchScheduleSendDialog(scheduledDateTime) } } - discard_scheduled_message.apply { + discardScheduledMessage.apply { applyColorFilter(textColor) setOnClickListener { hideScheduleSendUi() @@ -1671,11 +1675,11 @@ class ThreadActivity : SimpleActivity() { private fun showScheduleMessageDialog() { isScheduledMessage = true updateSendButtonDrawable() - scheduled_message_holder.beVisible() + binding.messageHolder.scheduledMessageHolder.beVisible() val dateTime = scheduledDateTime val millis = dateTime.millis - scheduled_message_button.text = if (dateTime.yearOfCentury().get() > DateTime.now().yearOfCentury().get()) { + binding.messageHolder.scheduledMessageButton.text = if (dateTime.yearOfCentury().get() > DateTime.now().yearOfCentury().get()) { millis.formatDate(this) } else { val flags = FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or FORMAT_NO_YEAR @@ -1685,7 +1689,7 @@ class ThreadActivity : SimpleActivity() { private fun hideScheduleSendUi() { isScheduledMessage = false - scheduled_message_holder.beGone() + binding.messageHolder.scheduledMessageHolder.beGone() updateSendButtonDrawable() } @@ -1697,7 +1701,7 @@ class ThreadActivity : SimpleActivity() { } ResourcesCompat.getDrawable(resources, drawableResId, theme)?.apply { applyColorFilter(getProperTextColor()) - thread_send_message.setCompoundDrawablesWithIntrinsicBounds(null, this, null, null) + binding.messageHolder.threadSendMessage.setCompoundDrawablesWithIntrinsicBounds(null, this, null, null) } } @@ -1726,7 +1730,7 @@ class ThreadActivity : SimpleActivity() { .map { Attachment(null, messageId, it.uri.toString(), it.mimetype, 0, 0, it.filename) } .toArrayList() - private fun setupAttachmentPickerView() { + private fun setupAttachmentPickerView() = binding.messageHolder.attachmentPicker.apply { val buttonColors = arrayOf( R.color.md_red_500, R.color.md_brown_500, @@ -1738,14 +1742,14 @@ class ThreadActivity : SimpleActivity() { R.color.md_blue_500 ).map { ResourcesCompat.getColor(resources, it, theme) } arrayOf( - choose_photo_icon, - choose_video_icon, - take_photo_icon, - record_video_icon, - record_audio_icon, - pick_file_icon, - pick_contact_icon, - schedule_message_icon + choosePhotoIcon, + chooseVideoIcon, + takePhotoIcon, + recordVideoIcon, + recordAudioIcon, + pickFileIcon, + pickContactIcon, + scheduleMessageIcon ).forEachIndexed { index, icon -> val iconColor = buttonColors[index] icon.background.applyColorFilter(iconColor) @@ -1754,38 +1758,38 @@ class ThreadActivity : SimpleActivity() { val textColor = getProperTextColor() arrayOf( - choose_photo_text, - choose_video_text, - take_photo_text, - record_video_text, - record_audio_text, - pick_file_text, - pick_contact_text, - schedule_message_text + choosePhotoText, + chooseVideoText, + takePhotoText, + recordVideoText, + recordAudioText, + pickFileText, + pickContactText, + scheduleMessageText ).forEach { it.setTextColor(textColor) } - choose_photo.setOnClickListener { + choosePhoto.setOnClickListener { launchGetContentIntent(arrayOf("image/*"), PICK_PHOTO_INTENT) } - choose_video.setOnClickListener { + chooseVideo.setOnClickListener { launchGetContentIntent(arrayOf("video/*"), PICK_VIDEO_INTENT) } - take_photo.setOnClickListener { + takePhoto.setOnClickListener { launchCapturePhotoIntent() } - record_video.setOnClickListener { + recordVideo.setOnClickListener { launchCaptureVideoIntent() } - record_audio.setOnClickListener { + recordAudio.setOnClickListener { launchCaptureAudioIntent() } - pick_file.setOnClickListener { + pickFile.setOnClickListener { launchGetContentIntent(arrayOf("*/*"), PICK_DOCUMENT_INTENT) } - pick_contact.setOnClickListener { + pickContact.setOnClickListener { launchPickContactIntent() } - schedule_message.setOnClickListener { + scheduleMessage.setOnClickListener { if (isScheduledMessage) { launchScheduleSendDialog(scheduledDateTime) } else { @@ -1795,20 +1799,20 @@ class ThreadActivity : SimpleActivity() { } private fun showAttachmentPicker() { - attachment_picker_divider.showWithAnimation() - attachment_picker_holder.showWithAnimation() + binding.messageHolder.attachmentPickerDivider.showWithAnimation() + binding.messageHolder.attachmentPickerHolder.showWithAnimation() animateAttachmentButton(rotation = -135f) } private fun maybeSetupRecycleBinView() { if (isRecycleBin) { - thread_send_message_holder.beGone() + binding.messageHolder.root.beGone() } } private fun hideAttachmentPicker() { - attachment_picker_divider.beGone() - attachment_picker_holder.apply { + binding.messageHolder.attachmentPickerDivider.beGone() + binding.messageHolder.attachmentPickerHolder.apply { beGone() updateLayoutParams { height = config.keyboardHeight @@ -1818,7 +1822,7 @@ class ThreadActivity : SimpleActivity() { } private fun animateAttachmentButton(rotation: Float) { - thread_add_attachment.animate() + binding.messageHolder.threadAddAttachment.animate() .rotation(rotation) .setDuration(500L) .setInterpolator(OvershootInterpolator()) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/VCardViewerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/VCardViewerActivity.kt index 8eee0efb..df2360d5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/VCardViewerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/VCardViewerActivity.kt @@ -5,9 +5,11 @@ import android.net.Uri import android.os.Bundle import com.simplemobiletools.commons.extensions.normalizePhoneNumber import com.simplemobiletools.commons.extensions.sendEmailIntent +import com.simplemobiletools.commons.extensions.viewBinding import com.simplemobiletools.commons.helpers.NavigationIcon import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.adapters.VCardViewerAdapter +import com.simplemobiletools.smsmessenger.databinding.ActivityVcardViewerBinding import com.simplemobiletools.smsmessenger.extensions.dialNumber import com.simplemobiletools.smsmessenger.helpers.EXTRA_VCARD_URI import com.simplemobiletools.smsmessenger.helpers.parseVCardFromUri @@ -16,17 +18,18 @@ import com.simplemobiletools.smsmessenger.models.VCardWrapper import ezvcard.VCard import ezvcard.property.Email import ezvcard.property.Telephone -import kotlinx.android.synthetic.main.activity_vcard_viewer.* class VCardViewerActivity : SimpleActivity() { + private val binding by viewBinding(ActivityVcardViewerBinding::inflate) + override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) - setContentView(R.layout.activity_vcard_viewer) + setContentView(binding.root) - updateMaterialActivityViews(vcard_viewer_coordinator, contacts_list, useTransparentNavigation = true, useTopSearchMenu = false) - setupMaterialScrollListener(contacts_list, vcard_toolbar) + updateMaterialActivityViews(binding.vcardViewerCoordinator, binding.contactsList, useTransparentNavigation = true, useTopSearchMenu = false) + setupMaterialScrollListener(binding.contactsList, binding.vcardToolbar) val vCardUri = intent.getParcelableExtra(EXTRA_VCARD_URI) as? Uri if (vCardUri != null) { @@ -41,11 +44,11 @@ class VCardViewerActivity : SimpleActivity() { override fun onResume() { super.onResume() - setupToolbar(vcard_toolbar, NavigationIcon.Arrow) + setupToolbar(binding.vcardToolbar, NavigationIcon.Arrow) } private fun setupOptionsMenu(vCardUri: Uri) { - vcard_toolbar.setOnMenuItemClickListener { menuItem -> + binding.vcardToolbar.setOnMenuItemClickListener { menuItem -> when (menuItem.itemId) { R.id.add_contact -> { val intent = Intent(Intent.ACTION_VIEW).apply { @@ -55,6 +58,7 @@ class VCardViewerActivity : SimpleActivity() { } startActivity(intent) } + else -> return@setOnMenuItemClickListener false } return@setOnMenuItemClickListener true @@ -69,7 +73,7 @@ class VCardViewerActivity : SimpleActivity() { handleClick(item) } } - contacts_list.adapter = adapter + binding.contactsList.adapter = adapter } private fun handleClick(property: VCardPropertyWrapper) { diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AttachmentsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AttachmentsAdapter.kt index adad4bb1..28603e50 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AttachmentsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AttachmentsAdapter.kt @@ -2,11 +2,12 @@ package com.simplemobiletools.smsmessenger.adapters import android.content.Intent import android.graphics.drawable.Drawable -import android.view.View +import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import androidx.viewbinding.ViewBinding import com.bumptech.glide.Glide import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.DiskCacheStrategy @@ -21,18 +22,19 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.smsmessenger.R 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.helpers.* 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( val activity: BaseSimpleActivity, val recyclerView: RecyclerView, val onAttachmentsRemoved: () -> Unit, val onReady: (() -> Unit) -) : ListAdapter(AttachmentDiffCallback()) { +) : ListAdapter(AttachmentDiffCallback()) { private val config = activity.config private val resources = activity.resources @@ -45,37 +47,35 @@ class AttachmentsAdapter( return getItem(position).viewType } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val layoutRes = when (viewType) { - ATTACHMENT_DOCUMENT -> R.layout.item_attachment_document_preview - ATTACHMENT_VCARD -> R.layout.item_attachment_vcard_preview - ATTACHMENT_MEDIA -> R.layout.item_attachment_media_preview + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AttachmentsViewHolder { + val inflater = LayoutInflater.from(parent.context) + val binding = when (viewType) { + ATTACHMENT_DOCUMENT -> ItemAttachmentDocumentPreviewBinding.inflate(inflater, parent, false) + ATTACHMENT_VCARD -> ItemAttachmentVcardPreviewBinding.inflate(inflater, parent, false) + ATTACHMENT_MEDIA -> ItemAttachmentMediaPreviewBinding.inflate(inflater, parent, false) else -> throw IllegalArgumentException("Unknown view type: $viewType") } - val view = activity.layoutInflater.inflate(layoutRes, parent, false) - return ViewHolder(view) + return AttachmentsViewHolder(binding) } - override fun onBindViewHolder(holder: ViewHolder, position: Int) { + override fun onBindViewHolder(holder: AttachmentsViewHolder, position: Int) { val attachment = getItem(position) - holder.bindView() { view, _ -> + holder.bindView { binding, _ -> when (attachment.viewType) { ATTACHMENT_DOCUMENT -> { - view.setupDocumentPreview( + (binding as ItemAttachmentDocumentPreviewBinding).setupDocumentPreview( uri = attachment.uri, title = attachment.filename, mimeType = attachment.mimetype, - attachment = true, onClick = { activity.launchViewIntent(attachment.uri, attachment.mimetype, attachment.filename) }, onRemoveButtonClicked = { removeAttachment(attachment) } ) } ATTACHMENT_VCARD -> { - view.setupVCardPreview( + (binding as ItemAttachmentVcardPreviewBinding).setupVCardPreview( activity = activity, uri = attachment.uri, - attachment = true, onClick = { val intent = Intent(activity, VCardViewerActivity::class.java).also { it.putExtra(EXTRA_VCARD_URI, attachment.uri) @@ -85,7 +85,10 @@ class AttachmentsAdapter( 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) { - view.apply { - media_attachment_holder.background.applyColorFilter(primaryColor.darkenColor()) - media_attachment_holder.setOnClickListener { + private fun setupMediaPreview(binding: ItemAttachmentMediaPreviewBinding, attachment: AttachmentSelection) { + binding.apply { + mediaAttachmentHolder.background.applyColorFilter(primaryColor.darkenColor()) + mediaAttachmentHolder.setOnClickListener { activity.launchViewIntent(attachment.uri, attachment.mimetype, attachment.filename) } - remove_attachment_button.apply { + + removeAttachmentButtonHolder.removeAttachmentButton.apply { beVisible() background.applyColorFilter(primaryColor) setOnClickListener { @@ -130,19 +134,21 @@ class AttachmentsAdapter( val compressImage = attachment.mimetype.isImageMimeType() && !attachment.mimetype.isGifMimeType() if (compressImage && attachment.isPending && config.mmsFileSizeLimit != FILE_SIZE_NONE) { thumbnail.beGone() - compression_progress.beVisible() + compressionProgress.beVisible() imageCompressor.compressImage(attachment.uri, config.mmsFileSizeLimit) { compressedUri -> activity.runOnUiThread { when (compressedUri) { attachment.uri -> { attachments.find { it.uri == attachment.uri }?.isPending = false - loadMediaPreview(view, attachment) + loadMediaPreview(this, attachment) } + null -> { activity.toast(R.string.compress_error) removeAttachment(attachment) } + else -> { attachments.remove(attachment) addAttachment(attachment.copy(uri = compressedUri, isPending = false)) @@ -152,12 +158,12 @@ class AttachmentsAdapter( } } } 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 size = resources.getDimension(R.dimen.attachment_preview_size).toInt() @@ -165,7 +171,7 @@ class AttachmentsAdapter( .diskCacheStrategy(DiskCacheStrategy.NONE) .transform(CenterCrop(), RoundedCorners(roundedCornersRadius)) - Glide.with(view.thumbnail) + Glide.with(binding.thumbnail) .load(attachment.uri) .transition(DrawableTransitionOptions.withCrossFade()) .override(size, size) @@ -178,20 +184,18 @@ class AttachmentsAdapter( } override fun onResourceReady(dr: Drawable?, a: Any?, t: Target?, d: DataSource?, i: Boolean): Boolean { - view.thumbnail.beVisible() - view.play_icon.beVisibleIf(attachment.mimetype.isVideoMimeType()) - view.compression_progress.beGone() + binding.thumbnail.beVisible() + binding.playIcon.beVisibleIf(attachment.mimetype.isVideoMimeType()) + binding.compressionProgress.beGone() return false } }) - .into(view.thumbnail) + .into(binding.thumbnail) } - open inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { - fun bindView(callback: (itemView: View, adapterPosition: Int) -> Unit): View { - return itemView.apply { - callback(this, adapterPosition) - } + inner class AttachmentsViewHolder(val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) { + fun bindView(callback: (binding: ViewBinding, adapterPosition: Int) -> Unit) { + callback(binding, adapterPosition) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AutoCompleteTextViewAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AutoCompleteTextViewAdapter.kt index ab18578f..c4562f46 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AutoCompleteTextViewAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AutoCompleteTextViewAdapter.kt @@ -5,17 +5,14 @@ import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter import android.widget.Filter -import android.widget.RelativeLayout -import android.widget.TextView +import com.simplemobiletools.commons.databinding.ItemContactWithNumberBinding import com.simplemobiletools.commons.extensions.darkenColor import com.simplemobiletools.commons.extensions.getContrastColor import com.simplemobiletools.commons.extensions.getProperBackgroundColor import com.simplemobiletools.commons.extensions.normalizeString import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.models.SimpleContact -import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.activities.SimpleActivity -import com.simplemobiletools.smsmessenger.extensions.config class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: ArrayList) : ArrayAdapter(activity, 0, contacts) { var resultList = ArrayList() @@ -24,27 +21,26 @@ class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: Ar val contact = resultList.getOrNull(position) var listItem = convertView if (listItem == null || listItem.tag != contact?.name?.isNotEmpty()) { - listItem = LayoutInflater.from(activity).inflate(R.layout.item_contact_with_number, parent, false) + listItem = ItemContactWithNumberBinding.inflate(LayoutInflater.from(activity), parent, false).root } - listItem!!.apply { - tag = contact?.name?.isNotEmpty() + listItem.tag = contact?.name?.isNotEmpty() + ItemContactWithNumberBinding.bind(listItem).apply { // clickable and focusable properties seem to break Autocomplete clicking, so remove them - findViewById(R.id.item_contact_frame).apply { + itemContactFrame.apply { isClickable = false isFocusable = false } val backgroundColor = activity.getProperBackgroundColor() - findViewById(R.id.item_contact_holder).setBackgroundColor(backgroundColor.darkenColor()) - - findViewById(R.id.item_contact_name).setTextColor(backgroundColor.getContrastColor()) - findViewById(R.id.item_contact_number).setTextColor(backgroundColor.getContrastColor()) + itemContactFrame.setBackgroundColor(backgroundColor.darkenColor()) + itemContactName.setTextColor(backgroundColor.getContrastColor()) + itemContactNumber.setTextColor(backgroundColor.getContrastColor()) if (contact != null) { - findViewById(R.id.item_contact_name).text = contact.name - findViewById(R.id.item_contact_number).text = contact.phoneNumbers.first().normalizedNumber - SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.name) + itemContactName.text = contact.name + itemContactNumber.text = contact.phoneNumbers.first().normalizedNumber + SimpleContactsHelper(context).loadContactImage(contact.photoUri, itemContactImage, contact.name) } } @@ -72,7 +68,7 @@ class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: Ar } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { - if (results?.count ?: -1 > 0) { + if ((results?.count ?: -1) > 0) { notifyDataSetChanged() } else { notifyDataSetInvalidated() diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/BaseConversationsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/BaseConversationsAdapter.kt index 17ba7623..c4425dbd 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/BaseConversationsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/BaseConversationsAdapter.kt @@ -5,7 +5,6 @@ import android.os.Parcelable import android.util.TypedValue import android.view.View import android.view.ViewGroup -import android.widget.TextView import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView 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.ensureBackgroundThread import com.simplemobiletools.commons.views.MyRecyclerView -import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.activities.SimpleActivity +import com.simplemobiletools.smsmessenger.databinding.ItemConversationBinding import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.models.Conversation -import kotlinx.android.synthetic.main.item_conversation.view.* @Suppress("LeakingThis") abstract class BaseConversationsAdapter( @@ -82,7 +80,10 @@ abstract class BaseConversationsAdapter( 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) { val conversation = getItem(position) @@ -97,7 +98,8 @@ abstract class BaseConversationsAdapter( override fun onViewRecycled(holder: ViewHolder) { super.onViewRecycled(holder) 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) { - view.apply { - setupViewBackground(activity) + ItemConversationBinding.bind(view).apply { + root.setupViewBackground(activity) val smsDraft = drafts[conversation.threadId] - draft_indicator.beVisibleIf(smsDraft != null) - draft_indicator.setTextColor(properPrimaryColor) + draftIndicator.beVisibleIf(smsDraft != null) + draftIndicator.setTextColor(properPrimaryColor) - pin_indicator.beVisibleIf(activity.config.pinnedConversations.contains(conversation.threadId.toString())) - pin_indicator.applyColorFilter(textColor) + pinIndicator.beVisibleIf(activity.config.pinnedConversations.contains(conversation.threadId.toString())) + pinIndicator.applyColorFilter(textColor) - conversation_frame.isSelected = selectedKeys.contains(conversation.hashCode()) + conversationFrame.isSelected = selectedKeys.contains(conversation.hashCode()) - conversation_address.apply { + conversationAddress.apply { text = conversation.title setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f) } - conversation_body_short.apply { + conversationBodyShort.apply { text = smsDraft ?: conversation.snippet setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f) } - conversation_date.apply { + conversationDate.apply { text = conversation.date.formatDateOrTime(context, true, false) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f) } val style = if (conversation.read) { - conversation_body_short.alpha = 0.7f + conversationBodyShort.alpha = 0.7f if (conversation.isScheduled) Typeface.ITALIC else Typeface.NORMAL } else { - conversation_body_short.alpha = 1f + conversationBodyShort.alpha = 1f if (conversation.isScheduled) Typeface.BOLD_ITALIC else Typeface.BOLD } - conversation_address.setTypeface(null, style) - conversation_body_short.setTypeface(null, style) + conversationAddress.setTypeface(null, style) + conversationBodyShort.setTypeface(null, style) - arrayListOf(conversation_address, conversation_body_short, conversation_date).forEach { + arrayListOf(conversationAddress, conversationBodyShort, conversationDate).forEach { it.setTextColor(textColor) } // at group conversations we use an icon as the placeholder, not any letter val placeholder = if (conversation.isGroupConversation) { - SimpleContactsHelper(context).getColoredGroupIcon(conversation.title) + SimpleContactsHelper(activity).getColoredGroupIcon(conversation.title) } else { null } - SimpleContactsHelper(context).loadContactImage(conversation.photoUri, conversation_image, conversation.title, placeholder) + SimpleContactsHelper(activity).loadContactImage(conversation.photoUri, conversationImage, conversation.title, placeholder) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ContactsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ContactsAdapter.kt index e134baf3..3a039e46 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ContactsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ContactsAdapter.kt @@ -5,17 +5,14 @@ import android.util.TypedValue import android.view.Menu import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView import com.bumptech.glide.Glide import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter +import com.simplemobiletools.commons.databinding.ItemContactWithNumberBinding import com.simplemobiletools.commons.extensions.getTextSize import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.commons.views.MyRecyclerView -import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.activities.SimpleActivity -import java.util.* class ContactsAdapter( activity: SimpleActivity, var contacts: ArrayList, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit @@ -40,11 +37,14 @@ class ContactsAdapter( 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) { val contact = contacts[position] - holder.bindView(contact, true, false) { itemView, layoutPosition -> + holder.bindView(contact, allowSingleClick = true, allowLongClick = false) { itemView, _ -> setupView(itemView, contact) } bindViewHolder(holder) @@ -62,27 +62,28 @@ class ContactsAdapter( } private fun setupView(view: View, contact: SimpleContact) { - view.apply { - findViewById(R.id.item_contact_name).apply { + ItemContactWithNumberBinding.bind(view).apply { + itemContactName.apply { text = contact.name setTextColor(textColor) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f) } - findViewById(R.id.item_contact_number).apply { + itemContactNumber.apply { text = TextUtils.join(", ", contact.phoneNumbers.map { it.normalizedNumber }) setTextColor(textColor) 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) { super.onViewRecycled(holder) if (!activity.isDestroyed && !activity.isFinishing) { - Glide.with(activity).clear(holder.itemView.findViewById(R.id.item_contact_image)) + val binding = ItemContactWithNumberBinding.bind(holder.itemView) + Glide.with(activity).clear(binding.itemContactImage) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/SearchResultsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/SearchResultsAdapter.kt index f594e76c..6b61c164 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/SearchResultsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/SearchResultsAdapter.kt @@ -10,10 +10,9 @@ import com.simplemobiletools.commons.extensions.getTextSize import com.simplemobiletools.commons.extensions.highlightTextPart import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.views.MyRecyclerView -import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.activities.SimpleActivity +import com.simplemobiletools.smsmessenger.databinding.ItemSearchResultBinding import com.simplemobiletools.smsmessenger.models.SearchResult -import kotlinx.android.synthetic.main.item_search_result.view.* class SearchResultsAdapter( activity: SimpleActivity, var searchResults: ArrayList, recyclerView: MyRecyclerView, highlightText: String, itemClick: (Any) -> Unit @@ -40,11 +39,14 @@ class SearchResultsAdapter( 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) { val searchResult = searchResults[position] - holder.bindView(searchResult, true, false) { itemView, layoutPosition -> + holder.bindView(searchResult, allowSingleClick = true, allowLongClick = false) { itemView, _ -> setupView(itemView, searchResult) } bindViewHolder(holder) @@ -64,33 +66,34 @@ class SearchResultsAdapter( } private fun setupView(view: View, searchResult: SearchResult) { - view.apply { - search_result_title.apply { + ItemSearchResultBinding.bind(view).apply { + searchResultTitle.apply { text = searchResult.title.highlightTextPart(textToHighlight, properPrimaryColor) setTextColor(textColor) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f) } - search_result_snippet.apply { + searchResultSnippet.apply { text = searchResult.snippet.highlightTextPart(textToHighlight, properPrimaryColor) setTextColor(textColor) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f) } - search_result_date.apply { + searchResultDate.apply { text = searchResult.date setTextColor(textColor) 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) { super.onViewRecycled(holder) - if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.search_result_image != null) { - Glide.with(activity).clear(holder.itemView.search_result_image) + if (!activity.isDestroyed && !activity.isFinishing) { + val binding = ItemSearchResultBinding.bind(holder.itemView) + Glide.with(activity).clear(binding.searchResultImage) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ThreadAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ThreadAdapter.kt index 67fae1e3..a436b71d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ThreadAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ThreadAdapter.kt @@ -12,7 +12,13 @@ import android.util.TypedValue import android.view.Menu import android.view.View 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.viewbinding.ViewBinding import com.bumptech.glide.Glide import com.bumptech.glide.load.DataSource 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.ThreadActivity import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity +import com.simplemobiletools.smsmessenger.databinding.* import com.simplemobiletools.smsmessenger.dialogs.DeleteConfirmationDialog import com.simplemobiletools.smsmessenger.dialogs.MessageDetailsDialog 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.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( activity: SimpleActivity, @@ -121,16 +116,16 @@ class ThreadAdapter( override fun onActionModeDestroyed() {} override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val layout = when (viewType) { - THREAD_LOADING -> R.layout.item_thread_loading - THREAD_DATE_TIME -> R.layout.item_thread_date_time - THREAD_RECEIVED_MESSAGE -> R.layout.item_received_message - THREAD_SENT_MESSAGE_ERROR -> R.layout.item_thread_error - THREAD_SENT_MESSAGE_SENT -> R.layout.item_thread_success - THREAD_SENT_MESSAGE_SENDING -> R.layout.item_thread_sending - else -> R.layout.item_sent_message + val binding = when (viewType) { + THREAD_LOADING -> ItemThreadLoadingBinding.inflate(layoutInflater, parent, false) + THREAD_DATE_TIME -> ItemThreadDateTimeBinding.inflate(layoutInflater, parent, false) + THREAD_SENT_MESSAGE_ERROR -> ItemThreadErrorBinding.inflate(layoutInflater, parent, false) + THREAD_SENT_MESSAGE_SENT -> ItemThreadSuccessBinding.inflate(layoutInflater, parent, false) + THREAD_SENT_MESSAGE_SENDING -> ItemThreadSendingBinding.inflate(layoutInflater, parent, false) + else -> ItemMessageBinding.inflate(layoutInflater, parent, false) } - return createViewHolder(layout, parent) + + return ThreadViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { @@ -278,258 +273,289 @@ class ThreadAdapter( } private fun setupView(holder: ViewHolder, view: View, message: Message) { - view.apply { - thread_message_holder.isSelected = selectedKeys.contains(message.hashCode()) - thread_message_body.apply { + ItemMessageBinding.bind(view).apply { + threadMessageHolder.isSelected = selectedKeys.contains(message.hashCode()) + threadMessageBody.apply { text = message.body setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize) + beVisibleIf(message.body.isNotEmpty()) + setOnLongClickListener { + holder.viewLongClicked() + true + } + + setOnClickListener { + holder.viewClicked(message) + } } - thread_message_body.beVisibleIf(message.body.isNotEmpty()) if (message.isReceivedMessage()) { - setupReceivedMessageView(view, message) + setupReceivedMessageView(messageBinding = this, message = message) } else { - setupSentMessageView(view, message) - } - - thread_message_body.setOnLongClickListener { - holder.viewLongClicked() - true - } - - thread_message_body.setOnClickListener { - holder.viewClicked(message) + setupSentMessageView(messageBinding = this, message = message) } if (message.attachment?.attachments?.isNotEmpty() == true) { - thread_mesage_attachments_holder.beVisible() - thread_mesage_attachments_holder.removeAllViews() + threadMessageAttachmentsHolder.beVisible() + threadMessageAttachmentsHolder.removeAllViews() for (attachment in message.attachment.attachments) { val mimetype = attachment.mimetype when { - mimetype.isImageMimeType() || mimetype.isVideoMimeType() -> setupImageView(holder, view, message, attachment) - mimetype.isVCardMimeType() -> setupVCardView(holder, view, message, attachment) - else -> setupFileView(holder, view, message, attachment) + mimetype.isImageMimeType() || mimetype.isVideoMimeType() -> setupImageView(holder, binding = this, message, attachment) + mimetype.isVCardMimeType() -> setupVCardView(holder, threadMessageAttachmentsHolder, message, attachment) + else -> setupFileView(holder, threadMessageAttachmentsHolder, message, attachment) } - thread_message_play_outline.beVisibleIf(mimetype.startsWith("video/")) + threadMessagePlayOutline.beVisibleIf(mimetype.startsWith("video/")) } } else { - thread_mesage_attachments_holder.beGone() + threadMessageAttachmentsHolder.beGone() + threadMessagePlayOutline.beGone() } } } - private fun setupReceivedMessageView(view: View, message: Message) { - view.apply { - thread_message_sender_photo.beVisible() - thread_message_sender_photo.setOnClickListener { + private fun setupReceivedMessageView(messageBinding: ItemMessageBinding, message: Message) { + messageBinding.apply { + with(ConstraintSet()) { + 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()!! - context.getContactFromAddress(contact.phoneNumbers.first().normalizedNumber) { + activity.getContactFromAddress(contact.phoneNumbers.first().normalizedNumber) { if (it != null) { 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) { - val contactLetterIcon = SimpleContactsHelper(context).getContactLetterIcon(message.senderName) - val placeholder = BitmapDrawable(context.resources, contactLetterIcon) + val contactLetterIcon = SimpleContactsHelper(activity).getContactLetterIcon(message.senderName) + val placeholder = BitmapDrawable(activity.resources, contactLetterIcon) val options = RequestOptions() .diskCacheStrategy(DiskCacheStrategy.RESOURCE) .error(placeholder) .centerCrop() - Glide.with(context) + Glide.with(activity) .load(message.senderPhotoUri) .placeholder(placeholder) .apply(options) .apply(RequestOptions.circleCropTransform()) - .into(thread_message_sender_photo) + .into(threadMessageSenderPhoto) } } } - private fun setupSentMessageView(view: View, message: Message) { - view.apply { - thread_message_sender_photo?.beGone() - val background = context.getProperPrimaryColor() - thread_message_body.background.applyColorFilter(background) - - val contrastColor = background.getContrastColor() - thread_message_body.setTextColor(contrastColor) - thread_message_body.setLinkTextColor(contrastColor) - - val padding = thread_message_body.paddingStart - if (message.isScheduled) { - thread_message_scheduled_icon.beVisible() - thread_message_scheduled_icon.applyColorFilter(contrastColor) - - val iconWidth = resources.getDimensionPixelSize(R.dimen.small_icon_size) - val rightPadding = padding + iconWidth - thread_message_body.setPadding(padding, padding, rightPadding, padding) - thread_message_body.typeface = Typeface.create(Typeface.DEFAULT, Typeface.ITALIC) - } else { - thread_message_scheduled_icon.beGone() - - thread_message_body.setPadding(padding, padding, padding, padding) - thread_message_body.typeface = Typeface.DEFAULT + private fun setupSentMessageView(messageBinding: ItemMessageBinding, message: Message) { + messageBinding.apply { + with(ConstraintSet()) { + clone(threadMessageHolder) + clear(threadMessageWrapper.id, ConstraintSet.START) + connect(threadMessageWrapper.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END) + applyTo(threadMessageHolder) } - } - } - private fun setupImageView(holder: ViewHolder, parent: View, message: Message, attachment: Attachment) { - val mimetype = attachment.mimetype - val uri = attachment.getUri() - parent.apply { - val imageView = layoutInflater.inflate(R.layout.item_attachment_image, null) - thread_mesage_attachments_holder.addView(imageView) + val primaryColor = activity.getProperPrimaryColor() + val contrastColor = primaryColor.getContrastColor() - val placeholderDrawable = ColorDrawable(Color.TRANSPARENT) - val isTallImage = attachment.height > attachment.width - val transformation = if (isTallImage) CenterCrop() else FitCenter() - val options = RequestOptions() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .placeholder(placeholderDrawable) - .transform(transformation) + threadMessageBody.apply { + updateLayoutParams { + removeRule(RelativeLayout.END_OF) + addRule(RelativeLayout.ALIGN_PARENT_END) + } - var builder = Glide.with(context) - .load(uri) - .apply(options) - .listener(object : RequestListener { - override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { - thread_message_play_outline.beGone() - thread_mesage_attachments_holder.removeView(imageView) - return false + background = AppCompatResources.getDrawable(activity, R.drawable.item_sent_background) + background.applyColorFilter(primaryColor) + setTextColor(contrastColor) + setLinkTextColor(contrastColor) + + if (message.isScheduled) { + typeface = Typeface.create(Typeface.DEFAULT, Typeface.ITALIC) + val scheduledDrawable = AppCompatResources.getDrawable(activity, R.drawable.ic_clock_vector)?.apply { + applyColorFilter(contrastColor) + val size = lineHeight + setBounds(0, 0, size, size) } - override fun onResourceReady(dr: Drawable?, a: Any?, t: Target?, d: DataSource?, i: Boolean) = false - }) - - // limit attachment sizes to avoid causing OOM - var wantedAttachmentSize = Size(attachment.width, attachment.height) - if (wantedAttachmentSize.width > maxChatBubbleWidth) { - val newHeight = wantedAttachmentSize.height / (wantedAttachmentSize.width / maxChatBubbleWidth) - wantedAttachmentSize = Size(maxChatBubbleWidth.toInt(), newHeight.toInt()) - } - - builder = if (isTallImage) { - builder.override(wantedAttachmentSize.width, wantedAttachmentSize.width) - } else { - builder.override(wantedAttachmentSize.width, wantedAttachmentSize.height) - } - - try { - builder.into(imageView.attachment_image) - } catch (ignore: Exception) { - } - - imageView.attachment_image.setOnClickListener { - if (actModeCallback.isSelectable) { - holder.viewClicked(message) + setCompoundDrawables(null, null, scheduledDrawable, null) } else { - activity.launchViewIntent(uri, mimetype, attachment.filename) + typeface = Typeface.DEFAULT + setCompoundDrawables(null, null, null, null) } } - imageView.setOnLongClickListener { - holder.viewLongClicked() - true - } } } - private fun setupVCardView(holder: ViewHolder, parent: View, message: Message, attachment: Attachment) { - val uri = attachment.getUri() - parent.apply { - val vCardView = layoutInflater.inflate(R.layout.item_attachment_vcard, null).apply { - setupVCardPreview( - activity = activity, - uri = uri, - onClick = { - if (actModeCallback.isSelectable) { - holder.viewClicked(message) - } else { - val intent = Intent(context, VCardViewerActivity::class.java).also { - it.putExtra(EXTRA_VCARD_URI, uri) - } - context.startActivity(intent) - } - }, - onLongClick = { holder.viewLongClicked() } - ) - } - thread_mesage_attachments_holder.addView(vCardView) - } - } - - private fun setupFileView(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 uri = attachment.getUri() - parent.apply { - val attachmentView = layoutInflater.inflate(R.layout.item_attachment_document, null).apply { - setupDocumentPreview( - uri = uri, - title = attachment.filename, - mimeType = attachment.mimetype, - onClick = { - if (actModeCallback.isSelectable) { - holder.viewClicked(message) - } else { - activity.launchViewIntent(uri, mimetype, attachment.filename) - } - }, - onLongClick = { holder.viewLongClicked() }, - ) - } - thread_mesage_attachments_holder.addView(attachmentView) + + val imageView = ItemAttachmentImageBinding.inflate(layoutInflater) + threadMessageAttachmentsHolder.addView(imageView.root) + + val placeholderDrawable = ColorDrawable(Color.TRANSPARENT) + val isTallImage = attachment.height > attachment.width + val transformation = if (isTallImage) CenterCrop() else FitCenter() + val options = RequestOptions() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .placeholder(placeholderDrawable) + .transform(transformation) + + var builder = Glide.with(root.context) + .load(uri) + .apply(options) + .listener(object : RequestListener { + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + threadMessagePlayOutline.beGone() + threadMessageAttachmentsHolder.removeView(imageView.root) + return false + } + + override fun onResourceReady(dr: Drawable?, a: Any?, t: Target?, d: DataSource?, i: Boolean) = false + }) + + // limit attachment sizes to avoid causing OOM + var wantedAttachmentSize = Size(attachment.width, attachment.height) + if (wantedAttachmentSize.width > maxChatBubbleWidth) { + val newHeight = wantedAttachmentSize.height / (wantedAttachmentSize.width / maxChatBubbleWidth) + wantedAttachmentSize = Size(maxChatBubbleWidth.toInt(), newHeight.toInt()) } + + builder = if (isTallImage) { + builder.override(wantedAttachmentSize.width, wantedAttachmentSize.width) + } else { + builder.override(wantedAttachmentSize.width, wantedAttachmentSize.height) + } + + try { + builder.into(imageView.attachmentImage) + } catch (ignore: Exception) { + } + + imageView.attachmentImage.setOnClickListener { + if (actModeCallback.isSelectable) { + holder.viewClicked(message) + } else { + activity.launchViewIntent(uri, mimetype, attachment.filename) + } + } + imageView.root.setOnLongClickListener { + holder.viewLongClicked() + true + } + } + + private fun setupVCardView(holder: ViewHolder, parent: LinearLayout, message: Message, attachment: Attachment) { + val uri = attachment.getUri() + val vCardView = ItemAttachmentVcardBinding.inflate(layoutInflater).apply { + setupVCardPreview( + activity = activity, + uri = uri, + onClick = { + if (actModeCallback.isSelectable) { + holder.viewClicked(message) + } else { + val intent = Intent(activity, VCardViewerActivity::class.java).also { + it.putExtra(EXTRA_VCARD_URI, uri) + } + activity.startActivity(intent) + } + }, + onLongClick = { holder.viewLongClicked() } + ) + }.root + + parent.addView(vCardView) + } + + private fun setupFileView(holder: ViewHolder, parent: LinearLayout, message: Message, attachment: Attachment) { + val mimetype = attachment.mimetype + val uri = attachment.getUri() + val attachmentView = ItemAttachmentDocumentBinding.inflate(layoutInflater).apply { + setupDocumentPreview( + uri = uri, + title = attachment.filename, + mimeType = attachment.mimetype, + onClick = { + if (actModeCallback.isSelectable) { + holder.viewClicked(message) + } else { + activity.launchViewIntent(uri, mimetype, attachment.filename) + } + }, + onLongClick = { holder.viewLongClicked() } + ) + }.root + + parent.addView(attachmentView) } private fun setupDateTime(view: View, dateTime: ThreadDateTime) { - view.apply { - thread_date_time.apply { - text = dateTime.date.formatDateOrTime(context, false, false) + ItemThreadDateTimeBinding.bind(view).apply { + threadDateTime.apply { + text = dateTime.date.formatDateOrTime(context, hideTimeAtOtherDays = false, showYearEvenIfCurrent = false) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize) } - thread_date_time.setTextColor(textColor) + threadDateTime.setTextColor(textColor) - thread_sim_icon.beVisibleIf(hasMultipleSIMCards) - thread_sim_number.beVisibleIf(hasMultipleSIMCards) + threadSimIcon.beVisibleIf(hasMultipleSIMCards) + threadSimNumber.beVisibleIf(hasMultipleSIMCards) if (hasMultipleSIMCards) { - thread_sim_number.text = dateTime.simID - thread_sim_number.setTextColor(textColor.getContrastColor()) - thread_sim_icon.applyColorFilter(textColor) + threadSimNumber.text = dateTime.simID + threadSimNumber.setTextColor(textColor.getContrastColor()) + threadSimIcon.applyColorFilter(textColor) } } } 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) - view.thread_success.applyColorFilter(textColor) + ItemThreadSuccessBinding.bind(view).apply { + threadSuccess.setImageResource(if (isDelivered) R.drawable.ic_check_double_vector else R.drawable.ic_check_vector) + threadSuccess.applyColorFilter(textColor) + } } 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) { - view.thread_sending.apply { + ItemThreadSendingBinding.bind(view).threadSending.apply { setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize) 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) { super.onViewRecycled(holder) - if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.thread_message_sender_photo != null) { - Glide.with(activity).clear(holder.itemView.thread_message_sender_photo) + if (!activity.isDestroyed && !activity.isFinishing) { + 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() { diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/VCardViewerAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/VCardViewerAdapter.kt index e6484c83..b0d344bf 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/VCardViewerAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/VCardViewerAdapter.kt @@ -1,7 +1,6 @@ package com.simplemobiletools.smsmessenger.adapters import android.util.TypedValue -import android.view.View import android.view.ViewGroup import androidx.core.graphics.drawable.toDrawable import androidx.recyclerview.widget.RecyclerView @@ -14,14 +13,17 @@ import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.smsmessenger.R 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.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( activity: SimpleActivity, private var items: MutableList, private val itemClick: (Any) -> Unit -) : RecyclerView.Adapter() { +) : RecyclerView.Adapter() { private var fontSize = activity.getTextSize() private var textColor = activity.getProperTextColor() @@ -31,123 +33,129 @@ class VCardViewerAdapter( override fun getItemViewType(position: Int): Int { return when (val item = items[position]) { - is VCardWrapper -> R.layout.item_vcard_contact - is VCardPropertyWrapper -> R.layout.item_vcard_contact_property + is VCardWrapper -> TYPE_VCARD_CONTACT + is VCardPropertyWrapper -> TYPE_VCARD_CONTACT_PROPERTY else -> throw IllegalArgumentException("Unexpected type: ${item::class.simpleName}") } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VCardViewHolder { - val view = layoutInflater.inflate(viewType, parent, false) - return VCardViewHolder(view) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + 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 itemView = holder.bindView() - when (item) { - is VCardWrapper -> setupVCardView(itemView, item) - is VCardPropertyWrapper -> setupVCardPropertyView(itemView, item) - else -> throw IllegalArgumentException("Unexpected type: ${item::class.simpleName}") + when (holder) { + is VCardContactViewHolder -> holder.bindView(item as VCardWrapper) + is VCardPropertyViewHolder -> holder.bindView(item as VCardPropertyWrapper) } } - private fun setupVCardView(view: View, item: VCardWrapper) { - val name = item.fullName - view.apply { - item_contact_name.apply { - text = name - setTextColor(textColor) - setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.1f) - } - item_contact_image.apply { - val photo = item.vCard.photos.firstOrNull() - val placeholder = if (name != null) { - SimpleContactsHelper(context).getContactLetterIcon(name).toDrawable(resources) - } else { - null + inner class VCardContactViewHolder(val binding: ItemVcardContactBinding) : RecyclerView.ViewHolder(binding.root) { + fun bindView(item: VCardWrapper) { + val name = item.fullName + binding.apply { + itemContactName.apply { + text = name + setTextColor(textColor) + setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.1f) } - val roundingRadius = resources.getDimensionPixelSize(R.dimen.big_margin) - val transformation = RoundedCorners(roundingRadius) - val options = RequestOptions() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .placeholder(placeholder) - .transform(transformation) - Glide.with(this) - .load(photo?.data ?: photo?.url) - .apply(options) - .transition(DrawableTransitionOptions.withCrossFade()) - .into(this) - } - expand_collapse_icon.apply { - val expandCollapseDrawable = if (item.expanded) { - R.drawable.ic_collapse_up - } else { - R.drawable.ic_expand_down - } - setImageResource(expandCollapseDrawable) - applyColorFilter(textColor) - } + itemContactImage.apply { + val photo = item.vCard.photos.firstOrNull() + val placeholder = if (name != null) { + SimpleContactsHelper(context).getContactLetterIcon(name).toDrawable(resources) + } else { + null + } - if (items.size > 1) { - setOnClickListener { - expandOrCollapseRow(view, item) + val roundingRadius = resources.getDimensionPixelSize(R.dimen.big_margin) + val transformation = RoundedCorners(roundingRadius) + val options = RequestOptions() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .placeholder(placeholder) + .transform(transformation) + Glide.with(this) + .load(photo?.data ?: photo?.url) + .apply(options) + .transition(DrawableTransitionOptions.withCrossFade()) + .into(this) } - } - onGlobalLayout { - if (items.size == 1) { - expandOrCollapseRow(view, item) - view.expand_collapse_icon.beGone() + expandCollapseIcon.apply { + val expandCollapseDrawable = if (item.expanded) { + R.drawable.ic_collapse_up + } else { + R.drawable.ic_expand_down + } + setImageResource(expandCollapseDrawable) + applyColorFilter(textColor) + } + + if (items.size > 1) { + root.setOnClickListener { + expandOrCollapseRow(item) + } + } + root.onGlobalLayout { + if (items.size == 1) { + expandOrCollapseRow(item) + expandCollapseIcon.beGone() + } } } } - } - private fun setupVCardPropertyView(view: View, property: VCardPropertyWrapper) { - view.apply { - item_vcard_property_title.apply { - text = property.value - setTextColor(textColor) - setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.1f) + private fun expandOrCollapseRow(item: VCardWrapper) { + val properties = item.properties + if (item.expanded) { + collapseRow(properties, item) + } else { + expandRow(properties, item) } - item_vcard_property_subtitle.apply { - text = property.type - setTextColor(textColor) - } - view.setOnClickListener { - itemClick(property) + } + + private fun expandRow(properties: List, vCardWrapper: VCardWrapper) { + vCardWrapper.expanded = true + val nextPosition = items.indexOf(vCardWrapper) + 1 + items.addAll(nextPosition, properties) + notifyItemRangeInserted(nextPosition, properties.size) + binding.expandCollapseIcon.setImageResource(R.drawable.ic_collapse_up) + } + + private fun collapseRow(properties: List, vCardWrapper: VCardWrapper) { + vCardWrapper.expanded = false + val nextPosition = items.indexOf(vCardWrapper) + 1 + repeat(properties.size) { + items.removeAt(nextPosition) } + notifyItemRangeRemoved(nextPosition, properties.size) + binding.expandCollapseIcon.setImageResource(R.drawable.ic_expand_down) } } - private fun expandOrCollapseRow(view: View, item: VCardWrapper) { - val properties = item.properties - if (item.expanded) { - collapseRow(view, properties, item) - } else { - expandRow(view, properties, item) + inner class VCardPropertyViewHolder(val binding: ItemVcardContactPropertyBinding) : RecyclerView.ViewHolder(binding.root) { + 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) + } + } } } - - private fun expandRow(view: View, properties: List, vCardWrapper: VCardWrapper) { - vCardWrapper.expanded = true - val nextPosition = items.indexOf(vCardWrapper) + 1 - items.addAll(nextPosition, properties) - notifyItemRangeInserted(nextPosition, properties.size) - view.expand_collapse_icon.setImageResource(R.drawable.ic_collapse_up) - } - - private fun collapseRow(view: View, properties: List, vCardWrapper: VCardWrapper) { - vCardWrapper.expanded = false - val nextPosition = items.indexOf(vCardWrapper) + 1 - repeat(properties.size) { - items.removeAt(nextPosition) - } - notifyItemRangeRemoved(nextPosition, properties.size) - view.expand_collapse_icon.setImageResource(R.drawable.ic_expand_down) - } - - inner class VCardViewHolder(view: View) : RecyclerView.ViewHolder(view) { - fun bindView() = itemView - } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/AddBlockedKeywordDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/AddBlockedKeywordDialog.kt index 2f55e791..4d2ebdbf 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/AddBlockedKeywordDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/AddBlockedKeywordDialog.kt @@ -7,14 +7,14 @@ import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.showKeyboard import com.simplemobiletools.commons.extensions.value import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.databinding.DialogAddBlockedKeywordBinding 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) { init { - val view = activity.layoutInflater.inflate(R.layout.dialog_add_blocked_keyword, null).apply { + val binding = DialogAddBlockedKeywordBinding.inflate(activity.layoutInflater).apply { 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) .setNegativeButton(R.string.cancel, null) .apply { - activity.setupDialogStuff(view, this) { alertDialog -> - alertDialog.showKeyboard(view.add_blocked_keyword_edittext) + activity.setupDialogStuff(binding.root, this) { alertDialog -> + alertDialog.showKeyboard(binding.addBlockedKeywordEdittext) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { - val newBlockedKeyword = view.add_blocked_keyword_edittext.value + val newBlockedKeyword = binding.addBlockedKeywordEdittext.value if (originalKeyword != null && newBlockedKeyword != originalKeyword) { activity.config.removeBlockedKeyword(originalKeyword) } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/DeleteConfirmationDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/DeleteConfirmationDialog.kt index f72a7513..b1d7327d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/DeleteConfirmationDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/DeleteConfirmationDialog.kt @@ -6,8 +6,7 @@ import com.simplemobiletools.commons.extensions.beGoneIf import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.smsmessenger.R -import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.delete_remember_title -import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.skip_the_recycle_bin_checkbox +import com.simplemobiletools.smsmessenger.databinding.DialogDeleteConfirmationBinding class DeleteConfirmationDialog( private val activity: Activity, @@ -17,16 +16,16 @@ class DeleteConfirmationDialog( ) { private var dialog: AlertDialog? = null - val view = activity.layoutInflater.inflate(R.layout.dialog_delete_confirmation, null)!! + val binding = DialogDeleteConfirmationBinding.inflate(activity.layoutInflater) init { - view.delete_remember_title.text = message - view.skip_the_recycle_bin_checkbox.beGoneIf(!showSkipRecycleBinOption) + binding.deleteRememberTitle.text = message + binding.skipTheRecycleBinCheckbox.beGoneIf(!showSkipRecycleBinOption) activity.getAlertDialogBuilder() .setPositiveButton(R.string.yes) { _, _ -> dialogConfirmed() } .setNegativeButton(R.string.no, null) .apply { - activity.setupDialogStuff(view, this) { alertDialog -> + activity.setupDialogStuff(binding.root, this) { alertDialog -> dialog = alertDialog } } @@ -34,6 +33,6 @@ class DeleteConfirmationDialog( private fun dialogConfirmed() { dialog?.dismiss() - callback(view.skip_the_recycle_bin_checkbox.isChecked) + callback(binding.skipTheRecycleBinCheckbox.isChecked) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ExportMessagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ExportMessagesDialog.kt index b25556e0..1c9c1a77 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ExportMessagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ExportMessagesDialog.kt @@ -1,14 +1,11 @@ package com.simplemobiletools.smsmessenger.dialogs -import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.activities.SimpleActivity +import com.simplemobiletools.smsmessenger.databinding.DialogExportMessagesBinding 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( private val activity: SimpleActivity, @@ -17,10 +14,10 @@ class ExportMessagesDialog( private val config = activity.config init { - val view = (activity.layoutInflater.inflate(R.layout.dialog_export_messages, null) as ViewGroup).apply { - export_sms_checkbox.isChecked = config.exportSms - export_mms_checkbox.isChecked = config.exportMms - export_messages_filename.setText( + val binding = DialogExportMessagesBinding.inflate(activity.layoutInflater).apply { + exportSmsCheckbox.isChecked = config.exportSms + exportMmsCheckbox.isChecked = config.exportMms + exportMessagesFilename.setText( activity.getString(R.string.messages) + "_" + activity.getCurrentFormattedDateTime() ) } @@ -29,11 +26,11 @@ class ExportMessagesDialog( .setPositiveButton(R.string.ok, null) .setNegativeButton(R.string.cancel, null) .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 { - config.exportSms = view.export_sms_checkbox.isChecked - config.exportMms = view.export_mms_checkbox.isChecked - val filename = view.export_messages_filename.value + config.exportSms = binding.exportSmsCheckbox.isChecked + config.exportMms = binding.exportMmsCheckbox.isChecked + val filename = binding.exportMessagesFilename.value when { filename.isEmpty() -> activity.toast(R.string.empty_name) filename.isAValidFilename() -> { diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ImportMessagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ImportMessagesDialog.kt index 626115fa..e626d8be 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ImportMessagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ImportMessagesDialog.kt @@ -1,6 +1,5 @@ package com.simplemobiletools.smsmessenger.dialogs -import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import com.simplemobiletools.commons.extensions.getAlertDialogBuilder 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.smsmessenger.R import com.simplemobiletools.smsmessenger.activities.SimpleActivity +import com.simplemobiletools.smsmessenger.databinding.DialogImportMessagesBinding import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.helpers.MessagesImporter -import com.simplemobiletools.smsmessenger.models.MessagesBackup import com.simplemobiletools.smsmessenger.models.ImportResult -import kotlinx.android.synthetic.main.dialog_import_messages.view.* +import com.simplemobiletools.smsmessenger.models.MessagesBackup class ImportMessagesDialog( private val activity: SimpleActivity, @@ -23,30 +22,30 @@ class ImportMessagesDialog( init { var ignoreClicks = false - val view = (activity.layoutInflater.inflate(R.layout.dialog_import_messages, null) as ViewGroup).apply { - import_sms_checkbox.isChecked = config.importSms - import_mms_checkbox.isChecked = config.importMms + val binding = DialogImportMessagesBinding.inflate(activity.layoutInflater).apply { + importSmsCheckbox.isChecked = config.importSms + importMmsCheckbox.isChecked = config.importMms } activity.getAlertDialogBuilder() .setPositiveButton(R.string.ok, null) .setNegativeButton(R.string.cancel, null) .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 { if (ignoreClicks) { 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) return@setOnClickListener } ignoreClicks = true activity.toast(R.string.importing) - config.importSms = view.import_sms_checkbox.isChecked - config.importMms = view.import_mms_checkbox.isChecked + config.importSms = binding.importSmsCheckbox.isChecked + config.importMms = binding.importMmsCheckbox.isChecked ensureBackgroundThread { MessagesImporter(activity).restoreMessages(messages) { handleParseResult(it) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/InvalidNumberDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/InvalidNumberDialog.kt index ee49c311..c7b82677 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/InvalidNumberDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/InvalidNumberDialog.kt @@ -4,18 +4,18 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.setupDialogStuff 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) { init { - val view = activity.layoutInflater.inflate(R.layout.dialog_invalid_number, null).apply { - dialog_invalid_number_desc.text = text + val binding = DialogInvalidNumberBinding.inflate(activity.layoutInflater).apply { + dialogInvalidNumberDesc.text = text } activity.getAlertDialogBuilder() .setPositiveButton(R.string.ok) { _, _ -> { } } .apply { - activity.setupDialogStuff(view, this) + activity.setupDialogStuff(binding.root, this) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ManageBlockedKeywordsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ManageBlockedKeywordsAdapter.kt index 51c7a855..3185fda6 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ManageBlockedKeywordsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ManageBlockedKeywordsAdapter.kt @@ -11,11 +11,8 @@ import com.simplemobiletools.commons.extensions.setupViewBackground import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.databinding.ItemManageBlockedKeywordBinding 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( activity: BaseSimpleActivity, var blockedKeywords: ArrayList, val listener: RefreshRecyclerViewListener?, @@ -56,11 +53,14 @@ class ManageBlockedKeywordsAdapter( 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) { val blockedKeyword = blockedKeywords[position] - holder.bindView(blockedKeyword, true, true) { itemView, _ -> + holder.bindView(blockedKeyword, allowSingleClick = true, allowLongClick = true) { itemView, _ -> setupView(itemView, blockedKeyword) } bindViewHolder(holder) @@ -71,21 +71,21 @@ class ManageBlockedKeywordsAdapter( private fun getSelectedItems() = blockedKeywords.filter { selectedKeys.contains(it.hashCode()) } private fun setupView(view: View, blockedKeyword: String) { - view.apply { - setupViewBackground(activity) - manage_blocked_keyword_holder?.isSelected = selectedKeys.contains(blockedKeyword.hashCode()) - manage_blocked_keyword_title.apply { + ItemManageBlockedKeywordBinding.bind(view).apply { + root.setupViewBackground(activity) + manageBlockedKeywordHolder.isSelected = selectedKeys.contains(blockedKeyword.hashCode()) + manageBlockedKeywordTitle.apply { text = blockedKeyword setTextColor(textColor) } - overflow_menu_icon.drawable.apply { + overflowMenuIcon.drawable.apply { mutate() setTint(activity.getProperTextColor()) } - overflow_menu_icon.setOnClickListener { - showPopupMenu(overflow_menu_anchor, blockedKeyword) + overflowMenuIcon.setOnClickListener { + showPopupMenu(overflowMenuAnchor, blockedKeyword) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/MessageDetailsDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/MessageDetailsDialog.kt index 3088cbd8..5c846b9f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/MessageDetailsDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/MessageDetailsDialog.kt @@ -25,7 +25,7 @@ class MessageDetailsDialog(val activity: BaseSimpleActivity, val message: Messag activity.getAlertDialogBuilder() .setPositiveButton(R.string.ok) { _, _ -> } .apply { - activity.setupDialogStuff(mDialogView, this, R.string.message_details) + activity.setupDialogStuff(mDialogView.root, this, R.string.message_details) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/RenameConversationDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/RenameConversationDialog.kt index 56888968..044944ea 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/RenameConversationDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/RenameConversationDialog.kt @@ -2,15 +2,14 @@ package com.simplemobiletools.smsmessenger.dialogs import android.app.Activity import android.content.DialogInterface.BUTTON_POSITIVE -import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.showKeyboard import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.databinding.DialogRenameConversationBinding import com.simplemobiletools.smsmessenger.models.Conversation -import kotlinx.android.synthetic.main.dialog_rename_conversation.view.* class RenameConversationDialog( private val activity: Activity, @@ -20,8 +19,8 @@ class RenameConversationDialog( private var dialog: AlertDialog? = null init { - val view = (activity.layoutInflater.inflate(R.layout.dialog_rename_conversation, null) as ViewGroup).apply { - rename_conv_edit_text.apply { + val binding = DialogRenameConversationBinding.inflate(activity.layoutInflater).apply { + renameConvEditText.apply { if (conversation.usesCustomTitle) { setText(conversation.title) } @@ -34,12 +33,12 @@ class RenameConversationDialog( .setPositiveButton(R.string.ok, null) .setNegativeButton(R.string.cancel, null) .apply { - activity.setupDialogStuff(view, this, R.string.rename_conversation) { alertDialog -> + activity.setupDialogStuff(binding.root, this, R.string.rename_conversation) { alertDialog -> dialog = alertDialog - alertDialog.showKeyboard(view.rename_conv_edit_text) + alertDialog.showKeyboard(binding.renameConvEditText) alertDialog.getButton(BUTTON_POSITIVE).apply { setOnClickListener { - val newTitle = view.rename_conv_edit_text.text.toString() + val newTitle = binding.renameConvEditText.text.toString() if (newTitle.isEmpty()) { activity.toast(R.string.empty_name) return@setOnClickListener diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ScheduleMessageDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ScheduleMessageDialog.kt index 2dac5173..b586a962 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ScheduleMessageDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ScheduleMessageDialog.kt @@ -11,18 +11,18 @@ import com.google.android.material.timepicker.TimeFormat import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.databinding.ScheduleMessageDialogBinding import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.roundToClosestMultipleOf -import kotlinx.android.synthetic.main.schedule_message_dialog.view.* import org.joda.time.DateTime -import java.util.* +import java.util.Calendar class ScheduleMessageDialog( private val activity: BaseSimpleActivity, private var dateTime: DateTime? = null, 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 var previewDialog: AlertDialog? = null @@ -32,16 +32,16 @@ class ScheduleMessageDialog( private val calendar = Calendar.getInstance() init { - arrayOf(view.subtitle, view.edit_time, view.edit_date).forEach { + arrayOf(binding.subtitle, binding.editTime, binding.editDate).forEach { it.setTextColor(textColor) } - arrayOf(view.date_image, view.time_image).forEach { + arrayOf(binding.dateImage, binding.timeImage).forEach { it.applyColorFilter(textColor) } - view.edit_date.setOnClickListener { showDatePicker() } - view.edit_time.setOnClickListener { showTimePicker() } + binding.editDate.setOnClickListener { showDatePicker() } + binding.editTime.setOnClickListener { showTimePicker() } val targetDateTime = dateTime ?: DateTime.now().plusHours(1) updateTexts(targetDateTime) @@ -56,8 +56,8 @@ class ScheduleMessageDialog( private fun updateTexts(dateTime: DateTime) { val dateFormat = activity.config.dateFormat val timeFormat = activity.getTimeFormat() - view.edit_date.text = dateTime.toString(dateFormat) - view.edit_time.text = dateTime.toString(timeFormat) + binding.editDate.text = dateTime.toString(dateFormat) + binding.editTime.text = dateTime.toString(timeFormat) } private fun showPreview() { @@ -70,7 +70,7 @@ class ScheduleMessageDialog( .setNegativeButton(R.string.cancel, null) .apply { previewShown = true - activity.setupDialogStuff(view, this, R.string.schedule_message) { dialog -> + activity.setupDialogStuff(binding.root, this, R.string.schedule_message) { dialog -> previewDialog = dialog dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { if (validateDateTime()) { diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/SelectTextDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/SelectTextDialog.kt index 12da5a57..ff4ac882 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/SelectTextDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/SelectTextDialog.kt @@ -4,19 +4,19 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.setupDialogStuff 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 class SelectTextDialog(val activity: BaseSimpleActivity, val text: String) { init { - val view = activity.layoutInflater.inflate(R.layout.dialog_select_text, null).apply { - dialog_select_text_value.text = text + val binding = DialogSelectTextBinding.inflate(activity.layoutInflater).apply { + dialogSelectTextValue.text = text } activity.getAlertDialogBuilder() - .setPositiveButton(R.string.ok) { dialog, which -> { } } + .setPositiveButton(R.string.ok) { _, _ -> { } } .apply { - activity.setupDialogStuff(view, this) + activity.setupDialogStuff(binding.root, this) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/AttachmentPreviews.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/AttachmentPreviews.kt index 58aea416..0f9a11a9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/AttachmentPreviews.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/AttachmentPreviews.kt @@ -2,26 +2,44 @@ package com.simplemobiletools.smsmessenger.helpers import android.app.Activity import android.net.Uri -import android.view.View import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.ensureBackgroundThread 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 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, title: String, mimeType: String, - attachment: Boolean = false, onClick: (() -> Unit)? = null, onLongClick: (() -> 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()) { filename.text = title } @@ -29,13 +47,13 @@ fun View.setupDocumentPreview( ensureBackgroundThread { try { val size = context.getFileSizeFromUri(uri) - post { - file_size.beVisible() - file_size.text = size.formatSize() + root.post { + fileSize.beVisible() + fileSize.text = size.formatSize() } } catch (e: Exception) { - post { - file_size.beGone() + root.post { + fileSize.beGone() } } } @@ -43,18 +61,36 @@ fun View.setupDocumentPreview( val textColor = context.getProperTextColor() val primaryColor = context.getProperPrimaryColor() - document_attachment_holder.background.applyColorFilter(textColor) filename.setTextColor(textColor) - file_size.setTextColor(textColor) + fileSize.setTextColor(textColor) icon.setImageResource(getIconResourceForMimeType(mimeType)) icon.background.setTint(primaryColor) - document_attachment_holder.background.applyColorFilter(primaryColor.darkenColor()) + root.background.applyColorFilter(primaryColor.darkenColor()) - if (attachment) { - remove_attachment_button.apply { + root.setOnClickListener { + 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() - background.applyColorFilter(primaryColor) + background.applyColorFilter(activity.getProperPrimaryColor()) if (onRemoveButtonClicked != null) { setOnClickListener { onRemoveButtonClicked.invoke() @@ -62,45 +98,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, uri: Uri, attachment: Boolean = false, onClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null, - onRemoveButtonClicked: (() -> Unit)? = null, + onVCardLoaded: (() -> Unit)? = null, ) { + val context = root.context val textColor = activity.getProperTextColor() val primaryColor = activity.getProperPrimaryColor() - vcard_attachment_holder.background.applyColorFilter(primaryColor.darkenColor()) - vcard_title.setTextColor(textColor) - vcard_subtitle.setTextColor(textColor) + root.background.applyColorFilter(primaryColor.darkenColor()) + vcardTitle.setTextColor(textColor) + vcardSubtitle.setTextColor(textColor) - if (attachment) { - vcard_progress.beVisible() - } - arrayOf(vcard_photo, vcard_title, vcard_subtitle, view_contact_details).forEach { + arrayOf(vcardPhoto, vcardTitle, vcardSubtitle, viewContactDetails).forEach { it.beGone() } parseVCardFromUri(activity, uri) { vCards -> activity.runOnUiThread { if (vCards.isEmpty()) { - vcard_title.beVisible() - vcard_title.text = context.getString(R.string.unknown_error_occurred) + vcardTitle.beVisible() + vcardTitle.text = context.getString(R.string.unknown_error_occurred) return@runOnUiThread } + val title = vCards.firstOrNull()?.parseNameFromVCard() val imageIcon = if (title != null) { SimpleContactsHelper(activity).getContactLetterIcon(title) @@ -108,41 +135,32 @@ fun View.setupVCardPreview( null } - arrayOf(vcard_photo, vcard_title).forEach { + arrayOf(vcardPhoto, vcardTitle).forEach { it.beVisible() } - vcard_photo.setImageBitmap(imageIcon) - vcard_title.text = title + vcardPhoto.setImageBitmap(imageIcon) + vcardTitle.text = title if (vCards.size > 1) { - vcard_subtitle.beVisible() + vcardSubtitle.beVisible() 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 { - vcard_subtitle.beGone() + vcardSubtitle.beGone() } if (attachment) { - vcard_progress.beGone() - remove_attachment_button.apply { - beVisible() - background.applyColorFilter(primaryColor) - if (onRemoveButtonClicked != null) { - setOnClickListener { - onRemoveButtonClicked.invoke() - } - } - } + onVCardLoaded?.invoke() } else { - view_contact_details.setTextColor(primaryColor) - view_contact_details.beVisible() + viewContactDetails.setTextColor(primaryColor) + viewContactDetails.beVisible() } - vcard_attachment_holder.setOnClickListener { + vcardAttachmentHolder.setOnClickListener { onClick?.invoke() } - vcard_attachment_holder.setOnLongClickListener { + vcardAttachmentHolder.setOnLongClickListener { onLongClick?.invoke() true } diff --git a/app/src/main/res/layout/activity_thread.xml b/app/src/main/res/layout/activity_thread.xml index 7f4e1f8f..38ca5df9 100644 --- a/app/src/main/res/layout/activity_thread.xml +++ b/app/src/main/res/layout/activity_thread.xml @@ -102,7 +102,7 @@ android:id="@+id/thread_messages_fastscroller" android:layout_width="match_parent" 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:supportSwipeToRefresh="true"> @@ -117,7 +117,7 @@ app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" app:stackFromEnd="true" tools:itemCount="3" - tools:listitem="@layout/item_sent_message" /> + tools:listitem="@layout/item_message" /> @@ -134,17 +134,19 @@ tools:ignore="ContentDescription" /> + android:paddingHorizontal="@dimen/activity_margin"> + android:src="@drawable/ic_person_vector" + android:visibility="gone" + tools:visibility="visible" /> @@ -42,23 +41,26 @@ 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_marginStart="@dimen/medium_margin" + android:layout_alignEnd="@+id/thread_message_attachments_holder" + android:layout_alignBottom="@+id/thread_message_attachments_holder" + android:layout_marginEnd="@dimen/medium_margin" android:layout_marginBottom="@dimen/activity_margin" android:src="@drawable/ic_play_outline_vector" android:visibility="gone" /> - + tools:drawableEndCompat="@drawable/scheduled_message_icon" + tools:text="Message content" /> diff --git a/app/src/main/res/layout/item_sent_message.xml b/app/src/main/res/layout/item_sent_message.xml deleted file mode 100644 index 2760f71d..00000000 --- a/app/src/main/res/layout/item_sent_message.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_invalid_short_code_info.xml b/app/src/main/res/layout/layout_invalid_short_code_info.xml index 2243f2a3..e81e615e 100644 --- a/app/src/main/res/layout/layout_invalid_short_code_info.xml +++ b/app/src/main/res/layout/layout_invalid_short_code_info.xml @@ -1,6 +1,5 @@ @@ -29,7 +29,9 @@ android:layout_height="wrap_content" android:layout_alignTop="@+id/scheduled_message_button" android:layout_alignBottom="@+id/scheduled_message_button" + android:paddingStart="@dimen/medium_margin" android:paddingTop="@dimen/medium_margin" + android:paddingEnd="@dimen/small_margin" android:paddingBottom="@dimen/medium_margin" android:src="@drawable/ic_clock_vector" /> @@ -202,6 +204,7 @@ tools:visibility="visible"> diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 2d1ded29..00000000 --- a/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - ext.kotlin_version = '1.7.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.3.1' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - mavenCentral() - maven { url "https://jitpack.io" } - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..9b58ac03 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + alias(libs.plugins.android).apply(false) + alias(libs.plugins.kotlinAndroid).apply(false) + alias(libs.plugins.parcelize).apply(false) + alias(libs.plugins.kotlinSerialization).apply(false) + alias(libs.plugins.ksp).apply(false) +} + +tasks.register("clean") { + delete { + rootProject.buildDir + } +} diff --git a/gradle.properties b/gradle.properties index dbb7bf70..cfecf3f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,4 @@ android.enableJetifier=true android.useAndroidX=true +org.gradle.jvmargs=-Xmx8192m +android.nonTransitiveRClass=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..6131f66e --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,64 @@ +[versions] +#jetbrains +kotlin = "1.9.0" +kotlinxSerializationJson = "1.5.1" +#KSP +ksp = "1.9.0-1.0.12" +#AndroidX +androidx-constraintlayout = "2.1.4" +androidx-swiperefreshlayout = "1.1.0" +androidx-lifecycleprocess = "2.6.1" +#Eventbus +eventbus = "3.3.1" +#Room +room = "2.6.0-alpha03" +#Simple Mobile Tools +simple-commons = "adb7dea7ee" +android-smsmms = "5657799572" +indicator-fast-scroll = "4524cd0b61" +#Gradle +gradlePlugins-agp = "8.1.0" +#build +app-build-compileSDKVersion = "34" +app-build-targetSDK = "34" +app-build-minimumSDK = "23" +app-build-javaVersion = "VERSION_17" +app-build-kotlinJVMTarget = "17" +#Helpers +ez-vcard = "0.11.3" +shortcut-badger = "1.1.22" +#versioning +app-version-appId = "com.simplemobiletools.smsmessenger" +app-version-versionCode = "79" +app-version-versionName = "5.18.2" +[libraries] +#AndroidX +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" } +androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "androidx-lifecycleprocess" } +androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "androidx-swiperefreshlayout" } +#Room +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } +androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +#Simple Mobile Tools +simple-mobile-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons", version.ref = "simple-commons" } +indicator-fast-scroll = { module = "com.github.tibbi:IndicatorFastScroll", version.ref = "indicator-fast-scroll" } +android-smsmms = { module = "com.github.tibbi:android-smsmms", version.ref = "android-smsmms" } +#EventBus +eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" } +#Helpers +ez-vcard = { module = "com.googlecode.ez-vcard:ez-vcard", version.ref = "ez-vcard" } +shortcut-badger = { module = "me.leolin:ShortcutBadger", version.ref = "shortcut-badger" } +#Kotlin +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +[bundles] +room = [ + "androidx-room-ktx", + "androidx-room-runtime", +] +[plugins] +android = { id = "com.android.application", version.ref = "gradlePlugins-agp" } +kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 640f35a7..33bc5be6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index e7b4def4..00000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..45478cbe --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { setUrl("https://jitpack.io") } + } +} +include(":app")