From 062adb76ac89d57bb73af75244f282a1a5dfa3d9 Mon Sep 17 00:00:00 2001 From: Moez Bhatti Date: Sun, 7 Feb 2021 14:30:40 -0500 Subject: [PATCH] Revert "Implement ViewBinding" This reverts commit 37d8c45379e351e4c556c72542fae67ac857ce1a. # Conflicts: # build.gradle # presentation/src/main/java/com/moez/QKSMS/common/widget/AvatarView.kt # presentation/src/main/java/com/moez/QKSMS/common/widget/TextInputDialog.kt # presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt # presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt # presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoController.kt # presentation/src/main/java/com/moez/QKSMS/feature/conversations/ConversationsAdapter.kt # presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt # presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsController.kt --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- presentation/build.gradle | 9 +- .../com/moez/QKSMS/common/MenuItemAdapter.kt | 45 ++--- .../moez/QKSMS/common/base/FlowableAdapter.kt | 3 +- .../com/moez/QKSMS/common/base/QkActivity.kt | 12 +- .../com/moez/QKSMS/common/base/QkAdapter.kt | 3 +- .../moez/QKSMS/common/base/QkController.kt | 32 ++-- .../moez/QKSMS/common/base/QkRealmAdapter.kt | 4 +- .../QKSMS/common/base/QkThemedActivity.kt | 3 +- .../moez/QKSMS/common/base/QkViewHolder.kt | 14 +- .../util/extensions/ActivityExtensions.kt | 9 - .../common/util/extensions/ViewExtensions.kt | 6 - .../moez/QKSMS/common/widget/AvatarView.kt | 30 +-- .../QKSMS/common/widget/GroupAvatarView.kt | 19 +- .../QKSMS/common/widget/PagerTitleView.kt | 11 +- .../QKSMS/common/widget/PreferenceView.kt | 26 +-- .../com/moez/QKSMS/common/widget/QkDialog.kt | 34 ++-- .../common/widget/RadioPreferenceView.kt | 20 +- .../QKSMS/common/widget/TextInputDialog.kt | 13 +- .../QKSMS/feature/backup/BackupActivity.kt | 10 +- .../QKSMS/feature/backup/BackupAdapter.kt | 23 ++- .../QKSMS/feature/backup/BackupController.kt | 91 +++++---- .../feature/blocking/BlockingActivity.kt | 9 +- .../feature/blocking/BlockingController.kt | 25 ++- .../manager/BlockingManagerController.kt | 25 +-- .../messages/BlockedMessagesAdapter.kt | 51 ++--- .../messages/BlockedMessagesController.kt | 12 +- .../blocking/numbers/BlockedNumbersAdapter.kt | 18 +- .../numbers/BlockedNumbersController.kt | 28 +-- .../feature/changelog/ChangelogAdapter.kt | 18 +- .../feature/changelog/ChangelogDialog.kt | 15 +- .../feature/compose/AttachmentAdapter.kt | 54 +++--- .../QKSMS/feature/compose/ComposeActivity.kt | 138 +++++++------- .../QKSMS/feature/compose/MessagesAdapter.kt | 71 +++---- .../feature/compose/editing/ChipsAdapter.kt | 26 +-- .../compose/editing/ComposeItemAdapter.kt | 121 ++++++------ .../compose/editing/DetailedChipView.kt | 37 ++-- .../compose/editing/PhoneNumberAdapter.kt | 20 +- .../editing/PhoneNumberPickerAdapter.kt | 25 ++- .../QKSMS/feature/compose/part/FileBinder.kt | 42 ++--- .../QKSMS/feature/compose/part/MediaBinder.kt | 21 +-- .../QKSMS/feature/compose/part/PartBinder.kt | 31 +-- .../feature/compose/part/PartsAdapter.kt | 27 +-- .../QKSMS/feature/compose/part/VCardBinder.kt | 40 ++-- .../feature/contacts/ContactsActivity.kt | 26 ++- .../ConversationInfoActivity.kt | 9 +- .../ConversationInfoAdapter.kt | 115 ++++++----- .../ConversationInfoController.kt | 15 +- .../conversations/ConversationsAdapter.kt | 59 +++--- .../QKSMS/feature/gallery/GalleryActivity.kt | 20 +- .../feature/gallery/GalleryPagerAdapter.kt | 54 +++--- .../moez/QKSMS/feature/main/MainActivity.kt | 178 ++++++++++-------- .../moez/QKSMS/feature/main/SearchAdapter.kt | 31 +-- .../NotificationPrefsActivity.kt | 66 ++++--- .../moez/QKSMS/feature/plus/PlusActivity.kt | 70 +++---- .../QKSMS/feature/qkreply/QkReplyActivity.kt | 52 +++-- .../feature/scheduled/ScheduledActivity.kt | 37 ++-- .../scheduled/ScheduledMessageAdapter.kt | 33 ++-- .../ScheduledMessageAttachmentAdapter.kt | 20 +- .../feature/settings/SettingsActivity.kt | 9 +- .../feature/settings/SettingsController.kt | 75 ++++---- .../feature/settings/about/AboutController.kt | 13 +- .../settings/autodelete/AutoDeleteDialog.kt | 13 +- .../settings/swipe/SwipeActionsController.kt | 37 ++-- .../feature/themepicker/HSVPickerView.kt | 41 ++-- .../QKSMS/feature/themepicker/ThemeAdapter.kt | 35 ++-- .../themepicker/ThemePickerController.kt | 42 ++--- .../main/res/layout/collapsing_toolbar.xml | 1 + .../main/res/layout/contact_chip_detailed.xml | 18 +- .../src/main/res/layout/main_activity.xml | 14 +- .../main/res/layout/main_permission_hint.xml | 18 +- .../src/main/res/layout/main_syncing.xml | 4 +- .../main/res/layout/message_list_item_in.xml | 6 - .../main/res/layout/message_list_item_out.xml | 5 - .../main/res/layout/qksms_plus_activity.xml | 4 +- .../main/res/layout/scheduled_activity.xml | 4 +- .../main/res/layout/settings_theme_widget.xml | 24 ++- 78 files changed, 1208 insertions(+), 1217 deletions(-) diff --git a/build.gradle b/build.gradle index c680e5c00..14546f92e 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' + classpath 'com.android.tools.build:gradle:3.5.4' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1' classpath 'com.google.gms:google-services:4.2.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 303be1d37..4b9cec46b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Mar 03 19:56:50 EST 2020 +#Tue Dec 03 23:30:52 EST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/presentation/build.gradle b/presentation/build.gradle index ac61c22d9..457b9da17 100644 --- a/presentation/build.gradle +++ b/presentation/build.gradle @@ -19,6 +19,7 @@ apply plugin: 'com.android.application' apply plugin: 'realm-android' // Realm needs to be before Kotlin or the build will fail apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' android { @@ -69,10 +70,6 @@ android { noAnalytics { dimension "analytics" } } - viewBinding { - enabled = true - } - if (System.getenv("CI") == "true") { signingConfigs.release.storeFile = file("../keystore") signingConfigs.release.storePassword = System.getenv("keystore_password") @@ -81,6 +78,10 @@ android { } } +androidExtensions { + experimental = true +} + configurations { noAnalyticsDebug noAnalyticsRelease diff --git a/presentation/src/main/java/com/moez/QKSMS/common/MenuItemAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/common/MenuItemAdapter.kt index eba4fed2a..656305482 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/MenuItemAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/MenuItemAdapter.kt @@ -20,26 +20,26 @@ package com.moez.QKSMS.common import android.content.Context import android.content.res.ColorStateList +import android.view.LayoutInflater import android.view.ViewGroup import androidx.annotation.ArrayRes import androidx.recyclerview.widget.RecyclerView +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.databinding.MenuListItemBinding import io.reactivex.disposables.CompositeDisposable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.menu_list_item.* +import kotlinx.android.synthetic.main.menu_list_item.view.* import javax.inject.Inject data class MenuItem(val title: String, val actionId: Int) -class MenuItemAdapter @Inject constructor( - private val context: Context, - private val colors: Colors -) : QkAdapter() { +class MenuItemAdapter @Inject constructor(private val context: Context, private val colors: Colors) : QkAdapter() { val menuItemClicks: Subject = PublishSubject.create() @@ -47,13 +47,13 @@ class MenuItemAdapter @Inject constructor( var selectedItem: Int? = null set(value) { - val old = data.map { it.actionId }.indexOfFirst { it == field }.takeIf { it != -1 } - val new = data.map { it.actionId }.indexOfFirst { it == value }.takeIf { it != -1 } + val old = data.map { it.actionId }.indexOfFirst { it == field } + val new = data.map { it.actionId }.indexOfFirst { it == value } field = value - old?.let(::notifyItemChanged) - new?.let(::notifyItemChanged) + old.let { notifyItemChanged(it) } + new.let { notifyItemChanged(it) } } fun setData(@ArrayRes titles: Int, @ArrayRes values: Int = -1) { @@ -63,28 +63,31 @@ class MenuItemAdapter @Inject constructor( .mapIndexed { index, title -> MenuItem(title, valueInts?.getOrNull(index) ?: index) } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, MenuListItemBinding::inflate).apply { - val states = arrayOf( - intArrayOf(android.R.attr.state_activated), - intArrayOf(-android.R.attr.state_activated)) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + val view = layoutInflater.inflate(R.layout.menu_list_item, parent, false) - val text = parent.context.resolveThemeColor(android.R.attr.textColorTertiary) - binding.check.imageTintList = ColorStateList(states, intArrayOf(colors.theme().theme, text)) + val states = arrayOf( + intArrayOf(android.R.attr.state_activated), + intArrayOf(-android.R.attr.state_activated)) - binding.root.setOnClickListener { + val text = parent.context.resolveThemeColor(android.R.attr.textColorTertiary) + view.check.imageTintList = ColorStateList(states, intArrayOf(colors.theme().theme, text)) + + return QkViewHolder(view).apply { + view.setOnClickListener { val menuItem = getItem(adapterPosition) menuItemClicks.onNext(menuItem.actionId) } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val menuItem = getItem(position) - holder.binding.title.text = menuItem.title - holder.binding.check.isActivated = (menuItem.actionId == selectedItem) - holder.binding.check.setVisible(selectedItem != null) + holder.title.text = menuItem.title + holder.check.isActivated = (menuItem.actionId == selectedItem) + holder.check.setVisible(selectedItem != null) } override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/FlowableAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/FlowableAdapter.kt index 7cd3f6156..1a71d5163 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/FlowableAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/FlowableAdapter.kt @@ -20,7 +20,6 @@ package com.moez.QKSMS.common.base import androidx.annotation.CallSuper import androidx.recyclerview.widget.RecyclerView -import androidx.viewbinding.ViewBinding import io.reactivex.Flowable import io.reactivex.disposables.Disposable @@ -28,7 +27,7 @@ import io.reactivex.disposables.Disposable * Base RecyclerView.Adapter that provides some convenience when creating a new Adapter, such as * data list handing and item animations */ -abstract class FlowableAdapter : QkAdapter() { +abstract class FlowableAdapter : QkAdapter() { var flowable: Flowable>? = null set(value) { diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/QkActivity.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/QkActivity.kt index 8da859f06..379224fd7 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/QkActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/QkActivity.kt @@ -22,20 +22,14 @@ import android.annotation.SuppressLint import android.os.Bundle import android.view.Menu import android.view.MenuItem -import android.view.View import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.Toolbar -import com.moez.QKSMS.R -import com.moez.QKSMS.common.widget.QkTextView import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.toolbar.* abstract class QkActivity : AppCompatActivity() { - val toolbar by lazy { findViewById(R.id.toolbar)!! } - protected val menu: Subject = BehaviorSubject.create() - protected val toolbarTitle by lazy { findViewById(R.id.toolbarTitle) } @SuppressLint("InlinedApi") override fun onCreate(savedInstanceState: Bundle?) { @@ -53,8 +47,8 @@ abstract class QkActivity : AppCompatActivity() { } } - override fun setContentView(view: View?) { - super.setContentView(view) + override fun setContentView(layoutResID: Int) { + super.setContentView(layoutResID) setSupportActionBar(toolbar) title = title // The title may have been set before layout inflation } diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/QkAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/QkAdapter.kt index d55d8e721..0101f4351 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/QkAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/QkAdapter.kt @@ -22,7 +22,6 @@ import android.view.View import androidx.core.view.isVisible import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView -import androidx.viewbinding.ViewBinding import com.moez.QKSMS.common.util.extensions.setVisible import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject @@ -31,7 +30,7 @@ import io.reactivex.subjects.Subject * Base RecyclerView.Adapter that provides some convenience when creating a new Adapter, such as * data list handing and item animations */ -abstract class QkAdapter : RecyclerView.Adapter>() { +abstract class QkAdapter : RecyclerView.Adapter() { var data: List = ArrayList() set(value) { diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/QkController.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/QkController.kt index 33d6b0c63..deefa8e21 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/QkController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/QkController.kt @@ -21,17 +21,15 @@ package com.moez.QKSMS.common.base import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.LayoutRes import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.Toolbar -import androidx.viewbinding.ViewBinding import com.bluelinelabs.conductor.archlifecycle.LifecycleController -import com.moez.QKSMS.R -import com.moez.QKSMS.common.widget.QkTextView +import kotlinx.android.extensions.LayoutContainer +import kotlinx.android.synthetic.* +import kotlinx.android.synthetic.main.toolbar.view.* -abstract class QkController, State, Presenter : QkPresenter, Binding : ViewBinding>( - private val bindingInflater: (LayoutInflater, ViewGroup, Boolean) -> Binding -) : LifecycleController() { +abstract class QkController, State, Presenter : QkPresenter> : LifecycleController(), LayoutContainer { abstract var presenter: Presenter @@ -41,15 +39,16 @@ abstract class QkController, State, Present protected val themedActivity: QkThemedActivity? get() = activity as? QkThemedActivity - private val toolbar by lazy { view?.findViewById(R.id.toolbar) } - private val toolbarTitle by lazy { view?.findViewById(R.id.toolbarTitle) } + override var containerView: View? = null - lateinit var binding: Binding + @LayoutRes + var layoutRes: Int = 0 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View { - binding = bindingInflater(inflater, container, false) - onViewCreated() - return binding.root + return inflater.inflate(layoutRes, container, false).also { + containerView = it + onViewCreated() + } } open fun onViewCreated() { @@ -61,13 +60,18 @@ abstract class QkController, State, Present fun setTitle(title: CharSequence?) { activity?.title = title - toolbarTitle?.text = title + view?.toolbarTitle?.text = title } fun showBackButton(show: Boolean) { appCompatActivity?.supportActionBar?.setDisplayHomeAsUpEnabled(show) } + override fun onDestroyView(view: View) { + containerView = null + clearFindViewByIdCache() + } + override fun onDestroy() { super.onDestroy() presenter.onCleared() diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/QkRealmAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/QkRealmAdapter.kt index 31fb5306d..7b1d8997e 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/QkRealmAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/QkRealmAdapter.kt @@ -20,7 +20,6 @@ package com.moez.QKSMS.common.base import android.view.View import androidx.recyclerview.widget.RecyclerView -import androidx.viewbinding.ViewBinding import com.moez.QKSMS.common.util.extensions.setVisible import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject @@ -31,8 +30,7 @@ import io.realm.RealmRecyclerViewAdapter import io.realm.RealmResults import timber.log.Timber -abstract class QkRealmAdapter - : RealmRecyclerViewAdapter>(null, true) { +abstract class QkRealmAdapter : RealmRecyclerViewAdapter(null, true) { /** * This view can be set, and the adapter will automatically control the visibility of this view diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt index e6bfd358c..14b858b2c 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt @@ -44,6 +44,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.rxkotlin.Observables import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.toolbar.* import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -133,7 +134,7 @@ abstract class QkThemedActivity : QkActivity() { // Set the color for the overflow and navigation icon val textSecondary = resolveThemeColor(android.R.attr.textColorSecondary) - toolbar.overflowIcon = toolbar.overflowIcon?.apply { setTint(textSecondary) } + toolbar?.overflowIcon = toolbar?.overflowIcon?.apply { setTint(textSecondary) } // Update the colours of the menu items Observables.combineLatest(menu, theme) { menu, theme -> diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/QkViewHolder.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/QkViewHolder.kt index b246c5b28..56e674349 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/QkViewHolder.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/QkViewHolder.kt @@ -18,16 +18,10 @@ */ package com.moez.QKSMS.common.base -import android.view.LayoutInflater -import android.view.ViewGroup +import android.view.View import androidx.recyclerview.widget.RecyclerView -import androidx.viewbinding.ViewBinding - -class QkViewHolder(val binding: T) : RecyclerView.ViewHolder(binding.root) { - - constructor( - parent: ViewGroup, - bindingInflator: (LayoutInflater, ViewGroup, Boolean) -> T - ) : this(bindingInflator(LayoutInflater.from(parent.context), parent, false)) +import kotlinx.android.extensions.LayoutContainer +class QkViewHolder(view: View) : RecyclerView.ViewHolder(view), LayoutContainer { + override val containerView: View = view } diff --git a/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ActivityExtensions.kt b/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ActivityExtensions.kt index c99257466..3d4f59f59 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ActivityExtensions.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ActivityExtensions.kt @@ -20,10 +20,7 @@ package com.moez.QKSMS.common.util.extensions import android.app.Activity import android.content.Context -import android.view.LayoutInflater import android.view.inputmethod.InputMethodManager -import androidx.appcompat.app.AppCompatActivity -import androidx.viewbinding.ViewBinding fun Activity.dismissKeyboard() { window.currentFocus?.let { focus -> @@ -33,9 +30,3 @@ fun Activity.dismissKeyboard() { focus.clearFocus() } } - -inline fun AppCompatActivity.viewBinding( - crossinline bindingInflater: (LayoutInflater) -> T -): Lazy = lazy(LazyThreadSafetyMode.NONE) { - bindingInflater(layoutInflater) -} diff --git a/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ViewExtensions.kt b/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ViewExtensions.kt index eec96d543..f2bf92d17 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ViewExtensions.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ViewExtensions.kt @@ -23,7 +23,6 @@ import android.content.Context import android.content.res.ColorStateList import android.graphics.PorterDuff import android.os.Build -import android.view.LayoutInflater import android.view.MotionEvent import android.view.View import android.view.ViewGroup @@ -32,7 +31,6 @@ import android.widget.EditText import android.widget.ImageView import android.widget.ProgressBar import androidx.recyclerview.widget.RecyclerView -import androidx.viewbinding.ViewBinding import androidx.viewpager.widget.ViewPager var ViewGroup.animateLayoutChanges: Boolean @@ -125,7 +123,3 @@ fun RecyclerView.scrapViews() { recycledViewPool.clear() adapter?.notifyDataSetChanged() } - -inline fun ViewGroup.viewBinding(crossinline bindingInflater: (LayoutInflater, ViewGroup) -> T): T { - return bindingInflater(LayoutInflater.from(context), this) -} diff --git a/presentation/src/main/java/com/moez/QKSMS/common/widget/AvatarView.kt b/presentation/src/main/java/com/moez/QKSMS/common/widget/AvatarView.kt index b5a06769b..f6703ed8a 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/widget/AvatarView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/widget/AvatarView.kt @@ -20,17 +20,17 @@ package com.moez.QKSMS.common.widget import android.content.Context import android.util.AttributeSet +import android.view.View import android.widget.FrameLayout import com.moez.QKSMS.R import com.moez.QKSMS.common.Navigator import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.AvatarViewBinding import com.moez.QKSMS.injection.appComponent import com.moez.QKSMS.model.Recipient import com.moez.QKSMS.util.GlideApp +import kotlinx.android.synthetic.main.avatar_view.view.* import javax.inject.Inject class AvatarView @JvmOverloads constructor( @@ -39,21 +39,21 @@ class AvatarView @JvmOverloads constructor( @Inject lateinit var colors: Colors @Inject lateinit var navigator: Navigator - private lateinit var theme: Colors.Theme - - private val binding = viewBinding(AvatarViewBinding::inflate) private var lookupKey: String? = null private var fullName: String? = null private var photoUri: String? = null private var lastUpdated: Long? = null + private var theme: Colors.Theme init { if (!isInEditMode) { appComponent.inject(this) - theme = colors.theme() } + theme = colors.theme() + + View.inflate(context, R.layout.avatar_view, this) setBackgroundResource(R.drawable.circle) clipToOutline = true } @@ -81,8 +81,8 @@ class AvatarView @JvmOverloads constructor( private fun updateView() { // Apply theme setBackgroundTint(theme.theme) - binding.initial.setTextColor(theme.textPrimary) - binding.icon.setTint(theme.textPrimary) + initial.setTextColor(theme.textPrimary) + icon.setTint(theme.textPrimary) val initials = fullName ?.substringBefore(',') @@ -93,18 +93,18 @@ class AvatarView @JvmOverloads constructor( .map { initial -> initial.toString() } if (initials.isNotEmpty()) { - binding.initial.text = if (initials.size > 1) initials.first() + initials.last() else initials.first() - binding.icon.visibility = GONE + initial.text = if (initials.size > 1) initials.first() + initials.last() else initials.first() + icon.visibility = GONE } else { - binding.initial.text = null - binding.icon.visibility = VISIBLE + initial.text = null + icon.visibility = VISIBLE } - binding.photo.setImageDrawable(null) + photo.setImageDrawable(null) photoUri?.let { photoUri -> - GlideApp.with(binding.photo) + GlideApp.with(photo) .load(photoUri) - .into(binding.photo) + .into(photo) } } } diff --git a/presentation/src/main/java/com/moez/QKSMS/common/widget/GroupAvatarView.kt b/presentation/src/main/java/com/moez/QKSMS/common/widget/GroupAvatarView.kt index 3237773ca..85b240a15 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/widget/GroupAvatarView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/widget/GroupAvatarView.kt @@ -20,15 +20,16 @@ package com.moez.QKSMS.common.widget import android.content.Context import android.util.AttributeSet +import android.view.View import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams +import com.moez.QKSMS.R import com.moez.QKSMS.common.util.extensions.getColorCompat import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setBackgroundTint -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.GroupAvatarViewBinding import com.moez.QKSMS.model.Recipient +import kotlinx.android.synthetic.main.group_avatar_view.view.* class GroupAvatarView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null @@ -40,7 +41,9 @@ class GroupAvatarView @JvmOverloads constructor( updateView() } - private val binding = viewBinding(GroupAvatarViewBinding::inflate) + init { + View.inflate(context, R.layout.group_avatar_view, this) + } override fun onFinishInflate() { super.onFinishInflate() @@ -51,18 +54,18 @@ class GroupAvatarView @JvmOverloads constructor( } private fun updateView() { - binding.avatar1Frame.setBackgroundTint(when (recipients.size > 1) { + avatar1Frame.setBackgroundTint(when (recipients.size > 1) { true -> context.resolveThemeColor(android.R.attr.windowBackground) false -> context.getColorCompat(android.R.color.transparent) }) - binding.avatar1Frame.updateLayoutParams { + avatar1Frame.updateLayoutParams { matchConstraintPercentWidth = if (recipients.size > 1) 0.75f else 1.0f } - binding.avatar2.isVisible = recipients.size > 1 + avatar2.isVisible = recipients.size > 1 - recipients.getOrNull(0).run(binding.avatar1::setRecipient) - recipients.getOrNull(1).run(binding.avatar2::setRecipient) + recipients.getOrNull(0).run(avatar1::setRecipient) + recipients.getOrNull(1).run(avatar2::setRecipient) } } diff --git a/presentation/src/main/java/com/moez/QKSMS/common/widget/PagerTitleView.kt b/presentation/src/main/java/com/moez/QKSMS/common/widget/PagerTitleView.kt index ad38263a7..0d3d5db6b 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/widget/PagerTitleView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/widget/PagerTitleView.kt @@ -25,10 +25,10 @@ import android.view.LayoutInflater import android.widget.LinearLayout import android.widget.TextView import androidx.viewpager.widget.ViewPager +import com.moez.QKSMS.R import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.forEach import com.moez.QKSMS.common.util.extensions.resolveThemeColor -import com.moez.QKSMS.databinding.TabViewBinding import com.moez.QKSMS.extensions.Optional import com.moez.QKSMS.injection.appComponent import com.moez.QKSMS.repository.ConversationRepository @@ -36,6 +36,7 @@ import com.uber.autodispose.android.ViewScopeProvider import com.uber.autodispose.autoDisposable import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.tab_view.view.* import javax.inject.Inject class PagerTitleView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { @@ -65,11 +66,11 @@ class PagerTitleView @JvmOverloads constructor(context: Context, attrs: Attribut removeAllViews() pager?.adapter?.count?.forEach { position -> - val binding = TabViewBinding.inflate(LayoutInflater.from(context), this, false) - binding.label.text = pager?.adapter?.getPageTitle(position) - binding.root.setOnClickListener { pager?.currentItem = position } + val view = LayoutInflater.from(context).inflate(R.layout.tab_view, this, false) + view.label.text = pager?.adapter?.getPageTitle(position) + view.setOnClickListener { pager?.currentItem = position } - addView(binding.root) + addView(view) } childCount.forEach { index -> diff --git a/presentation/src/main/java/com/moez/QKSMS/common/widget/PreferenceView.kt b/presentation/src/main/java/com/moez/QKSMS/common/widget/PreferenceView.kt index 366f1408d..4e1a724c7 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/widget/PreferenceView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/widget/PreferenceView.kt @@ -28,9 +28,8 @@ import com.moez.QKSMS.R import com.moez.QKSMS.common.util.extensions.resolveThemeAttribute import com.moez.QKSMS.common.util.extensions.resolveThemeColorStateList import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.PreferenceViewBinding import com.moez.QKSMS.injection.appComponent +import kotlinx.android.synthetic.main.preference_view.view.* class PreferenceView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null @@ -43,7 +42,7 @@ class PreferenceView @JvmOverloads constructor( if (isInEditMode) { findViewById(R.id.titleView).text = value } else { - binding.titleView.text = value + titleView.text = value } } @@ -58,23 +57,22 @@ class PreferenceView @JvmOverloads constructor( setVisible(value?.isNotEmpty() == true) } } else { - binding.summaryView.text = value - binding.summaryView.setVisible(value?.isNotEmpty() == true) + summaryView.text = value + summaryView.setVisible(value?.isNotEmpty() == true) } } - val binding: PreferenceViewBinding = viewBinding(PreferenceViewBinding::inflate) - init { if (!isInEditMode) { appComponent.inject(this) } + View.inflate(context, R.layout.preference_view, this) setBackgroundResource(context.resolveThemeAttribute(R.attr.selectableItemBackground)) orientation = HORIZONTAL gravity = Gravity.CENTER_VERTICAL - binding.icon.imageTintList = context.resolveThemeColorStateList(android.R.attr.textColorSecondary) + icon.imageTintList = context.resolveThemeColorStateList(android.R.attr.textColorSecondary) context.obtainStyledAttributes(attrs, R.styleable.PreferenceView).run { title = getString(R.styleable.PreferenceView_title) @@ -82,21 +80,17 @@ class PreferenceView @JvmOverloads constructor( // If there's a custom view used for the preference's widget, inflate it getResourceId(R.styleable.PreferenceView_widget, -1).takeIf { it != -1 }?.let { id -> - View.inflate(context, id, binding.widgetFrame) + View.inflate(context, id, widgetFrame) } // If an icon is being used, set up the icon view getResourceId(R.styleable.PreferenceView_icon, -1).takeIf { it != -1 }?.let { id -> - binding.icon.setVisible(true) - binding.icon.setImageResource(id) + icon.setVisible(true) + icon.setImageResource(id) } recycle() } } - fun widget(): T { - return binding.widgetFrame.getChildAt(0) as T - } - -} +} \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/common/widget/QkDialog.kt b/presentation/src/main/java/com/moez/QKSMS/common/widget/QkDialog.kt index f38687b06..f275c8a0c 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/widget/QkDialog.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/widget/QkDialog.kt @@ -19,15 +19,17 @@ package com.moez.QKSMS.common.widget import android.app.Activity +import android.view.LayoutInflater import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter -import com.moez.QKSMS.databinding.QkDialogBinding +import kotlinx.android.synthetic.main.qk_dialog.view.* class QkDialog(private val context: Activity) : AlertDialog(context) { - private val binding = QkDialogBinding.inflate(context.layoutInflater) + private val view = LayoutInflater.from(context).inflate(R.layout.qk_dialog, null) @StringRes var titleRes: Int? = null @@ -39,8 +41,8 @@ class QkDialog(private val context: Activity) : AlertDialog(context) { var title: String? = null set(value) { field = value - binding.title.text = value - binding.title.isVisible = !value.isNullOrBlank() + view.title.text = value + view.title.isVisible = !value.isNullOrBlank() } @StringRes @@ -53,15 +55,15 @@ class QkDialog(private val context: Activity) : AlertDialog(context) { var subtitle: String? = null set(value) { field = value - binding.subtitle.text = value - binding.subtitle.isVisible = !value.isNullOrBlank() + view.subtitle.text = value + view.subtitle.isVisible = !value.isNullOrBlank() } - var adapter: QkAdapter<*, *>? = null + var adapter: QkAdapter<*>? = null set(value) { field = value - binding.list.isVisible = value != null - binding.list.adapter = value + view.list.isVisible = value != null + view.list.adapter = value } var positiveButtonListener: (() -> Unit)? = null @@ -70,9 +72,9 @@ class QkDialog(private val context: Activity) : AlertDialog(context) { var positiveButton: Int? = null set(value) { field = value - value?.run(binding.positiveButton::setText) - binding.positiveButton.isVisible = value != null - binding.positiveButton.setOnClickListener { + value?.run(view.positiveButton::setText) + view.positiveButton.isVisible = value != null + view.positiveButton.setOnClickListener { positiveButtonListener?.invoke() ?: dismiss() } } @@ -83,9 +85,9 @@ class QkDialog(private val context: Activity) : AlertDialog(context) { var negativeButton: Int? = null set(value) { field = value - value?.run(binding.negativeButton::setText) - binding.negativeButton.isVisible = value != null - binding.negativeButton.setOnClickListener { + value?.run(view.negativeButton::setText) + view.negativeButton.isVisible = value != null + view.negativeButton.setOnClickListener { negativeButtonListener?.invoke() ?: dismiss() } } @@ -97,7 +99,7 @@ class QkDialog(private val context: Activity) : AlertDialog(context) { } init { - setView(binding.root) + setView(view) } } diff --git a/presentation/src/main/java/com/moez/QKSMS/common/widget/RadioPreferenceView.kt b/presentation/src/main/java/com/moez/QKSMS/common/widget/RadioPreferenceView.kt index abb7f3713..9f129c1af 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/widget/RadioPreferenceView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/widget/RadioPreferenceView.kt @@ -30,9 +30,8 @@ import com.moez.QKSMS.common.util.extensions.forwardTouches import com.moez.QKSMS.common.util.extensions.resolveThemeAttribute import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.RadioPreferenceViewBinding import com.moez.QKSMS.injection.appComponent +import kotlinx.android.synthetic.main.radio_preference_view.view.* import javax.inject.Inject class RadioPreferenceView @JvmOverloads constructor( @@ -48,7 +47,7 @@ class RadioPreferenceView @JvmOverloads constructor( if (isInEditMode) { findViewById(R.id.titleView).text = value } else { - binding.titleView.text = value + titleView.text = value } } @@ -63,18 +62,17 @@ class RadioPreferenceView @JvmOverloads constructor( setVisible(value?.isNotEmpty() == true) } } else { - binding.summaryView.text = value - binding.summaryView.setVisible(value?.isNotEmpty() == true) + summaryView.text = value + summaryView.setVisible(value?.isNotEmpty() == true) } } - val binding: RadioPreferenceViewBinding = viewBinding(RadioPreferenceViewBinding::inflate) - init { if (!isInEditMode) { appComponent.inject(this) } + View.inflate(context, R.layout.radio_preference_view, this) setBackgroundResource(context.resolveThemeAttribute(R.attr.selectableItemBackground)) val states = arrayOf( @@ -86,8 +84,8 @@ class RadioPreferenceView @JvmOverloads constructor( false -> colors.theme().theme } val textSecondary = context.resolveThemeColor(android.R.attr.textColorTertiary) - binding.radioButton.buttonTintList = ColorStateList(states, intArrayOf(themeColor, textSecondary)) - binding.radioButton.forwardTouches(this) + radioButton.buttonTintList = ColorStateList(states, intArrayOf(themeColor, textSecondary)) + radioButton.forwardTouches(this) context.obtainStyledAttributes(attrs, R.styleable.RadioPreferenceView)?.run { title = getString(R.styleable.RadioPreferenceView_title) @@ -95,11 +93,11 @@ class RadioPreferenceView @JvmOverloads constructor( // If there's a custom view used for the preference's widget, inflate it getResourceId(R.styleable.RadioPreferenceView_widget, -1).takeIf { it != -1 }?.let { id -> - View.inflate(context, id, binding.widgetFrame) + View.inflate(context, id, widgetFrame) } recycle() } } -} +} \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/common/widget/TextInputDialog.kt b/presentation/src/main/java/com/moez/QKSMS/common/widget/TextInputDialog.kt index 0c9ee56d8..1f639a018 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/widget/TextInputDialog.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/widget/TextInputDialog.kt @@ -20,27 +20,28 @@ package com.moez.QKSMS.common.widget import android.app.Activity import android.content.DialogInterface +import android.view.LayoutInflater import androidx.appcompat.app.AlertDialog import com.moez.QKSMS.R -import com.moez.QKSMS.databinding.TextInputDialogBinding +import kotlinx.android.synthetic.main.text_input_dialog.view.* class TextInputDialog(context: Activity, hint: String, listener: (String) -> Unit) : AlertDialog(context) { - private val binding = TextInputDialogBinding.inflate(context.layoutInflater) + private val layout = LayoutInflater.from(context).inflate(R.layout.text_input_dialog, null) init { - binding.field.hint = hint + layout.field.hint = hint - setView(binding.root) + setView(layout) setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(R.string.button_cancel)) { _, _ -> } setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.button_delete)) { _, _ -> listener("") } setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.button_save)) { _, _ -> - listener(binding.field.text.toString()) + listener(layout.field.text.toString()) } } fun setText(text: String): TextInputDialog { - binding.field.setText(text) + layout.field.setText(text) return this } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupActivity.kt index 327fe4f13..65c52b3ce 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupActivity.kt @@ -22,22 +22,22 @@ import android.os.Bundle import com.bluelinelabs.conductor.Conductor import com.bluelinelabs.conductor.Router import com.bluelinelabs.conductor.RouterTransaction +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkThemedActivity -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.ContainerActivityBinding import dagger.android.AndroidInjection +import kotlinx.android.synthetic.main.container_activity.* + class BackupActivity : QkThemedActivity() { - private val binding by viewBinding(ContainerActivityBinding::inflate) private lateinit var router: Router override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.container_activity) - router = Conductor.attachRouter(this, binding.container, savedInstanceState) + router = Conductor.attachRouter(this, container, savedInstanceState) if (!router.hasRootController()) { router.setRoot(RouterTransaction.with(BackupController())) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupAdapter.kt index 57350e22c..038295dc6 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupAdapter.kt @@ -20,37 +20,42 @@ package com.moez.QKSMS.feature.backup import android.content.Context import android.text.format.Formatter +import android.view.LayoutInflater import android.view.ViewGroup import com.moez.QKSMS.R import com.moez.QKSMS.common.base.FlowableAdapter import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.DateFormatter -import com.moez.QKSMS.databinding.BackupListItemBinding import com.moez.QKSMS.model.BackupFile import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.backup_list_item.* import javax.inject.Inject class BackupAdapter @Inject constructor( private val context: Context, private val dateFormatter: DateFormatter -) : FlowableAdapter() { +) : FlowableAdapter() { val backupSelected: Subject = PublishSubject.create() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, BackupListItemBinding::inflate).apply { - binding.root.setOnClickListener { backupSelected.onNext(getItem(adapterPosition)) } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + val view = layoutInflater.inflate(R.layout.backup_list_item, parent, false) + + return QkViewHolder(view).apply { + view.setOnClickListener { backupSelected.onNext(getItem(adapterPosition)) } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val backup = getItem(position) + val count = backup.messages - holder.binding.title.text = dateFormatter.getDetailedTimestamp(backup.date) - holder.binding.messages.text = context.resources.getQuantityString(R.plurals.backup_message_count, count, count) - holder.binding.size.text = Formatter.formatFileSize(context, backup.size) + holder.title.text = dateFormatter.getDetailedTimestamp(backup.date) + holder.messages.text = context.resources.getQuantityString(R.plurals.backup_message_count, count, count) + holder.size.text = Formatter.formatFileSize(context, backup.size) } } \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt index dc0e691c8..1439f5f47 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt @@ -22,7 +22,6 @@ import android.Manifest import android.app.Activity import android.content.res.ColorStateList import android.graphics.Typeface -import android.view.LayoutInflater import android.view.View import androidx.appcompat.app.AlertDialog import androidx.core.app.ActivityCompat @@ -37,19 +36,18 @@ import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setPositiveButton import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.widget.PreferenceView -import com.moez.QKSMS.databinding.BackupControllerBinding -import com.moez.QKSMS.databinding.BackupListDialogBinding import com.moez.QKSMS.injection.appComponent import com.moez.QKSMS.model.BackupFile import com.moez.QKSMS.repository.BackupRepository import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.backup_controller.* +import kotlinx.android.synthetic.main.backup_list_dialog.view.* +import kotlinx.android.synthetic.main.preference_view.view.* import javax.inject.Inject -class BackupController : QkController( - BackupControllerBinding::inflate -), BackupView { +class BackupController : QkController(), BackupView { @Inject lateinit var adapter: BackupAdapter @Inject lateinit var dateFormatter: DateFormatter @@ -60,11 +58,11 @@ class BackupController : QkController = PublishSubject.create() private val backupFilesDialog by lazy { - val binding = BackupListDialogBinding.inflate(LayoutInflater.from(activity)) + val view = View.inflate(activity, R.layout.backup_list_dialog, null) .apply { files.adapter = adapter.apply { emptyView = empty } } AlertDialog.Builder(activity!!) - .setView(binding.root) + .setView(view) .setCancelable(true) .create() } @@ -89,6 +87,7 @@ class BackupController : QkController - binding.progressBar.indeterminateTintList = ColorStateList.valueOf(theme.theme) - binding.progressBar.progressTintList = ColorStateList.valueOf(theme.theme) - binding.fab.setBackgroundTint(theme.theme) - binding.fabIcon.setTint(theme.textPrimary) - binding.fabLabel.setTextColor(theme.textPrimary) + progressBar.indeterminateTintList = ColorStateList.valueOf(theme.theme) + progressBar.progressTintList = ColorStateList.valueOf(theme.theme) + fab.setBackgroundTint(theme.theme) + fabIcon.setTint(theme.textPrimary) + fabLabel.setTextColor(theme.textPrimary) } // Make the list titles bold - binding.linearLayout.children - .mapNotNull { view -> view as? PreferenceView } - .map { preferenceView -> preferenceView.binding.titleView } + linearLayout.children + .mapNotNull { it as? PreferenceView } + .map { it.titleView } .forEach { it.setTypeface(it.typeface, Typeface.BOLD) } } @@ -124,51 +123,51 @@ class BackupController : QkController { - binding.progressIcon.setImageResource(R.drawable.ic_file_upload_black_24dp) - binding.progressTitle.setText(R.string.backup_backing_up) - binding.progressSummary.text = state.backupProgress.getLabel(activity!!) - binding.progressSummary.isVisible = binding.progressSummary.text.isNotEmpty() - binding.progressCancel.isVisible = false + progressIcon.setImageResource(R.drawable.ic_file_upload_black_24dp) + progressTitle.setText(R.string.backup_backing_up) + progressSummary.text = state.backupProgress.getLabel(activity!!) + progressSummary.isVisible = progressSummary.text.isNotEmpty() + progressCancel.isVisible = false val running = (state.backupProgress as? BackupRepository.Progress.Running) - binding.progressBar.isVisible = state.backupProgress.indeterminate || running?.max ?: 0 > 0 - binding.progressBar.isIndeterminate = state.backupProgress.indeterminate - binding.progressBar.max = running?.max ?: 0 - binding.progressBar.progress = running?.count ?: 0 - binding.progress.isVisible = true - binding.fab.isVisible = false + progressBar.isVisible = state.backupProgress.indeterminate || running?.max ?: 0 > 0 + progressBar.isIndeterminate = state.backupProgress.indeterminate + progressBar.max = running?.max ?: 0 + progressBar.progress = running?.count ?: 0 + progress.isVisible = true + fab.isVisible = false } state.restoreProgress.running -> { - binding.progressIcon.setImageResource(R.drawable.ic_file_download_black_24dp) - binding.progressTitle.setText(R.string.backup_restoring) - binding.progressSummary.text = state.restoreProgress.getLabel(activity!!) - binding.progressSummary.isVisible = binding.progressSummary.text.isNotEmpty() - binding.progressCancel.isVisible = true + progressIcon.setImageResource(R.drawable.ic_file_download_black_24dp) + progressTitle.setText(R.string.backup_restoring) + progressSummary.text = state.restoreProgress.getLabel(activity!!) + progressSummary.isVisible = progressSummary.text.isNotEmpty() + progressCancel.isVisible = true val running = (state.restoreProgress as? BackupRepository.Progress.Running) - binding.progressBar.isVisible = state.restoreProgress.indeterminate || running?.max ?: 0 > 0 - binding.progressBar.isIndeterminate = state.restoreProgress.indeterminate - binding.progressBar.max = running?.max ?: 0 - binding.progressBar.progress = running?.count ?: 0 - binding.progress.isVisible = true - binding.fab.isVisible = false + progressBar.isVisible = state.restoreProgress.indeterminate || running?.max ?: 0 > 0 + progressBar.isIndeterminate = state.restoreProgress.indeterminate + progressBar.max = running?.max ?: 0 + progressBar.progress = running?.count ?: 0 + progress.isVisible = true + fab.isVisible = false } else -> { - binding.progress.isVisible = false - binding.fab.isVisible = true + progress.isVisible = false + fab.isVisible = true } } - binding.backup.summary = state.lastBackup + backup.summary = state.lastBackup adapter.data = state.backups - binding.fabIcon.setImageResource(when (state.upgraded) { + fabIcon.setImageResource(when (state.upgraded) { true -> R.drawable.ic_file_upload_black_24dp false -> R.drawable.ic_star_black_24dp }) - binding.fabLabel.setText(when (state.upgraded) { + fabLabel.setText(when (state.upgraded) { true -> R.string.backup_now false -> R.string.title_qksms_plus }) @@ -176,18 +175,18 @@ class BackupController : QkController = activityVisibleSubject - override fun restoreClicks(): Observable<*> = binding.restore.clicks() + override fun restoreClicks(): Observable<*> = restore.clicks() override fun restoreFileSelected(): Observable = adapter.backupSelected .doOnNext { backupFilesDialog.dismiss() } override fun restoreConfirmed(): Observable<*> = confirmRestoreSubject - override fun stopRestoreClicks(): Observable<*> = binding.progressCancel.clicks() + override fun stopRestoreClicks(): Observable<*> = progressCancel.clicks() override fun stopRestoreConfirmed(): Observable<*> = stopRestoreSubject - override fun fabClicks(): Observable<*> = binding.fab.clicks() + override fun fabClicks(): Observable<*> = fab.clicks() override fun requestStoragePermission() { ActivityCompat.requestPermissions(activity!!, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 0) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingActivity.kt index 9b5d59a54..e028400fb 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingActivity.kt @@ -22,22 +22,21 @@ import android.os.Bundle import com.bluelinelabs.conductor.Conductor import com.bluelinelabs.conductor.Router import com.bluelinelabs.conductor.RouterTransaction +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkThemedActivity -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.ContainerActivityBinding import dagger.android.AndroidInjection +import kotlinx.android.synthetic.main.container_activity.* class BlockingActivity : QkThemedActivity() { - private val binding by viewBinding(ContainerActivityBinding::inflate) private lateinit var router: Router override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.container_activity) - router = Conductor.attachRouter(this, binding.container, savedInstanceState) + router = Conductor.attachRouter(this, container, savedInstanceState) if (!router.hasRootController()) { router.setRoot(RouterTransaction.with(BlockingController())) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingController.kt index c73e15670..1289b9c49 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingController.kt @@ -26,22 +26,20 @@ import com.moez.QKSMS.common.QkChangeHandler import com.moez.QKSMS.common.base.QkController import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.animateLayoutChanges -import com.moez.QKSMS.common.widget.QkSwitch -import com.moez.QKSMS.databinding.BlockingControllerBinding import com.moez.QKSMS.feature.blocking.manager.BlockingManagerController import com.moez.QKSMS.feature.blocking.messages.BlockedMessagesController import com.moez.QKSMS.feature.blocking.numbers.BlockedNumbersController import com.moez.QKSMS.injection.appComponent +import kotlinx.android.synthetic.main.blocking_controller.* +import kotlinx.android.synthetic.main.settings_switch_widget.view.* import javax.inject.Inject -class BlockingController : QkController( - BlockingControllerBinding::inflate -), BlockingView { +class BlockingController : QkController(), BlockingView { - override val blockingManagerIntent by lazy { binding.blockingManager.clicks() } - override val blockedNumbersIntent by lazy { binding.blockedNumbers.clicks() } - override val blockedMessagesIntent by lazy { binding.blockedMessages.clicks() } - override val dropClickedIntent by lazy { binding.drop.clicks() } + override val blockingManagerIntent by lazy { blockingManager.clicks() } + override val blockedNumbersIntent by lazy { blockedNumbers.clicks() } + override val blockedMessagesIntent by lazy { blockedMessages.clicks() } + override val dropClickedIntent by lazy { drop.clicks() } @Inject lateinit var colors: Colors @Inject override lateinit var presenter: BlockingPresenter @@ -49,11 +47,12 @@ class BlockingController : QkController().isChecked = state.dropEnabled - binding.blockedMessages.isEnabled = !state.dropEnabled + blockingManager.summary = state.blockingManager + drop.checkbox.isChecked = state.dropEnabled + blockedMessages.isEnabled = !state.dropEnabled } override fun openBlockedNumbers() { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerController.kt index 400ac7202..ed64b1d5c 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerController.kt @@ -7,16 +7,18 @@ import androidx.core.view.isVisible import com.jakewharton.rxbinding2.view.clicks import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkController -import com.moez.QKSMS.databinding.BlockingManagerControllerBinding import com.moez.QKSMS.injection.appComponent import com.moez.QKSMS.util.Preferences import io.reactivex.Observable import io.reactivex.Single import io.reactivex.subjects.PublishSubject +import kotlinx.android.synthetic.main.blocking_manager_controller.* +import kotlinx.android.synthetic.main.blocking_manager_list_option.view.* +import kotlinx.android.synthetic.main.radio_preference_view.view.* import javax.inject.Inject -class BlockingManagerController : QkController(BlockingManagerControllerBinding::inflate), BlockingManagerView { +class BlockingManagerController : QkController(), + BlockingManagerView { @Inject override lateinit var presenter: BlockingManagerPresenter @@ -25,6 +27,7 @@ class BlockingManagerController : QkController = activityResumedSubject - override fun qksmsClicked(): Observable<*> = binding.qksms.clicks() - override fun callControlClicked(): Observable<*> = binding.callControl.clicks() - override fun siaClicked(): Observable<*> = binding.shouldIAnswer.clicks() + override fun qksmsClicked(): Observable<*> = qksms.clicks() + override fun callControlClicked(): Observable<*> = callControl.clicks() + override fun siaClicked(): Observable<*> = shouldIAnswer.clicks() override fun showCopyDialog(manager: String): Single = Single.create { emitter -> AlertDialog.Builder(activity) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/messages/BlockedMessagesAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/messages/BlockedMessagesAdapter.kt index 7a48e2aa2..9a4c37e38 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/messages/BlockedMessagesAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/messages/BlockedMessagesAdapter.kt @@ -20,6 +20,7 @@ package com.moez.QKSMS.feature.blocking.messages import android.content.Context import android.graphics.Typeface +import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.view.isVisible import com.moez.QKSMS.R @@ -27,63 +28,65 @@ import com.moez.QKSMS.common.base.QkRealmAdapter import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.DateFormatter import com.moez.QKSMS.common.util.extensions.resolveThemeColor -import com.moez.QKSMS.databinding.BlockedListItemBinding import com.moez.QKSMS.model.Conversation import com.moez.QKSMS.util.Preferences import io.reactivex.subjects.PublishSubject +import kotlinx.android.synthetic.main.blocked_list_item.* +import kotlinx.android.synthetic.main.blocked_list_item.view.* import javax.inject.Inject class BlockedMessagesAdapter @Inject constructor( private val context: Context, private val dateFormatter: DateFormatter -) : QkRealmAdapter() { +) : QkRealmAdapter() { val clicks: PublishSubject = PublishSubject.create() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, BlockedListItemBinding::inflate).apply { - if (viewType == 0) { - binding.title.setTypeface(binding.title.typeface, Typeface.BOLD) - binding.date.setTypeface(binding.date.typeface, Typeface.BOLD) - binding.date.setTextColor(parent.context.resolveThemeColor(android.R.attr.textColorPrimary)) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.blocked_list_item, parent, false) + + if (viewType == 0) { + view.title.setTypeface(view.title.typeface, Typeface.BOLD) + view.date.setTypeface(view.date.typeface, Typeface.BOLD) + view.date.setTextColor(view.context.resolveThemeColor(android.R.attr.textColorPrimary)) + } - binding.root.setOnClickListener { + return QkViewHolder(view).apply { + view.setOnClickListener { val conversation = getItem(adapterPosition) ?: return@setOnClickListener when (toggleSelection(conversation.id, false)) { - true -> binding.root.isActivated = isSelected(conversation.id) + true -> view.isActivated = isSelected(conversation.id) false -> clicks.onNext(conversation.id) } } - - binding.root.setOnLongClickListener { + view.setOnLongClickListener { val conversation = getItem(adapterPosition) ?: return@setOnLongClickListener true toggleSelection(conversation.id) - binding.root.isActivated = isSelected(conversation.id) + view.isActivated = isSelected(conversation.id) true } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val conversation = getItem(position) ?: return - holder.binding.root.isActivated = isSelected(conversation.id) + holder.containerView.isActivated = isSelected(conversation.id) - holder.binding.avatars.recipients = conversation.recipients - holder.binding.title.collapseEnabled = conversation.recipients.size > 1 - holder.binding.title.text = conversation.getTitle() - holder.binding.date.text = dateFormatter.getConversationTimestamp(conversation.date) + holder.avatars.recipients = conversation.recipients + holder.title.collapseEnabled = conversation.recipients.size > 1 + holder.title.text = conversation.getTitle() + holder.date.text = dateFormatter.getConversationTimestamp(conversation.date) - holder.binding.blocker.text = when (conversation.blockingClient) { + holder.blocker.text = when (conversation.blockingClient) { Preferences.BLOCKING_MANAGER_CC -> context.getString(R.string.blocking_manager_call_control_title) Preferences.BLOCKING_MANAGER_SIA -> context.getString(R.string.blocking_manager_sia_title) else -> null } - holder.binding.reason.text = conversation.blockReason - holder.binding.blocker.isVisible = holder.binding.blocker.text.isNotEmpty() - holder.binding.reason.isVisible = holder.binding.blocker.text.isNotEmpty() + holder.reason.text = conversation.blockReason + holder.blocker.isVisible = holder.blocker.text.isNotEmpty() + holder.reason.isVisible = holder.blocker.text.isNotEmpty() } override fun getItemViewType(position: Int): Int { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/messages/BlockedMessagesController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/messages/BlockedMessagesController.kt index eae709285..92dfcac39 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/messages/BlockedMessagesController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/messages/BlockedMessagesController.kt @@ -27,15 +27,16 @@ import android.view.View import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkController import com.moez.QKSMS.common.util.Colors -import com.moez.QKSMS.databinding.BlockedMessagesControllerBinding import com.moez.QKSMS.feature.blocking.BlockingDialog import com.moez.QKSMS.injection.appComponent import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.blocked_messages_controller.* +import kotlinx.android.synthetic.main.container_activity.* import javax.inject.Inject -class BlockedMessagesController : QkController(BlockedMessagesControllerBinding::inflate), BlockedMessagesView { +class BlockedMessagesController : QkController(), + BlockedMessagesView { override val menuReadyIntent: Subject = PublishSubject.create() override val optionsItemIntent: Subject = PublishSubject.create() @@ -53,12 +54,13 @@ class BlockedMessagesController : QkController() { +class BlockedNumbersAdapter : QkRealmAdapter() { val unblockAddress: Subject = PublishSubject.create() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, BlockedNumberListItemBinding::inflate).apply { - binding.unblock.setOnClickListener { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.blocked_number_list_item, parent, false) + return QkViewHolder(view).apply { + containerView.unblock.setOnClickListener { val number = getItem(adapterPosition) ?: return@setOnClickListener unblockAddress.onNext(number.id) } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val item = getItem(position)!! - holder.binding.number.text = item.address + holder.number.text = item.address } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/numbers/BlockedNumbersController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/numbers/BlockedNumbersController.kt index 3e167351d..8b0927eca 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/numbers/BlockedNumbersController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/numbers/BlockedNumbersController.kt @@ -18,6 +18,7 @@ */ package com.moez.QKSMS.feature.blocking.numbers +import android.view.LayoutInflater import android.view.View import androidx.appcompat.app.AlertDialog import com.jakewharton.rxbinding2.view.clicks @@ -26,17 +27,17 @@ import com.moez.QKSMS.common.base.QkController import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.databinding.BlockedNumbersAddDialogBinding -import com.moez.QKSMS.databinding.BlockedNumbersControllerBinding import com.moez.QKSMS.injection.appComponent import com.moez.QKSMS.util.PhoneNumberUtils import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.blocked_numbers_add_dialog.view.* +import kotlinx.android.synthetic.main.blocked_numbers_controller.* import javax.inject.Inject -class BlockedNumbersController : QkController(BlockedNumbersControllerBinding::inflate), BlockedNumbersView { +class BlockedNumbersController : QkController(), + BlockedNumbersView { @Inject override lateinit var presenter: BlockedNumbersPresenter @Inject lateinit var colors: Colors @@ -48,6 +49,7 @@ class BlockedNumbersController : QkController = adapter.unblockAddress - override fun addAddress(): Observable<*> = binding.add.clicks() + override fun addAddress(): Observable<*> = add.clicks() override fun saveAddress(): Observable = saveAddressSubject override fun showAddDialog() { - val binding = BlockedNumbersAddDialogBinding.inflate(activity?.layoutInflater!!) - val textWatcher = BlockedNumberTextWatcher(binding.input, phoneNumberUtils) + val layout = LayoutInflater.from(activity).inflate(R.layout.blocked_numbers_add_dialog, null) + val textWatcher = BlockedNumberTextWatcher(layout.input, phoneNumberUtils) val dialog = AlertDialog.Builder(activity!!) - .setView(binding.root) + .setView(layout) .setPositiveButton(R.string.blocked_numbers_dialog_block) { _, _ -> - saveAddressSubject.onNext(binding.input.text.toString()) + saveAddressSubject.onNext(layout.input.text.toString()) } .setNegativeButton(R.string.button_cancel) { _, _ -> } .setOnDismissListener { textWatcher.dispose() } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogAdapter.kt index 98e954d74..43de03391 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogAdapter.kt @@ -20,16 +20,15 @@ package com.moez.QKSMS.feature.changelog import android.content.Context import android.graphics.Typeface +import android.view.LayoutInflater import android.view.ViewGroup import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter import com.moez.QKSMS.common.base.QkViewHolder -import com.moez.QKSMS.databinding.ChangelogListItemBinding import com.moez.QKSMS.manager.ChangelogManager +import kotlinx.android.synthetic.main.changelog_list_item.* -class ChangelogAdapter( - private val context: Context -) : QkAdapter() { +class ChangelogAdapter(private val context: Context) : QkAdapter() { data class ChangelogItem(val type: Int, val label: String) @@ -53,18 +52,19 @@ class ChangelogAdapter( data = changes } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, ChangelogListItemBinding::inflate).apply { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.changelog_list_item, parent, false) + return QkViewHolder(view).apply { if (viewType == 0) { - binding.changelogItem.setTypeface(binding.changelogItem.typeface, Typeface.BOLD) + changelogItem.setTypeface(changelogItem.typeface, Typeface.BOLD) } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val item = getItem(position) - holder.binding.changelogItem.text = item.label + holder.changelogItem.text = item.label } override fun getItemViewType(position: Int): Int { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogDialog.kt b/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogDialog.kt index 7cf1c2a0b..04dc1d4ce 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogDialog.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogDialog.kt @@ -18,14 +18,15 @@ */ package com.moez.QKSMS.feature.changelog +import android.view.LayoutInflater import androidx.appcompat.app.AlertDialog import com.moez.QKSMS.BuildConfig import com.moez.QKSMS.R -import com.moez.QKSMS.databinding.ChangelogDialogBinding import com.moez.QKSMS.feature.main.MainActivity import com.moez.QKSMS.manager.ChangelogManager import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.changelog_dialog.view.* class ChangelogDialog(activity: MainActivity) { @@ -35,17 +36,17 @@ class ChangelogDialog(activity: MainActivity) { private val adapter = ChangelogAdapter(activity) init { - val binding = ChangelogDialogBinding.inflate(activity.layoutInflater) + val layout = LayoutInflater.from(activity).inflate(R.layout.changelog_dialog, null) dialog = AlertDialog.Builder(activity) .setCancelable(true) - .setView(binding.root) + .setView(layout) .create() - binding.version.text = activity.getString(R.string.changelog_version, BuildConfig.VERSION_NAME) - binding.changelog.adapter = adapter - binding.more.setOnClickListener { dialog.dismiss(); moreClicks.onNext(Unit) } - binding.dismiss.setOnClickListener { dialog.dismiss() } + layout.version.text = activity.getString(R.string.changelog_version, BuildConfig.VERSION_NAME) + layout.changelog.adapter = adapter + layout.more.setOnClickListener { dialog.dismiss(); moreClicks.onNext(Unit) } + layout.dismiss.setOnClickListener { dialog.dismiss() } } fun show(changelog: ChangelogManager.Changelog) { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/AttachmentAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/AttachmentAdapter.kt index 7ef4c887e..3563798bc 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/AttachmentAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/AttachmentAdapter.kt @@ -19,13 +19,12 @@ package com.moez.QKSMS.feature.compose import android.content.Context +import android.view.LayoutInflater import android.view.ViewGroup -import androidx.viewbinding.ViewBinding import com.bumptech.glide.Glide +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter import com.moez.QKSMS.common.base.QkViewHolder -import com.moez.QKSMS.databinding.AttachmentContactListItemBinding -import com.moez.QKSMS.databinding.AttachmentImageListItemBinding import com.moez.QKSMS.extensions.mapNotNull import com.moez.QKSMS.model.Attachment import ezvcard.Ezvcard @@ -34,11 +33,14 @@ import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.attachment_contact_list_item.* +import kotlinx.android.synthetic.main.attachment_image_list_item.* +import kotlinx.android.synthetic.main.attachment_image_list_item.view.* import javax.inject.Inject class AttachmentAdapter @Inject constructor( private val context: Context -) : QkAdapter() { +) : QkAdapter() { companion object { private const val VIEW_TYPE_IMAGE = 0 @@ -47,42 +49,38 @@ class AttachmentAdapter @Inject constructor( val attachmentDeleted: Subject = PublishSubject.create() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - val holder: QkViewHolder = when (viewType) { - VIEW_TYPE_IMAGE -> QkViewHolder(parent, AttachmentImageListItemBinding::inflate) - VIEW_TYPE_CONTACT -> QkViewHolder(parent, AttachmentContactListItemBinding::inflate) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val inflater = LayoutInflater.from(parent.context) + val view = when (viewType) { + VIEW_TYPE_IMAGE -> inflater.inflate(R.layout.attachment_image_list_item, parent, false) + .apply { thumbnailBounds.clipToOutline = true } + + VIEW_TYPE_CONTACT -> inflater.inflate(R.layout.attachment_contact_list_item, parent, false) + else -> null!! // Impossible } - return holder.apply { - if (binding is AttachmentImageListItemBinding) { - binding.thumbnailBounds.clipToOutline = true - } - - binding.root.setOnClickListener { + return QkViewHolder(view).apply { + view.setOnClickListener { val attachment = getItem(adapterPosition) attachmentDeleted.onNext(attachment) } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val attachment = getItem(position) - when { - attachment is Attachment.Image && holder.binding is AttachmentImageListItemBinding -> { - Glide.with(context) - .load(attachment.getUri()) - .into(holder.binding.thumbnail) - } + when (attachment) { + is Attachment.Image -> Glide.with(context) + .load(attachment.getUri()) + .into(holder.thumbnail) - attachment is Attachment.Contact && holder.binding is AttachmentContactListItemBinding -> { - Observable.just(attachment.vCard) - .mapNotNull { vCard -> Ezvcard.parse(vCard).first() } - .subscribeOn(Schedulers.computation()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe { vcard -> holder.binding.name.text = vcard.formattedName.value } - } + is Attachment.Contact -> Observable.just(attachment.vCard) + .mapNotNull { vCard -> Ezvcard.parse(vCard).first() } + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { vcard -> holder.name?.text = vcard.formattedName.value } } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt index 8cad8642f..3b42535b6 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt @@ -55,8 +55,6 @@ import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.util.extensions.setVisible import com.moez.QKSMS.common.util.extensions.showKeyboard -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.ComposeActivityBinding import com.moez.QKSMS.feature.compose.editing.ChipsAdapter import com.moez.QKSMS.feature.contacts.ContactsActivity import com.moez.QKSMS.model.Attachment @@ -67,6 +65,7 @@ import dagger.android.AndroidInjection import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.compose_activity.* import java.text.SimpleDateFormat import java.util.* import javax.inject.Inject @@ -95,29 +94,28 @@ class ComposeActivity : QkThemedActivity(), ComposeView { override val chipDeletedIntent: Subject by lazy { chipsAdapter.chipDeleted } override val menuReadyIntent: Observable = menu.map { Unit } override val optionsItemIntent: Subject = PublishSubject.create() - override val sendAsGroupIntent by lazy { binding.sendAsGroupBackground.clicks() } + override val sendAsGroupIntent by lazy { sendAsGroupBackground.clicks() } override val messageClickIntent: Subject by lazy { messageAdapter.clicks } override val messagePartClickIntent: Subject by lazy { messageAdapter.partClicks } override val messagesSelectedIntent by lazy { messageAdapter.selectionChanges } override val cancelSendingIntent: Subject by lazy { messageAdapter.cancelSending } override val attachmentDeletedIntent: Subject by lazy { attachmentAdapter.attachmentDeleted } - override val textChangedIntent by lazy { binding.message.textChanges() } - override val attachIntent by lazy { Observable.merge(binding.attach.clicks(), binding.attachingBackground.clicks()) } - override val cameraIntent by lazy { Observable.merge(binding.camera.clicks(), binding.cameraLabel.clicks()) } - override val galleryIntent by lazy { Observable.merge(binding.gallery.clicks(), binding.galleryLabel.clicks()) } - override val scheduleIntent by lazy { Observable.merge(binding.schedule.clicks(), binding.scheduleLabel.clicks()) } - override val attachContactIntent by lazy { Observable.merge(binding.contact.clicks(), binding.contactLabel.clicks()) } + override val textChangedIntent by lazy { message.textChanges() } + override val attachIntent by lazy { Observable.merge(attach.clicks(), attachingBackground.clicks()) } + override val cameraIntent by lazy { Observable.merge(camera.clicks(), cameraLabel.clicks()) } + override val galleryIntent by lazy { Observable.merge(gallery.clicks(), galleryLabel.clicks()) } + override val scheduleIntent by lazy { Observable.merge(schedule.clicks(), scheduleLabel.clicks()) } + override val attachContactIntent by lazy { Observable.merge(contact.clicks(), contactLabel.clicks()) } override val attachmentSelectedIntent: Subject = PublishSubject.create() override val contactSelectedIntent: Subject = PublishSubject.create() - override val inputContentIntent by lazy { binding.message.inputContentSelected } + override val inputContentIntent by lazy { message.inputContentSelected } override val scheduleSelectedIntent: Subject = PublishSubject.create() - override val changeSimIntent by lazy { binding.sim.clicks() } - override val scheduleCancelIntent by lazy { binding.scheduledCancel.clicks() } - override val sendIntent by lazy { binding.send.clicks() } + override val changeSimIntent by lazy { sim.clicks() } + override val scheduleCancelIntent by lazy { scheduledCancel.clicks() } + override val sendIntent by lazy { send.clicks() } override val viewQksmsPlusIntent: Subject = PublishSubject.create() override val backPressedIntent: Subject = PublishSubject.create() - private val binding by viewBinding(ComposeActivityBinding::inflate) private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[ComposeViewModel::class.java] } private var cameraDestination: Uri? = null @@ -125,33 +123,33 @@ class ComposeActivity : QkThemedActivity(), ComposeView { override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.compose_activity) showBackButton(true) viewModel.bindView(this) - binding.contentView.layoutTransition = LayoutTransition().apply { + contentView.layoutTransition = LayoutTransition().apply { disableTransitionType(LayoutTransition.CHANGING) } - chipsAdapter.view = binding.chips + chipsAdapter.view = chips - binding.chips.itemAnimator = null - binding.chips.layoutManager = FlexboxLayoutManager(this) + chips.itemAnimator = null + chips.layoutManager = FlexboxLayoutManager(this) - messageAdapter.autoScrollToStart(binding.messageList) - messageAdapter.emptyView = binding.messagesEmpty + messageAdapter.autoScrollToStart(messageList) + messageAdapter.emptyView = messagesEmpty - binding.messageList.setHasFixedSize(true) - binding.messageList.adapter = messageAdapter + messageList.setHasFixedSize(true) + messageList.adapter = messageAdapter - binding.attachments.adapter = attachmentAdapter + attachments.adapter = attachmentAdapter - binding.message.supportsInputContent = true + message.supportsInputContent = true theme - .doOnNext { binding.loading.setTint(it.theme) } - .doOnNext { binding.attach.setBackgroundTint(it.theme) } - .doOnNext { binding.attach.setTint(it.textPrimary) } + .doOnNext { loading.setTint(it.theme) } + .doOnNext { attach.setBackgroundTint(it.theme) } + .doOnNext { attach.setTint(it.textPrimary) } .doOnNext { messageAdapter.theme = it } .autoDisposable(scope()) .subscribe() @@ -160,7 +158,7 @@ class ComposeActivity : QkThemedActivity(), ComposeView { // These theme attributes don't apply themselves on API 21 if (Build.VERSION.SDK_INT <= 22) { - binding.messageBackground.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) + messageBackground.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) } } @@ -188,59 +186,59 @@ class ComposeActivity : QkThemedActivity(), ComposeView { else -> state.conversationtitle } - binding.toolbarSubtitle.setVisible(state.query.isNotEmpty()) - binding.toolbarSubtitle.text = getString(R.string.compose_subtitle_results, state.searchSelectionPosition, + toolbarSubtitle.setVisible(state.query.isNotEmpty()) + toolbarSubtitle.text = getString(R.string.compose_subtitle_results, state.searchSelectionPosition, state.searchResults) - binding.toolbarTitle.setVisible(!state.editingMode) - binding.chips.setVisible(state.editingMode) - binding.composeBar.setVisible(!state.loading) + toolbarTitle.setVisible(!state.editingMode) + chips.setVisible(state.editingMode) + composeBar.setVisible(!state.loading) // Don't set the adapters unless needed - if (state.editingMode && binding.chips.adapter == null) binding.chips.adapter = chipsAdapter + if (state.editingMode && chips.adapter == null) chips.adapter = chipsAdapter - binding.toolbar.menu.findItem(R.id.add)?.isVisible = state.editingMode - binding.toolbar.menu.findItem(R.id.call)?.isVisible = !state.editingMode && state.selectedMessages == 0 + toolbar.menu.findItem(R.id.add)?.isVisible = state.editingMode + toolbar.menu.findItem(R.id.call)?.isVisible = !state.editingMode && state.selectedMessages == 0 && state.query.isEmpty() - binding.toolbar.menu.findItem(R.id.info)?.isVisible = !state.editingMode && state.selectedMessages == 0 + toolbar.menu.findItem(R.id.info)?.isVisible = !state.editingMode && state.selectedMessages == 0 && state.query.isEmpty() - binding.toolbar.menu.findItem(R.id.copy)?.isVisible = !state.editingMode && state.selectedMessages > 0 - binding.toolbar.menu.findItem(R.id.details)?.isVisible = !state.editingMode && state.selectedMessages == 1 - binding.toolbar.menu.findItem(R.id.delete)?.isVisible = !state.editingMode && state.selectedMessages > 0 - binding.toolbar.menu.findItem(R.id.forward)?.isVisible = !state.editingMode && state.selectedMessages == 1 - binding.toolbar.menu.findItem(R.id.previous)?.isVisible = state.selectedMessages == 0 && state.query.isNotEmpty() - binding.toolbar.menu.findItem(R.id.next)?.isVisible = state.selectedMessages == 0 && state.query.isNotEmpty() - binding.toolbar.menu.findItem(R.id.clear)?.isVisible = state.selectedMessages == 0 && state.query.isNotEmpty() + toolbar.menu.findItem(R.id.copy)?.isVisible = !state.editingMode && state.selectedMessages > 0 + toolbar.menu.findItem(R.id.details)?.isVisible = !state.editingMode && state.selectedMessages == 1 + toolbar.menu.findItem(R.id.delete)?.isVisible = !state.editingMode && state.selectedMessages > 0 + toolbar.menu.findItem(R.id.forward)?.isVisible = !state.editingMode && state.selectedMessages == 1 + toolbar.menu.findItem(R.id.previous)?.isVisible = state.selectedMessages == 0 && state.query.isNotEmpty() + toolbar.menu.findItem(R.id.next)?.isVisible = state.selectedMessages == 0 && state.query.isNotEmpty() + toolbar.menu.findItem(R.id.clear)?.isVisible = state.selectedMessages == 0 && state.query.isNotEmpty() chipsAdapter.data = state.selectedChips - binding.loading.setVisible(state.loading) + loading.setVisible(state.loading) - binding.sendAsGroup.setVisible(state.editingMode && state.selectedChips.size >= 2) - binding.sendAsGroupSwitch.isChecked = state.sendAsGroup + sendAsGroup.setVisible(state.editingMode && state.selectedChips.size >= 2) + sendAsGroupSwitch.isChecked = state.sendAsGroup - binding.messageList.setVisible(!state.editingMode || state.sendAsGroup || state.selectedChips.size == 1) + messageList.setVisible(!state.editingMode || state.sendAsGroup || state.selectedChips.size == 1) messageAdapter.data = state.messages messageAdapter.highlight = state.searchSelectionId - binding.scheduledGroup.isVisible = state.scheduled != 0L - binding.scheduledTime.text = dateFormatter.getScheduledTimestamp(state.scheduled) + scheduledGroup.isVisible = state.scheduled != 0L + scheduledTime.text = dateFormatter.getScheduledTimestamp(state.scheduled) - binding.attachments.setVisible(state.attachments.isNotEmpty()) + attachments.setVisible(state.attachments.isNotEmpty()) attachmentAdapter.data = state.attachments - binding.attach.animate().rotation(if (state.attaching) 135f else 0f).start() - binding.attaching.isVisible = state.attaching + attach.animate().rotation(if (state.attaching) 135f else 0f).start() + attaching.isVisible = state.attaching - binding.counter.text = state.remaining - binding.counter.setVisible(binding.counter.text.isNotBlank()) + counter.text = state.remaining + counter.setVisible(counter.text.isNotBlank()) - binding.sim.setVisible(state.subscription != null) - binding.sim.contentDescription = getString(R.string.compose_sim_cd, state.subscription?.displayName) - binding.simIndex.text = state.subscription?.simSlotIndex?.plus(1)?.toString() + sim.setVisible(state.subscription != null) + sim.contentDescription = getString(R.string.compose_sim_cd, state.subscription?.displayName) + simIndex.text = state.subscription?.simSlotIndex?.plus(1)?.toString() - binding.send.isEnabled = state.canSend - binding.send.imageAlpha = if (state.canSend) 255 else 128 + send.isEnabled = state.canSend + send.imageAlpha = if (state.canSend) 255 else 128 } override fun clearSelection() = messageAdapter.clearSelection() @@ -282,7 +280,7 @@ class ComposeActivity : QkThemedActivity(), ComposeView { }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)).show() // On some devices, the keyboard can cover the date picker - binding.message.hideKeyboard() + message.hideKeyboard() } override fun requestContact() { @@ -293,7 +291,7 @@ class ComposeActivity : QkThemedActivity(), ComposeView { } override fun showContacts(sharing: Boolean, chips: List) { - binding.message.hideKeyboard() + message.hideKeyboard() val serialized = HashMap(chips.associate { chip -> chip.address to chip.contact?.lookupKey }) val intent = Intent(this, ContactsActivity::class.java) .putExtra(ContactsActivity.SharingKey, sharing) @@ -302,12 +300,12 @@ class ComposeActivity : QkThemedActivity(), ComposeView { } override fun themeChanged() { - binding.messageList.scrapViews() + messageList.scrapViews() } override fun showKeyboard() { - binding.message.postDelayed({ - binding.message.showKeyboard() + message.postDelayed({ + message.showKeyboard() }, 200) } @@ -332,19 +330,19 @@ class ComposeActivity : QkThemedActivity(), ComposeView { } override fun setDraft(draft: String) { - binding.message.setText(draft) - binding.message.setSelection(draft.length) + message.setText(draft) + message.setSelection(draft.length) } override fun scrollToMessage(id: Long) { messageAdapter.data?.second ?.indexOfLast { message -> message.id == id } ?.takeIf { position -> position != -1 } - ?.let(binding.messageList::scrollToPosition) + ?.let(messageList::scrollToPosition) } override fun showQksmsPlusSnackbar(message: Int) { - Snackbar.make(binding.contentView, message, Snackbar.LENGTH_LONG).run { + Snackbar.make(contentView, message, Snackbar.LENGTH_LONG).run { setAction(R.string.button_more) { viewQksmsPlusIntent.onNext(Unit) } setActionTextColor(colors.theme().theme) show() diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt index 6515746c0..d892224b6 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt @@ -46,7 +46,6 @@ import com.moez.QKSMS.common.util.extensions.setPadding import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.util.extensions.setVisible import com.moez.QKSMS.compat.SubscriptionManagerCompat -import com.moez.QKSMS.databinding.MessageListItemInBinding import com.moez.QKSMS.extensions.isSmil import com.moez.QKSMS.extensions.isText import com.moez.QKSMS.feature.compose.BubbleUtils.canGroup @@ -60,6 +59,15 @@ import com.moez.QKSMS.util.Preferences import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject import io.realm.RealmResults +import kotlinx.android.synthetic.main.message_list_item_in.* +import kotlinx.android.synthetic.main.message_list_item_in.attachments +import kotlinx.android.synthetic.main.message_list_item_in.body +import kotlinx.android.synthetic.main.message_list_item_in.sim +import kotlinx.android.synthetic.main.message_list_item_in.simIndex +import kotlinx.android.synthetic.main.message_list_item_in.status +import kotlinx.android.synthetic.main.message_list_item_in.timestamp +import kotlinx.android.synthetic.main.message_list_item_in.view.* +import kotlinx.android.synthetic.main.message_list_item_out.* import java.util.* import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -74,7 +82,7 @@ class MessagesAdapter @Inject constructor( private val phoneNumberUtils: PhoneNumberUtils, private val prefs: Preferences, private val textViewStyler: TextViewStyler -) : QkRealmAdapter() { +) : QkRealmAdapter() { companion object { private const val VIEW_TYPE_MESSAGE_IN = 0 @@ -130,7 +138,7 @@ class MessagesAdapter @Inject constructor( * this a unique viewType even though it uses the same view, so that regular messages * don't need clipToOutline set to true, and they don't need to worry about images */ - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { // Use the parent's context to inflate the layout, otherwise link clicks will crash the app val layoutInflater = LayoutInflater.from(parent.context) @@ -144,26 +152,24 @@ class MessagesAdapter @Inject constructor( view = layoutInflater.inflate(R.layout.message_list_item_in, parent, false) } - val binding = MessageListItemInBinding.bind(view) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - binding.body.hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE + view.body.hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE } val partsAdapter = partsAdapterProvider.get() partsAdapter.clicks.subscribe(partClicks) - binding.attachments.adapter = partsAdapter - binding.attachments.setRecycledViewPool(partsViewPool) - binding.body.forwardTouches(view) + view.attachments.adapter = partsAdapter + view.attachments.setRecycledViewPool(partsViewPool) + view.body.forwardTouches(view) - return QkViewHolder(binding).apply { + return QkViewHolder(view).apply { view.setOnClickListener { val message = getItem(adapterPosition) ?: return@setOnClickListener when (toggleSelection(message.id, false)) { true -> view.isActivated = isSelected(message.id) false -> { clicks.onNext(message.id) - expanded[message.id] = binding.status.visibility != View.VISIBLE + expanded[message.id] = view.status.visibility != View.VISIBLE notifyItemChanged(adapterPosition) } } @@ -177,7 +183,7 @@ class MessagesAdapter @Inject constructor( } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val message = getItem(position) ?: return val previous = if (position == 0) null else getItem(position - 1) val next = if (position == itemCount - 1) null else getItem(position + 1) @@ -188,10 +194,10 @@ class MessagesAdapter @Inject constructor( } // Update the selected state - holder.binding.root.isActivated = isSelected(message.id) || highlight == message.id + holder.containerView.isActivated = isSelected(message.id) || highlight == message.id // Bind the cancel view - holder.binding.cancel.let { cancel -> + holder.cancel?.let { cancel -> val isCancellable = message.isSending() && message.date > System.currentTimeMillis() cancel.setVisible(isCancellable) cancel.clicks().subscribe { cancelSending.onNext(message.id) } @@ -219,25 +225,26 @@ class MessagesAdapter @Inject constructor( val timeSincePrevious = TimeUnit.MILLISECONDS.toMinutes(message.date - (previous?.date ?: 0)) val subscription = subs.find { sub -> sub.subscriptionId == message.subId } - holder.binding.timestamp.text = dateFormatter.getMessageTimestamp(message.date) - holder.binding.simIndex.text = subscription?.simSlotIndex?.plus(1)?.toString() + holder.timestamp.text = dateFormatter.getMessageTimestamp(message.date) + holder.simIndex.text = subscription?.simSlotIndex?.plus(1)?.toString() - holder.binding.timestamp.setVisible(timeSincePrevious >= BubbleUtils.TIMESTAMP_THRESHOLD + holder.timestamp.setVisible(timeSincePrevious >= BubbleUtils.TIMESTAMP_THRESHOLD || message.subId != previous?.subId && subscription != null) - holder.binding.sim.setVisible(message.subId != previous?.subId && subscription != null && subs.size > 1) - holder.binding.simIndex.setVisible(message.subId != previous?.subId && subscription != null && subs.size > 1) + + holder.sim.setVisible(message.subId != previous?.subId && subscription != null && subs.size > 1) + holder.simIndex.setVisible(message.subId != previous?.subId && subscription != null && subs.size > 1) // Bind the grouping val media = message.parts.filter { !it.isSmil() && !it.isText() } - holder.binding.root.setPadding(bottom = if (canGroup(message, next)) 0 else 16.dpToPx(context)) + holder.containerView.setPadding(bottom = if (canGroup(message, next)) 0 else 16.dpToPx(context)) // Bind the avatar and bubble colour if (!message.isMe()) { - holder.binding.avatar.setRecipient(contactCache[message.address]) - holder.binding.avatar.setVisible(!canGroup(message, next), View.INVISIBLE) + holder.avatar.setRecipient(contactCache[message.address]) + holder.avatar.setVisible(!canGroup(message, next), View.INVISIBLE) - holder.binding.body.setTextColor(theme.textPrimary) - holder.binding.body.setBackgroundTint(theme.theme) + holder.body.setTextColor(theme.textPrimary) + holder.body.setBackgroundTint(theme.theme) } // Bind the body text @@ -263,29 +270,29 @@ class MessagesAdapter @Inject constructor( } } val emojiOnly = messageText.isNotBlank() && messageText.matches(EMOJI_REGEX) - textViewStyler.setTextSize(holder.binding.body, when (emojiOnly) { + textViewStyler.setTextSize(holder.body, when (emojiOnly) { true -> TextViewStyler.SIZE_EMOJI false -> TextViewStyler.SIZE_PRIMARY }) - holder.binding.body.text = messageText - holder.binding.body.setVisible(message.isSms() || messageText.isNotBlank()) - holder.binding.body.setBackgroundResource(getBubble( + holder.body.text = messageText + holder.body.setVisible(message.isSms() || messageText.isNotBlank()) + holder.body.setBackgroundResource(getBubble( emojiOnly = emojiOnly, canGroupWithPrevious = canGroup(message, previous) || media.isNotEmpty(), canGroupWithNext = canGroup(message, next), isMe = message.isMe())) // Bind the attachments - val partsAdapter = holder.binding.attachments.adapter as PartsAdapter + val partsAdapter = holder.attachments.adapter as PartsAdapter partsAdapter.theme = theme partsAdapter.setData(message, previous, next, holder) } - private fun bindStatus(holder: QkViewHolder, message: Message, next: Message?) { + private fun bindStatus(holder: QkViewHolder, message: Message, next: Message?) { val age = TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis() - message.date) - holder.binding.status.text = when { + holder.status.text = when { message.isSending() -> context.getString(R.string.message_status_sending) message.isDelivered() -> context.getString(R.string.message_status_delivered, dateFormatter.getTimestamp(message.dateSent)) @@ -299,7 +306,7 @@ class MessagesAdapter @Inject constructor( else -> dateFormatter.getTimestamp(message.date) } - holder.binding.status.setVisible(when { + holder.status.setVisible(when { expanded[message.id] == true -> true message.isSending() -> true message.isFailedMessage() -> true diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ChipsAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ChipsAdapter.kt index a6ebc5d01..b415d32f3 100755 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ChipsAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ChipsAdapter.kt @@ -20,6 +20,7 @@ package com.moez.QKSMS.feature.compose.editing import android.content.Context import android.os.Build +import android.view.LayoutInflater import android.view.ViewGroup import android.widget.RelativeLayout import androidx.recyclerview.widget.RecyclerView @@ -29,35 +30,37 @@ import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.extensions.dpToPx import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setBackgroundTint -import com.moez.QKSMS.databinding.ContactChipBinding import com.moez.QKSMS.model.Recipient import io.reactivex.subjects.PublishSubject +import kotlinx.android.synthetic.main.contact_chip.* import javax.inject.Inject -class ChipsAdapter @Inject constructor() : QkAdapter() { +class ChipsAdapter @Inject constructor() : QkAdapter() { var view: RecyclerView? = null val chipDeleted: PublishSubject = PublishSubject.create() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, ContactChipBinding::inflate).apply { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val inflater = LayoutInflater.from(parent.context) + val view = inflater.inflate(R.layout.contact_chip, parent, false) + return QkViewHolder(view).apply { // These theme attributes don't apply themselves on API 21 if (Build.VERSION.SDK_INT <= 22) { - binding.content.setBackgroundTint(parent.context.resolveThemeColor(R.attr.bubbleColor)) + content.setBackgroundTint(view.context.resolveThemeColor(R.attr.bubbleColor)) } - binding.root.setOnClickListener { + view.setOnClickListener { val chip = getItem(adapterPosition) - showDetailedChip(parent.context, chip) + showDetailedChip(view.context, chip) } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val recipient = getItem(position) - holder.binding.avatar.setRecipient(recipient) - holder.binding.name.text = recipient.contact?.name?.takeIf { it.isNotBlank() } ?: recipient.address + holder.avatar.setRecipient(recipient) + holder.name.text = recipient.contact?.name?.takeIf { it.isNotBlank() } ?: recipient.address } /** @@ -73,9 +76,8 @@ class ChipsAdapter @Inject constructor() : QkAdapter() { +) : QkAdapter() { val clicks: Subject = PublishSubject.create() val longClicks: Subject = PublishSubject.create() @@ -57,19 +59,22 @@ class ComposeItemAdapter @Inject constructor( notifyDataSetChanged() } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, ContactListItemBinding::inflate).apply { - binding.icon.setTint(colors.theme().theme) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + val view = layoutInflater.inflate(R.layout.contact_list_item, parent, false) - binding.numbers.setRecycledViewPool(numbersViewPool) - binding.numbers.adapter = PhoneNumberAdapter() - binding.numbers.forwardTouches(binding.root) + view.icon.setTint(colors.theme().theme) - binding.root.setOnClickListener { + view.numbers.setRecycledViewPool(numbersViewPool) + view.numbers.adapter = PhoneNumberAdapter() + view.numbers.forwardTouches(view) + + return QkViewHolder(view).apply { + view.setOnClickListener { val item = getItem(adapterPosition) clicks.onNext(item) } - binding.root.setOnLongClickListener { + view.setOnLongClickListener { val item = getItem(adapterPosition) longClicks.onNext(item) true @@ -77,7 +82,7 @@ class ComposeItemAdapter @Inject constructor( } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val prevItem = if (position > 0) getItem(position - 1) else null val item = getItem(position) @@ -90,92 +95,92 @@ class ComposeItemAdapter @Inject constructor( } } - private fun bindNew(holder: QkViewHolder, contact: Contact) { - holder.binding.index.isVisible = false + private fun bindNew(holder: QkViewHolder, contact: Contact) { + holder.index.isVisible = false - holder.binding.icon.isVisible = false + holder.icon.isVisible = false - holder.binding.avatar.recipients = listOf(createRecipient(contact)) + holder.avatar.recipients = listOf(createRecipient(contact)) - holder.binding.title.text = contact.numbers.joinToString { it.address } + holder.title.text = contact.numbers.joinToString { it.address } - holder.binding.subtitle.isVisible = false + holder.subtitle.isVisible = false - holder.binding.numbers.isVisible = false + holder.numbers.isVisible = false } - private fun bindRecent(holder: QkViewHolder, conversation: Conversation, prev: ComposeItem?) { - holder.binding.index.isVisible = false + private fun bindRecent(holder: QkViewHolder, conversation: Conversation, prev: ComposeItem?) { + holder.index.isVisible = false - holder.binding.icon.isVisible = prev !is ComposeItem.Recent - holder.binding.icon.setImageResource(R.drawable.ic_history_black_24dp) + holder.icon.isVisible = prev !is ComposeItem.Recent + holder.icon.setImageResource(R.drawable.ic_history_black_24dp) - holder.binding.avatar.recipients = conversation.recipients + holder.avatar.recipients = conversation.recipients - holder.binding.title.text = conversation.getTitle() + holder.title.text = conversation.getTitle() - holder.binding.subtitle.isVisible = conversation.recipients.size > 1 && conversation.name.isBlank() - holder.binding.subtitle.text = conversation.recipients.joinToString(", ") { recipient -> + holder.subtitle.isVisible = conversation.recipients.size > 1 && conversation.name.isBlank() + holder.subtitle.text = conversation.recipients.joinToString(", ") { recipient -> recipient.contact?.name ?: recipient.address } - holder.binding.subtitle.collapseEnabled = conversation.recipients.size > 1 + holder.subtitle.collapseEnabled = conversation.recipients.size > 1 - holder.binding.numbers.isVisible = conversation.recipients.size == 1 - (holder.binding.numbers.adapter as PhoneNumberAdapter).data = conversation.recipients + holder.numbers.isVisible = conversation.recipients.size == 1 + (holder.numbers.adapter as PhoneNumberAdapter).data = conversation.recipients .mapNotNull { recipient -> recipient.contact } .flatMap { contact -> contact.numbers } } - private fun bindStarred(holder: QkViewHolder, contact: Contact, prev: ComposeItem?) { - holder.binding.index.isVisible = false + private fun bindStarred(holder: QkViewHolder, contact: Contact, prev: ComposeItem?) { + holder.index.isVisible = false - holder.binding.icon.isVisible = prev !is ComposeItem.Starred - holder.binding.icon.setImageResource(R.drawable.ic_star_black_24dp) + holder.icon.isVisible = prev !is ComposeItem.Starred + holder.icon.setImageResource(R.drawable.ic_star_black_24dp) - holder.binding.avatar.recipients = listOf(createRecipient(contact)) + holder.avatar.recipients = listOf(createRecipient(contact)) - holder.binding.title.text = contact.name + holder.title.text = contact.name - holder.binding.subtitle.isVisible = false + holder.subtitle.isVisible = false - holder.binding.numbers.isVisible = true - (holder.binding.numbers.adapter as PhoneNumberAdapter).data = contact.numbers + holder.numbers.isVisible = true + (holder.numbers.adapter as PhoneNumberAdapter).data = contact.numbers } - private fun bindGroup(holder: QkViewHolder, group: ContactGroup, prev: ComposeItem?) { - holder.binding.index.isVisible = false + private fun bindGroup(holder: QkViewHolder, group: ContactGroup, prev: ComposeItem?) { + holder.index.isVisible = false - holder.binding.icon.isVisible = prev !is ComposeItem.Group - holder.binding.icon.setImageResource(R.drawable.ic_people_black_24dp) + holder.icon.isVisible = prev !is ComposeItem.Group + holder.icon.setImageResource(R.drawable.ic_people_black_24dp) - holder.binding.avatar.recipients = group.contacts.map(::createRecipient) + holder.avatar.recipients = group.contacts.map(::createRecipient) - holder.binding.title.text = group.title + holder.title.text = group.title - holder.binding.subtitle.isVisible = true - holder.binding.subtitle.text = group.contacts.joinToString(", ") { it.name } - holder.binding.subtitle.collapseEnabled = group.contacts.size > 1 + holder.subtitle.isVisible = true + holder.subtitle.text = group.contacts.joinToString(", ") { it.name } + holder.subtitle.collapseEnabled = group.contacts.size > 1 - holder.binding.numbers.isVisible = false + holder.numbers.isVisible = false } - private fun bindPerson(holder: QkViewHolder, contact: Contact, prev: ComposeItem?) { - holder.binding.index.isVisible = true - holder.binding.index.text = if (contact.name.getOrNull(0)?.isLetter() == true) contact.name[0].toString() else "#" - holder.binding.index.isVisible = prev !is ComposeItem.Person || + private fun bindPerson(holder: QkViewHolder, contact: Contact, prev: ComposeItem?) { + holder.index.isVisible = true + holder.index.text = if (contact.name.getOrNull(0)?.isLetter() == true) contact.name[0].toString() else "#" + holder.index.isVisible = prev !is ComposeItem.Person || (contact.name[0].isLetter() && !contact.name[0].equals(prev.value.name[0], ignoreCase = true)) || (!contact.name[0].isLetter() && prev.value.name[0].isLetter()) - holder.binding.icon.isVisible = false + holder.icon.isVisible = false - holder.binding.avatar.recipients = listOf(createRecipient(contact)) + holder.avatar.recipients = listOf(createRecipient(contact)) - holder.binding.title.text = contact.name + holder.title.text = contact.name - holder.binding.subtitle.isVisible = false + holder.subtitle.isVisible = false - holder.binding.numbers.isVisible = true - (holder.binding.numbers.adapter as PhoneNumberAdapter).data = contact.numbers + holder.numbers.isVisible = true + (holder.numbers.adapter as PhoneNumberAdapter).data = contact.numbers } private fun createRecipient(contact: Contact): Recipient { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/DetailedChipView.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/DetailedChipView.kt index 0b9475df7..aa90cd994 100755 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/DetailedChipView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/DetailedChipView.kt @@ -19,53 +19,44 @@ package com.moez.QKSMS.feature.compose.editing import android.content.Context -import android.util.AttributeSet import android.view.View import android.view.animation.AlphaAnimation -import androidx.constraintlayout.widget.ConstraintLayout +import android.widget.RelativeLayout import com.moez.QKSMS.R import com.moez.QKSMS.common.util.Colors -import com.moez.QKSMS.common.util.extensions.dpToPx import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.ContactChipDetailedBinding import com.moez.QKSMS.injection.appComponent import com.moez.QKSMS.model.Recipient +import kotlinx.android.synthetic.main.contact_chip_detailed.view.* import javax.inject.Inject -class DetailedChipView(context: Context, attrs: AttributeSet? = null) : ConstraintLayout(context, attrs) { +class DetailedChipView(context: Context) : RelativeLayout(context) { @Inject lateinit var colors: Colors - private val binding = viewBinding(ContactChipDetailedBinding::inflate) - init { - if (!isInEditMode) { - appComponent.inject(this) - visibility = View.GONE - } + View.inflate(context, R.layout.contact_chip_detailed, this) + appComponent.inject(this) setOnClickListener { hide() } - setBackgroundResource(R.drawable.rounded_rectangle_2dp) - elevation = 8.dpToPx(context) .toFloat() -// updateLayoutParams { setMargins(8.dpToPx(context) ) } + visibility = View.GONE isFocusable = true isFocusableInTouchMode = true } fun setRecipient(recipient: Recipient) { - binding.avatar.setRecipient(recipient) - binding.name.text = recipient.contact?.name?.takeIf { it.isNotBlank() } ?: recipient.address - binding.info.text = recipient.address + avatar.setRecipient(recipient) + name.text = recipient.contact?.name?.takeIf { it.isNotBlank() } ?: recipient.address + info.text = recipient.address colors.theme(recipient).let { theme -> - setBackgroundTint(theme.theme) - binding.name.setTextColor(theme.textPrimary) - binding.info.setTextColor(theme.textTertiary) - binding.delete.setTint(theme.textPrimary) + card.setBackgroundTint(theme.theme) + name.setTextColor(theme.textPrimary) + info.setTextColor(theme.textTertiary) + delete.setTint(theme.textPrimary) } } @@ -86,7 +77,7 @@ class DetailedChipView(context: Context, attrs: AttributeSet? = null) : Constrai } fun setOnDeleteListener(listener: (View) -> Unit) { - binding.delete.setOnClickListener(listener) + delete.setOnClickListener(listener) } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/PhoneNumberAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/PhoneNumberAdapter.kt index 9a914e167..534f013e9 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/PhoneNumberAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/PhoneNumberAdapter.kt @@ -18,23 +18,27 @@ */ package com.moez.QKSMS.feature.compose.editing +import android.view.LayoutInflater import android.view.ViewGroup +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter import com.moez.QKSMS.common.base.QkViewHolder -import com.moez.QKSMS.databinding.ContactNumberListItemBinding import com.moez.QKSMS.model.PhoneNumber +import kotlinx.android.synthetic.main.contact_number_list_item.* -class PhoneNumberAdapter : QkAdapter() { +class PhoneNumberAdapter : QkAdapter() { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, ContactNumberListItemBinding::inflate) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val inflater = LayoutInflater.from(parent.context) + val view = inflater.inflate(R.layout.contact_number_list_item, parent, false) + return QkViewHolder(view) } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val number = getItem(position) - holder.binding.address.text = number.address - holder.binding.type.text = number.type + holder.address.text = number.address + holder.type.text = number.type } override fun areItemsTheSame(old: PhoneNumber, new: PhoneNumber): Boolean { @@ -45,4 +49,4 @@ class PhoneNumberAdapter : QkAdapter( return old.type == new.type && old.address == new.address } -} +} \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/PhoneNumberPickerAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/PhoneNumberPickerAdapter.kt index 74b5e4295..084e41a37 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/PhoneNumberPickerAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/PhoneNumberPickerAdapter.kt @@ -19,21 +19,24 @@ package com.moez.QKSMS.feature.compose.editing import android.content.Context +import android.view.LayoutInflater import android.view.ViewGroup import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.extensions.forwardTouches -import com.moez.QKSMS.databinding.PhoneNumberListItemBinding import com.moez.QKSMS.extensions.Optional import com.moez.QKSMS.model.PhoneNumber import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.phone_number_list_item.* +import kotlinx.android.synthetic.main.radio_preference_view.* +import kotlinx.android.synthetic.main.radio_preference_view.view.* import javax.inject.Inject class PhoneNumberPickerAdapter @Inject constructor( private val context: Context -) : QkAdapter() { +) : QkAdapter() { val selectedItemChanges: Subject> = BehaviorSubject.create() @@ -45,23 +48,25 @@ class PhoneNumberPickerAdapter @Inject constructor( selectedItemChanges.onNext(Optional(value)) } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, PhoneNumberListItemBinding::inflate).apply { - binding.number.binding.radioButton.forwardTouches(itemView) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val inflater = LayoutInflater.from(parent.context) + val view = inflater.inflate(R.layout.phone_number_list_item, parent, false) + return QkViewHolder(view).apply { + radioButton.forwardTouches(itemView) - binding.root.setOnClickListener { + view.setOnClickListener { val phoneNumber = getItem(adapterPosition) selectedItem = phoneNumber.id } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val phoneNumber = getItem(position) - holder.binding.number.binding.radioButton.isChecked = phoneNumber.id == selectedItem - holder.binding.number.binding.titleView.text = phoneNumber.address - holder.binding.number.binding.summaryView.text = when (phoneNumber.isDefault) { + holder.number.radioButton.isChecked = phoneNumber.id == selectedItem + holder.number.titleView.text = phoneNumber.address + holder.number.summaryView.text = when (phoneNumber.isDefault) { true -> context.getString(R.string.compose_number_picker_default, phoneNumber.type) false -> phoneNumber.type } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/FileBinder.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/FileBinder.kt index cb055e40b..ff12a1bdd 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/FileBinder.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/FileBinder.kt @@ -28,37 +28,35 @@ import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.databinding.MmsFileListItemBinding import com.moez.QKSMS.feature.compose.BubbleUtils import com.moez.QKSMS.model.Message import com.moez.QKSMS.model.MmsPart import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers +import kotlinx.android.synthetic.main.mms_file_list_item.* import javax.inject.Inject -class FileBinder @Inject constructor( - colors: Colors, - private val context: Context -) : PartBinder(MmsFileListItemBinding::inflate) { +class FileBinder @Inject constructor(colors: Colors, private val context: Context) : PartBinder() { + override val partLayout = R.layout.mms_file_list_item override var theme = colors.theme() // This is the last binder we check. If we're here, we can bind the part override fun canBindPart(part: MmsPart) = true @SuppressLint("CheckResult") - override fun bindPartInternal( - holder: QkViewHolder, + override fun bindPart( + holder: QkViewHolder, part: MmsPart, message: Message, canGroupWithPrevious: Boolean, canGroupWithNext: Boolean ) { BubbleUtils.getBubble(false, canGroupWithPrevious, canGroupWithNext, message.isMe()) - .let(holder.binding.fileBackground::setBackgroundResource) + .let(holder.fileBackground::setBackgroundResource) - holder.binding.root.setOnClickListener { clicks.onNext(part.id) } + holder.containerView.setOnClickListener { clicks.onNext(part.id) } Observable.just(part.getUri()) .map(context.contentResolver::openInputStream) @@ -73,23 +71,23 @@ class FileBinder @Inject constructor( } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe { size -> holder.binding.size.text = size } + .subscribe { size -> holder.size.text = size } - holder.binding.filename.text = part.name + holder.filename.text = part.name - val params = holder.binding.fileBackground.layoutParams as FrameLayout.LayoutParams + val params = holder.fileBackground.layoutParams as FrameLayout.LayoutParams if (!message.isMe()) { - holder.binding.fileBackground.layoutParams = params.apply { gravity = Gravity.START } - holder.binding.fileBackground.setBackgroundTint(theme.theme) - holder.binding.icon.setTint(theme.textPrimary) - holder.binding.filename.setTextColor(theme.textPrimary) - holder.binding.size.setTextColor(theme.textTertiary) + holder.fileBackground.layoutParams = params.apply { gravity = Gravity.START } + holder.fileBackground.setBackgroundTint(theme.theme) + holder.icon.setTint(theme.textPrimary) + holder.filename.setTextColor(theme.textPrimary) + holder.size.setTextColor(theme.textTertiary) } else { - holder.binding.fileBackground.layoutParams = params.apply { gravity = Gravity.END } - holder.binding.fileBackground.setBackgroundTint(holder.binding.root.context.resolveThemeColor(R.attr.bubbleColor)) - holder.binding.icon.setTint(holder.binding.root.context.resolveThemeColor(android.R.attr.textColorSecondary)) - holder.binding.filename.setTextColor(holder.binding.root.context.resolveThemeColor(android.R.attr.textColorPrimary)) - holder.binding.size.setTextColor(holder.binding.root.context.resolveThemeColor(android.R.attr.textColorTertiary)) + holder.fileBackground.layoutParams = params.apply { gravity = Gravity.END } + holder.fileBackground.setBackgroundTint(holder.containerView.context.resolveThemeColor(R.attr.bubbleColor)) + holder.icon.setTint(holder.containerView.context.resolveThemeColor(android.R.attr.textColorSecondary)) + holder.filename.setTextColor(holder.containerView.context.resolveThemeColor(android.R.attr.textColorPrimary)) + holder.size.setTextColor(holder.containerView.context.resolveThemeColor(android.R.attr.textColorTertiary)) } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/MediaBinder.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/MediaBinder.kt index 78c5a3209..1ac437a5c 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/MediaBinder.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/MediaBinder.kt @@ -19,45 +19,44 @@ package com.moez.QKSMS.feature.compose.part import android.content.Context +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.setVisible import com.moez.QKSMS.common.widget.BubbleImageView -import com.moez.QKSMS.databinding.MmsPreviewListItemBinding import com.moez.QKSMS.extensions.isImage import com.moez.QKSMS.extensions.isVideo import com.moez.QKSMS.model.Message import com.moez.QKSMS.model.MmsPart import com.moez.QKSMS.util.GlideApp +import kotlinx.android.synthetic.main.mms_preview_list_item.* import javax.inject.Inject -class MediaBinder @Inject constructor( - colors: Colors, - private val context: Context -) : PartBinder(MmsPreviewListItemBinding::inflate) { +class MediaBinder @Inject constructor(colors: Colors, private val context: Context) : PartBinder() { + override val partLayout = R.layout.mms_preview_list_item override var theme = colors.theme() override fun canBindPart(part: MmsPart) = part.isImage() || part.isVideo() - override fun bindPartInternal( - holder: QkViewHolder, + override fun bindPart( + holder: QkViewHolder, part: MmsPart, message: Message, canGroupWithPrevious: Boolean, canGroupWithNext: Boolean ) { - holder.binding.video.setVisible(part.isVideo()) - holder.binding.root.setOnClickListener { clicks.onNext(part.id) } + holder.video.setVisible(part.isVideo()) + holder.containerView.setOnClickListener { clicks.onNext(part.id) } - holder.binding.thumbnail.bubbleStyle = when { + holder.thumbnail.bubbleStyle = when { !canGroupWithPrevious && canGroupWithNext -> if (message.isMe()) BubbleImageView.Style.OUT_FIRST else BubbleImageView.Style.IN_FIRST canGroupWithPrevious && canGroupWithNext -> if (message.isMe()) BubbleImageView.Style.OUT_MIDDLE else BubbleImageView.Style.IN_MIDDLE canGroupWithPrevious && !canGroupWithNext -> if (message.isMe()) BubbleImageView.Style.OUT_LAST else BubbleImageView.Style.IN_LAST else -> BubbleImageView.Style.ONLY } - GlideApp.with(context).load(part.getUri()).fitCenter().into(holder.binding.thumbnail) + GlideApp.with(context).load(part.getUri()).fitCenter().into(holder.thumbnail) } } \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/PartBinder.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/PartBinder.kt index c4e27ba27..d56f8547d 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/PartBinder.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/PartBinder.kt @@ -18,9 +18,6 @@ */ package com.moez.QKSMS.feature.compose.part -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.viewbinding.ViewBinding import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.model.Message @@ -28,36 +25,18 @@ import com.moez.QKSMS.model.MmsPart import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject -abstract class PartBinder( - val bindingInflater: (LayoutInflater, ViewGroup, Boolean) -> Binding -) { +abstract class PartBinder { val clicks: Subject = PublishSubject.create() - abstract var theme: Colors.Theme + abstract val partLayout: Int - fun bindPart( - holder: QkViewHolder, - part: MmsPart, - message: Message, - canGroupWithPrevious: Boolean, - canGroupWithNext: Boolean - ): Boolean { - val castHolder = holder as? QkViewHolder - - if (!canBindPart(part) || castHolder == null) { - return false - } - - bindPartInternal(castHolder, part, message, canGroupWithPrevious, canGroupWithNext) - - return true - } + abstract var theme: Colors.Theme abstract fun canBindPart(part: MmsPart): Boolean - protected abstract fun bindPartInternal( - holder: QkViewHolder, + abstract fun bindPart( + holder: QkViewHolder, part: MmsPart, message: Message, canGroupWithPrevious: Boolean, diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/PartsAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/PartsAdapter.kt index 6f5437d2d..567f49268 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/PartsAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/PartsAdapter.kt @@ -18,20 +18,20 @@ */ package com.moez.QKSMS.feature.compose.part +import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.viewbinding.ViewBinding import com.moez.QKSMS.common.base.QkAdapter import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.forwardTouches -import com.moez.QKSMS.databinding.MessageListItemInBinding import com.moez.QKSMS.extensions.isSmil import com.moez.QKSMS.extensions.isText import com.moez.QKSMS.feature.compose.BubbleUtils.canGroup import com.moez.QKSMS.model.Message import com.moez.QKSMS.model.MmsPart import io.reactivex.Observable +import kotlinx.android.synthetic.main.message_list_item_in.* import javax.inject.Inject class PartsAdapter @Inject constructor( @@ -39,7 +39,7 @@ class PartsAdapter @Inject constructor( fileBinder: FileBinder, mediaBinder: MediaBinder, vCardBinder: VCardBinder -) : QkAdapter() { +) : QkAdapter() { private val partBinders = listOf(mediaBinder, vCardBinder, fileBinder) @@ -54,31 +54,34 @@ class PartsAdapter @Inject constructor( private lateinit var message: Message private var previous: Message? = null private var next: Message? = null - private var holder: QkViewHolder? = null + private var holder: QkViewHolder? = null private var bodyVisible: Boolean = true - fun setData(message: Message, previous: Message?, next: Message?, holder: QkViewHolder) { + fun setData(message: Message, previous: Message?, next: Message?, holder: QkViewHolder) { this.message = message this.previous = previous this.next = next this.holder = holder - this.bodyVisible = holder.binding.body.visibility == View.VISIBLE + this.bodyVisible = holder.body.visibility == View.VISIBLE this.data = message.parts.filter { !it.isSmil() && !it.isText() } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, partBinders[viewType].bindingInflater).apply { - holder?.binding?.root?.let(binding.root::forwardTouches) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val layout = partBinders.getOrNull(viewType)?.partLayout ?: 0 + val view = LayoutInflater.from(parent.context).inflate(layout, parent, false) + holder?.containerView?.let(view::forwardTouches) + return QkViewHolder(view) } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val part = data[position] val canGroupWithPrevious = canGroup(message, previous) || position > 0 val canGroupWithNext = canGroup(message, next) || position < itemCount - 1 || bodyVisible - partBinders.find { binder -> binder.bindPart(holder, part, message, canGroupWithPrevious, canGroupWithNext) } + partBinders + .firstOrNull { it.canBindPart(part) } + ?.bindPart(holder, part, message, canGroupWithPrevious, canGroupWithNext) } override fun getItemViewType(position: Int): Int { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/VCardBinder.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/VCardBinder.kt index 8c0f10508..9e068137d 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/VCardBinder.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/VCardBinder.kt @@ -27,7 +27,6 @@ import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.databinding.MmsVcardListItemBinding import com.moez.QKSMS.extensions.isVCard import com.moez.QKSMS.extensions.mapNotNull import com.moez.QKSMS.feature.compose.BubbleUtils @@ -37,49 +36,48 @@ import ezvcard.Ezvcard import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers +import kotlinx.android.synthetic.main.mms_vcard_list_item.* import javax.inject.Inject -class VCardBinder @Inject constructor( - colors: Colors, - private val context: Context -) : PartBinder(MmsVcardListItemBinding::inflate) { +class VCardBinder @Inject constructor(colors: Colors, private val context: Context) : PartBinder() { + override val partLayout = R.layout.mms_vcard_list_item override var theme = colors.theme() override fun canBindPart(part: MmsPart) = part.isVCard() - override fun bindPartInternal( - holder: QkViewHolder, + override fun bindPart( + holder: QkViewHolder, part: MmsPart, message: Message, canGroupWithPrevious: Boolean, canGroupWithNext: Boolean ) { BubbleUtils.getBubble(false, canGroupWithPrevious, canGroupWithNext, message.isMe()) - .let(holder.binding.vCardBackground::setBackgroundResource) + .let(holder.vCardBackground::setBackgroundResource) - holder.binding.root.setOnClickListener { clicks.onNext(part.id) } + holder.containerView.setOnClickListener { clicks.onNext(part.id) } Observable.just(part.getUri()) .map(context.contentResolver::openInputStream) .mapNotNull { inputStream -> inputStream.use { Ezvcard.parse(it).first() } } .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe { vcard -> holder.binding.name?.text = vcard.formattedName.value } + .subscribe { vcard -> holder.name?.text = vcard.formattedName.value } - val params = holder.binding.vCardBackground.layoutParams as FrameLayout.LayoutParams + val params = holder.vCardBackground.layoutParams as FrameLayout.LayoutParams if (!message.isMe()) { - holder.binding.vCardBackground.layoutParams = params.apply { gravity = Gravity.START } - holder.binding.vCardBackground.setBackgroundTint(theme.theme) - holder.binding.vCardAvatar.setTint(theme.textPrimary) - holder.binding.name.setTextColor(theme.textPrimary) - holder.binding.label.setTextColor(theme.textTertiary) + holder.vCardBackground.layoutParams = params.apply { gravity = Gravity.START } + holder.vCardBackground.setBackgroundTint(theme.theme) + holder.vCardAvatar.setTint(theme.textPrimary) + holder.name.setTextColor(theme.textPrimary) + holder.label.setTextColor(theme.textTertiary) } else { - holder.binding.vCardBackground.layoutParams = params.apply { gravity = Gravity.END } - holder.binding.vCardBackground.setBackgroundTint(holder.binding.root.context.resolveThemeColor(R.attr.bubbleColor)) - holder.binding.vCardAvatar.setTint(holder.binding.root.context.resolveThemeColor(android.R.attr.textColorSecondary)) - holder.binding.name.setTextColor(holder.binding.root.context.resolveThemeColor(android.R.attr.textColorPrimary)) - holder.binding.label.setTextColor(holder.binding.root.context.resolveThemeColor(android.R.attr.textColorTertiary)) + holder.vCardBackground.layoutParams = params.apply { gravity = Gravity.END } + holder.vCardBackground.setBackgroundTint(holder.containerView.context.resolveThemeColor(R.attr.bubbleColor)) + holder.vCardAvatar.setTint(holder.containerView.context.resolveThemeColor(android.R.attr.textColorSecondary)) + holder.name.setTextColor(holder.containerView.context.resolveThemeColor(android.R.attr.textColorPrimary)) + holder.label.setTextColor(holder.containerView.context.resolveThemeColor(android.R.attr.textColorTertiary)) } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/contacts/ContactsActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/contacts/ContactsActivity.kt index af2904a82..f5ca9f71d 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/contacts/ContactsActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/contacts/ContactsActivity.kt @@ -34,9 +34,7 @@ import com.moez.QKSMS.common.util.extensions.hideKeyboard import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.showKeyboard -import com.moez.QKSMS.common.util.extensions.viewBinding import com.moez.QKSMS.common.widget.QkDialog -import com.moez.QKSMS.databinding.ContactsActivityBinding import com.moez.QKSMS.extensions.Optional import com.moez.QKSMS.feature.compose.editing.ComposeItem import com.moez.QKSMS.feature.compose.editing.ComposeItemAdapter @@ -46,6 +44,7 @@ import dagger.android.AndroidInjection import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.contacts_activity.* import javax.inject.Inject class ContactsActivity : QkThemedActivity(), ContactsContract { @@ -59,15 +58,14 @@ class ContactsActivity : QkThemedActivity(), ContactsContract { @Inject lateinit var phoneNumberAdapter: PhoneNumberPickerAdapter @Inject lateinit var viewModelFactory: ViewModelFactory - override val queryChangedIntent: Observable by lazy { binding.search.textChanges() } - override val queryClearedIntent: Observable<*> by lazy { binding.cancel.clicks() } - override val queryEditorActionIntent: Observable by lazy { binding.search.editorActions() } + override val queryChangedIntent: Observable by lazy { search.textChanges() } + override val queryClearedIntent: Observable<*> by lazy { cancel.clicks() } + override val queryEditorActionIntent: Observable by lazy { search.editorActions() } override val composeItemPressedIntent: Subject by lazy { contactsAdapter.clicks } override val composeItemLongPressedIntent: Subject by lazy { contactsAdapter.longClicks } override val phoneNumberSelectedIntent: Subject> by lazy { phoneNumberAdapter.selectedItemChanges } override val phoneNumberActionIntent: Subject = PublishSubject.create() - private val binding by viewBinding(ContactsActivityBinding::inflate) private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[ContactsViewModel::class.java] } private val phoneNumberDialog by lazy { @@ -85,20 +83,20 @@ class ContactsActivity : QkThemedActivity(), ContactsContract { override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.contacts_activity) showBackButton(true) viewModel.bindView(this) - binding.contacts.adapter = contactsAdapter + contacts.adapter = contactsAdapter // These theme attributes don't apply themselves on API 21 if (Build.VERSION.SDK_INT <= 22) { - binding.search.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) + search.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) } } override fun render(state: ContactsState) { - binding.cancel.isVisible = state.query.length > 1 + cancel.isVisible = state.query.length > 1 contactsAdapter.data = state.composeItems @@ -112,17 +110,17 @@ class ContactsActivity : QkThemedActivity(), ContactsContract { } override fun clearQuery() { - binding.search.text = null + search.text = null } override fun openKeyboard() { - binding.search.postDelayed({ - binding.search.showKeyboard() + search.postDelayed({ + search.showKeyboard() }, 200) } override fun finish(result: HashMap) { - binding.search.hideKeyboard() + search.hideKeyboard() val intent = Intent().putExtra(ChipsKey, result) setResult(Activity.RESULT_OK, intent) finish() diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoActivity.kt index 949bfa925..1b6e50378 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoActivity.kt @@ -22,22 +22,21 @@ import android.os.Bundle import com.bluelinelabs.conductor.Conductor import com.bluelinelabs.conductor.Router import com.bluelinelabs.conductor.RouterTransaction +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkThemedActivity -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.ContainerActivityBinding import dagger.android.AndroidInjection +import kotlinx.android.synthetic.main.container_activity.* class ConversationInfoActivity : QkThemedActivity() { - private val binding by viewBinding(ContainerActivityBinding::inflate) private lateinit var router: Router override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.container_activity) - router = Conductor.attachRouter(this, binding.container, savedInstanceState) + router = Conductor.attachRouter(this, container, savedInstanceState) if (!router.hasRootController()) { val threadId = intent.extras?.getLong("threadId") ?: 0L router.setRoot(RouterTransaction.with(ConversationInfoController(threadId))) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoAdapter.kt index 04ec5798e..f75034171 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoAdapter.kt @@ -1,9 +1,9 @@ package com.moez.QKSMS.feature.conversationinfo import android.content.Context +import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.view.isVisible -import androidx.viewbinding.ViewBinding import com.jakewharton.rxbinding2.view.clicks import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter @@ -11,20 +11,20 @@ import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.databinding.ConversationInfoSettingsBinding -import com.moez.QKSMS.databinding.ConversationMediaListItemBinding -import com.moez.QKSMS.databinding.ConversationRecipientListItemBinding import com.moez.QKSMS.extensions.isVideo import com.moez.QKSMS.feature.conversationinfo.ConversationInfoItem.* import com.moez.QKSMS.util.GlideApp import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.conversation_info_settings.* +import kotlinx.android.synthetic.main.conversation_media_list_item.* +import kotlinx.android.synthetic.main.conversation_recipient_list_item.* import javax.inject.Inject class ConversationInfoAdapter @Inject constructor( private val context: Context, private val colors: Colors -) : QkAdapter() { +) : QkAdapter() { val recipientClicks: Subject = PublishSubject.create() val recipientLongClicks: Subject = PublishSubject.create() @@ -36,97 +36,90 @@ class ConversationInfoAdapter @Inject constructor( val deleteClicks: Subject = PublishSubject.create() val mediaClicks: Subject = PublishSubject.create() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - val holder: QkViewHolder = when (viewType) { - 0 -> QkViewHolder(parent, ConversationRecipientListItemBinding::inflate) - 1 -> QkViewHolder(parent, ConversationInfoSettingsBinding::inflate) - 2 -> QkViewHolder(parent, ConversationMediaListItemBinding::inflate) - else -> throw IllegalStateException() - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val inflater = LayoutInflater.from(parent.context) + return when (viewType) { + 0 -> QkViewHolder(inflater.inflate(R.layout.conversation_recipient_list_item, parent, false)).apply { + itemView.setOnClickListener { + val item = getItem(adapterPosition) as? ConversationInfoRecipient + item?.value?.id?.run(recipientClicks::onNext) + } - return holder.apply { - when (binding) { - is ConversationRecipientListItemBinding -> { - itemView.setOnClickListener { - val item = getItem(adapterPosition) as? ConversationInfoRecipient - item?.value?.id?.run(recipientClicks::onNext) - } - - itemView.setOnLongClickListener { - val item = getItem(adapterPosition) as? ConversationInfoRecipient - item?.value?.id?.run(recipientLongClicks::onNext) - true - } - - binding.theme.setOnClickListener { - val item = getItem(adapterPosition) as? ConversationInfoRecipient - item?.value?.id?.run(themeClicks::onNext) - } + itemView.setOnLongClickListener { + val item = getItem(adapterPosition) as? ConversationInfoRecipient + item?.value?.id?.run(recipientLongClicks::onNext) + true } - is ConversationInfoSettingsBinding -> { - binding.groupName.clicks().subscribe(nameClicks) - binding.notifications.clicks().subscribe(notificationClicks) - binding.archive.clicks().subscribe(archiveClicks) - binding.block.clicks().subscribe(blockClicks) - binding.delete.clicks().subscribe(deleteClicks) + theme.setOnClickListener { + val item = getItem(adapterPosition) as? ConversationInfoRecipient + item?.value?.id?.run(themeClicks::onNext) } + } - is ConversationMediaListItemBinding -> { - itemView.setOnClickListener { - val item = getItem(adapterPosition) as? ConversationInfoMedia - item?.value?.id?.run(mediaClicks::onNext) - } + 1 -> QkViewHolder(inflater.inflate(R.layout.conversation_info_settings, parent, false)).apply { + groupName.clicks().subscribe(nameClicks) + notifications.clicks().subscribe(notificationClicks) + archive.clicks().subscribe(archiveClicks) + block.clicks().subscribe(blockClicks) + delete.clicks().subscribe(deleteClicks) + } + + 2 -> QkViewHolder(inflater.inflate(R.layout.conversation_media_list_item, parent, false)).apply { + itemView.setOnClickListener { + val item = getItem(adapterPosition) as? ConversationInfoMedia + item?.value?.id?.run(mediaClicks::onNext) } } + + else -> throw IllegalStateException() } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { - val item = getItem(position) - when { - item is ConversationInfoRecipient && holder.binding is ConversationRecipientListItemBinding -> { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + when (val item = getItem(position)) { + is ConversationInfoRecipient -> { val recipient = item.value - holder.binding.avatar.setRecipient(recipient) + holder.avatar.setRecipient(recipient) - holder.binding.name.text = recipient.contact?.name ?: recipient.address + holder.name.text = recipient.contact?.name ?: recipient.address - holder.binding.address.text = recipient.address - holder.binding.address.setVisible(recipient.contact != null) + holder.address.text = recipient.address + holder.address.setVisible(recipient.contact != null) - holder.binding.add.setVisible(recipient.contact == null) + holder.add.setVisible(recipient.contact == null) val theme = colors.theme(recipient) - holder.binding.theme.setTint(theme.theme) + holder.theme.setTint(theme.theme) } - item is ConversationInfoSettings && holder.binding is ConversationInfoSettingsBinding -> { - holder.binding.groupName.isVisible = item.recipients.size > 1 - holder.binding.groupName.summary = item.name + is ConversationInfoSettings -> { + holder.groupName.isVisible = item.recipients.size > 1 + holder.groupName.summary = item.name - holder.binding.notifications.isEnabled = !item.blocked + holder.notifications.isEnabled = !item.blocked - holder.binding.archive.isEnabled = !item.blocked - holder.binding.archive.title = context.getString(when (item.archived) { + holder.archive.isEnabled = !item.blocked + holder.archive.title = context.getString(when (item.archived) { true -> R.string.info_unarchive false -> R.string.info_archive }) - holder.binding.block.title = context.getString(when (item.blocked) { + holder.block.title = context.getString(when (item.blocked) { true -> R.string.info_unblock false -> R.string.info_block }) } - item is ConversationInfoMedia && holder.binding is ConversationMediaListItemBinding -> { + is ConversationInfoMedia -> { val part = item.value GlideApp.with(context) .load(part.getUri()) .fitCenter() - .into(holder.binding.thumbnail) + .into(holder.thumbnail) - holder.binding.video.isVisible = part.isVideo() + holder.video.isVisible = part.isVideo() } } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoController.kt index 07682cf98..c33408798 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/conversationinfo/ConversationInfoController.kt @@ -28,7 +28,6 @@ import com.moez.QKSMS.common.QkChangeHandler import com.moez.QKSMS.common.base.QkController import com.moez.QKSMS.common.util.extensions.scrapViews import com.moez.QKSMS.common.widget.TextInputDialog -import com.moez.QKSMS.databinding.ConversationInfoControllerBinding import com.moez.QKSMS.feature.blocking.BlockingDialog import com.moez.QKSMS.feature.conversationinfo.injection.ConversationInfoModule import com.moez.QKSMS.feature.themepicker.ThemePickerController @@ -38,12 +37,12 @@ import com.uber.autodispose.autoDisposable import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.conversation_info_controller.* import javax.inject.Inject class ConversationInfoController( val threadId: Long = 0 -) : QkController(ConversationInfoControllerBinding::inflate), ConversationInfoView { +) : QkController(), ConversationInfoView { @Inject override lateinit var presenter: ConversationInfoPresenter @Inject lateinit var blockingDialog: BlockingDialog @@ -63,12 +62,14 @@ class ConversationInfoController( .conversationInfoModule(ConversationInfoModule(this)) .build() .inject(this) + + layoutRes = R.layout.conversation_info_controller } override fun onViewCreated() { - binding.recyclerView.adapter = adapter - binding.recyclerView.addItemDecoration(GridSpacingItemDecoration(adapter, activity!!)) - binding.recyclerView.layoutManager = GridLayoutManager(activity, 3).apply { + recyclerView.adapter = adapter + recyclerView.addItemDecoration(GridSpacingItemDecoration(adapter, activity!!)) + recyclerView.layoutManager = GridLayoutManager(activity, 3).apply { spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { override fun getSpanSize(position: Int): Int = if (adapter.getItemViewType(position) == 2) 1 else 3 } @@ -76,7 +77,7 @@ class ConversationInfoController( themedActivity?.theme ?.autoDisposable(scope()) - ?.subscribe { binding.recyclerView.scrapViews() } + ?.subscribe { recyclerView.scrapViews() } } override fun onAttach(view: View) { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/conversations/ConversationsAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/conversations/ConversationsAdapter.kt index 370be6bce..ed1a3f11a 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/conversations/ConversationsAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/conversations/ConversationsAdapter.kt @@ -35,9 +35,10 @@ import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.DateFormatter import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.databinding.ConversationListItemBinding import com.moez.QKSMS.model.Conversation import com.moez.QKSMS.util.PhoneNumberUtils +import kotlinx.android.synthetic.main.conversation_list_item.* +import kotlinx.android.synthetic.main.conversation_list_item.view.* import javax.inject.Inject class ConversationsAdapter @Inject constructor( @@ -46,48 +47,50 @@ class ConversationsAdapter @Inject constructor( private val dateFormatter: DateFormatter, private val navigator: Navigator, private val phoneNumberUtils: PhoneNumberUtils -) : QkRealmAdapter() { +) : QkRealmAdapter() { init { // This is how we access the threadId for the swipe actions setHasStableIds(true) } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, ConversationListItemBinding::inflate).apply { - if (viewType == 1) { - val textColorPrimary = parent.context.resolveThemeColor(android.R.attr.textColorPrimary) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + val view = layoutInflater.inflate(R.layout.conversation_list_item, parent, false) - binding.title.setTypeface(binding.title.typeface, Typeface.BOLD) + if (viewType == 1) { + val textColorPrimary = parent.context.resolveThemeColor(android.R.attr.textColorPrimary) - binding.snippet.setTypeface(binding.snippet.typeface, Typeface.BOLD) - binding.snippet.setTextColor(textColorPrimary) - binding.snippet.maxLines = 5 + view.title.setTypeface(view.title.typeface, Typeface.BOLD) - binding.unread.isVisible = true + view.snippet.setTypeface(view.snippet.typeface, Typeface.BOLD) + view.snippet.setTextColor(textColorPrimary) + view.snippet.maxLines = 5 - binding.date.setTypeface(binding.date.typeface, Typeface.BOLD) - binding.date.setTextColor(textColorPrimary) - } + view.unread.isVisible = true + + view.date.setTypeface(view.date.typeface, Typeface.BOLD) + view.date.setTextColor(textColorPrimary) + } - binding.root.setOnClickListener { + return QkViewHolder(view).apply { + view.setOnClickListener { val conversation = getItem(adapterPosition) ?: return@setOnClickListener when (toggleSelection(conversation.id, false)) { - true -> binding.root.isActivated = isSelected(conversation.id) + true -> view.isActivated = isSelected(conversation.id) false -> navigator.showConversation(conversation.id) } } - - binding.root.setOnLongClickListener { + view.setOnLongClickListener { val conversation = getItem(adapterPosition) ?: return@setOnLongClickListener true toggleSelection(conversation.id) - binding.root.isActivated = isSelected(conversation.id) + view.isActivated = isSelected(conversation.id) true } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val conversation = getItem(position) ?: return // If the last message wasn't incoming, then the colour doesn't really matter anyway @@ -100,24 +103,24 @@ class ConversationsAdapter @Inject constructor( } val theme = colors.theme(recipient).theme - holder.binding.root.isActivated = isSelected(conversation.id) + holder.containerView.isActivated = isSelected(conversation.id) - holder.binding.avatars.recipients = conversation.recipients - holder.binding.title.collapseEnabled = conversation.recipients.size > 1 - holder.binding.title.text = buildSpannedString { + holder.avatars.recipients = conversation.recipients + holder.title.collapseEnabled = conversation.recipients.size > 1 + holder.title.text = buildSpannedString { append(conversation.getTitle()) if (conversation.draft.isNotEmpty()) { color(theme) { append(" " + context.getString(R.string.main_draft)) } } } - holder.binding.date.text = conversation.date.takeIf { it > 0 }?.let(dateFormatter::getConversationTimestamp) - holder.binding.snippet.text = when { + holder.date.text = conversation.date.takeIf { it > 0 }?.let(dateFormatter::getConversationTimestamp) + holder.snippet.text = when { conversation.draft.isNotEmpty() -> conversation.draft conversation.me -> context.getString(R.string.main_sender_you, conversation.snippet) else -> conversation.snippet } - holder.binding.pinned.isVisible = conversation.pinned - holder.binding.unread.setTint(theme) + holder.pinned.isVisible = conversation.pinned + holder.unread.setTint(theme) } override fun getItemId(position: Int): Long { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryActivity.kt index fe8e0fa2b..f2c261b68 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryActivity.kt @@ -33,13 +33,12 @@ import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkActivity import com.moez.QKSMS.common.util.DateFormatter import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.GalleryActivityBinding import com.moez.QKSMS.model.MmsPart import dagger.android.AndroidInjection import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.gallery_activity.* import javax.inject.Inject class GalleryActivity : QkActivity(), GalleryView { @@ -50,21 +49,20 @@ class GalleryActivity : QkActivity(), GalleryView { val partId by lazy { intent.getLongExtra("partId", 0L) } - private val binding by viewBinding(GalleryActivityBinding::inflate) - private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[GalleryViewModel::class.java] } private val optionsItemSubject: Subject = PublishSubject.create() private val pageChangedSubject: Subject = PublishSubject.create() + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[GalleryViewModel::class.java] } override fun onCreate(savedInstanceState: Bundle?) { delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.gallery_activity) showBackButton(true) viewModel.bindView(this) - binding.pager.adapter = pagerAdapter - binding.pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + pager.adapter = pagerAdapter + pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { this@GalleryActivity.onPageSelected(position) } @@ -76,7 +74,7 @@ class GalleryActivity : QkActivity(), GalleryView { ?.indexOfFirst { part -> part.id == partId } ?.let { index -> onPageSelected(index) - binding.pager.setCurrentItem(index, false) + pager.setCurrentItem(index, false) pagerAdapter.unregisterAdapterDataObserver(this) } } @@ -84,15 +82,15 @@ class GalleryActivity : QkActivity(), GalleryView { } fun onPageSelected(position: Int) { - binding.toolbarSubtitle.text = pagerAdapter.getItem(position)?.messages?.firstOrNull()?.date + toolbarSubtitle.text = pagerAdapter.getItem(position)?.messages?.firstOrNull()?.date ?.let(dateFormatter::getDetailedTimestamp) - binding.toolbarSubtitle.isVisible = binding.toolbarTitle.text.isNotBlank() + toolbarSubtitle.isVisible = toolbarTitle.text.isNotBlank() pagerAdapter.getItem(position)?.run(pageChangedSubject::onNext) } override fun render(state: GalleryState) { - binding.toolbar.setVisible(state.navigationVisible) + toolbar.setVisible(state.navigationVisible) title = state.title pagerAdapter.updateData(state.parts) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryPagerAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryPagerAdapter.kt index 96050060f..f3a4405bc 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryPagerAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryPagerAdapter.kt @@ -19,9 +19,9 @@ package com.moez.QKSMS.feature.gallery import android.content.Context +import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.viewbinding.ViewBinding import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.ExoPlayerFactory import com.google.android.exoplayer2.source.ExtractorMediaSource @@ -30,23 +30,22 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory import com.google.android.exoplayer2.util.Util import com.google.android.mms.ContentType +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkRealmAdapter import com.moez.QKSMS.common.base.QkViewHolder -import com.moez.QKSMS.databinding.GalleryImagePageBinding -import com.moez.QKSMS.databinding.GalleryInvalidPageBinding -import com.moez.QKSMS.databinding.GalleryVideoPageBinding import com.moez.QKSMS.extensions.isImage import com.moez.QKSMS.extensions.isVideo import com.moez.QKSMS.model.MmsPart import com.moez.QKSMS.util.GlideApp import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.gallery_image_page.* +import kotlinx.android.synthetic.main.gallery_image_page.view.* +import kotlinx.android.synthetic.main.gallery_video_page.* import java.util.* import javax.inject.Inject -class GalleryPagerAdapter @Inject constructor( - private val context: Context -) : QkRealmAdapter() { +class GalleryPagerAdapter @Inject constructor(private val context: Context) : QkRealmAdapter() { companion object { private const val VIEW_TYPE_INVALID = 0 @@ -59,61 +58,60 @@ class GalleryPagerAdapter @Inject constructor( private val contentResolver = context.contentResolver private val exoPlayers = Collections.newSetFromMap(WeakHashMap()) - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - val holder: QkViewHolder = when (viewType) { - VIEW_TYPE_IMAGE -> QkViewHolder(parent, GalleryImagePageBinding::inflate) - VIEW_TYPE_VIDEO -> QkViewHolder(parent, GalleryVideoPageBinding::inflate) - else -> QkViewHolder(parent, GalleryInvalidPageBinding::inflate) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val inflater = LayoutInflater.from(parent.context) + return QkViewHolder(when (viewType) { + VIEW_TYPE_IMAGE -> inflater.inflate(R.layout.gallery_image_page, parent, false).apply { - return holder.apply { - if (binding is GalleryImagePageBinding) { // When calling the public setter, it doesn't allow the midscale to be the same as the // maxscale or the minscale. We don't want 3 levels and we don't want to modify the library // so let's celebrate the invention of reflection! - binding.image.attacher.run { + image.attacher.run { javaClass.getDeclaredField("mMinScale").run { isAccessible = true - setFloat(binding.image.attacher, 1f) + setFloat(image.attacher, 1f) } javaClass.getDeclaredField("mMidScale").run { isAccessible = true - setFloat(binding.image.attacher, 1f) + setFloat(image.attacher, 1f) } javaClass.getDeclaredField("mMaxScale").run { isAccessible = true - setFloat(binding.image.attacher, 3f) + setFloat(image.attacher, 3f) } } } - binding.root.setOnClickListener(clicks::onNext) - } + VIEW_TYPE_VIDEO -> inflater.inflate(R.layout.gallery_video_page, parent, false) + + else -> inflater.inflate(R.layout.gallery_invalid_page, parent, false) + + }.apply { setOnClickListener(clicks::onNext) }) } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val part = getItem(position) ?: return - when { - getItemViewType(position) == VIEW_TYPE_IMAGE && holder.binding is GalleryImagePageBinding -> { + when (getItemViewType(position)) { + VIEW_TYPE_IMAGE -> { // We need to explicitly request a gif from glide for animations to work when (part.getUri().let(contentResolver::getType)) { ContentType.IMAGE_GIF -> GlideApp.with(context) .asGif() .load(part.getUri()) - .into(holder.binding.image) + .into(holder.image) else -> GlideApp.with(context) .asBitmap() .load(part.getUri()) - .into(holder.binding.image) + .into(holder.image) } } - getItemViewType(position) == VIEW_TYPE_VIDEO && holder.binding is GalleryVideoPageBinding -> { + VIEW_TYPE_VIDEO -> { val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory(null) val trackSelector = DefaultTrackSelector(videoTrackSelectionFactory) val exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector) - holder.binding.video.player = exoPlayer + holder.video.player = exoPlayer exoPlayers.add(exoPlayer) val dataSourceFactory = DefaultDataSourceFactory(context, Util.getUserAgent(context, "QKSMS")) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt index 088a8179f..068bc4bec 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt @@ -29,10 +29,12 @@ import android.view.Gravity import android.view.Menu import android.view.MenuItem import android.view.View +import android.view.ViewStub import androidx.appcompat.app.ActionBarDrawerToggle import androidx.core.app.ActivityCompat import androidx.core.view.GravityCompat import androidx.core.view.isVisible +import androidx.lifecycle.Lifecycle import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.ItemTouchHelper @@ -50,8 +52,6 @@ import com.moez.QKSMS.common.util.extensions.scrapViews import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.MainActivityBinding import com.moez.QKSMS.feature.blocking.BlockingDialog import com.moez.QKSMS.feature.changelog.ChangelogDialog import com.moez.QKSMS.feature.conversations.ConversationItemTouchCallback @@ -65,6 +65,10 @@ import io.reactivex.Observable import io.reactivex.disposables.CompositeDisposable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.drawer_view.* +import kotlinx.android.synthetic.main.main_activity.* +import kotlinx.android.synthetic.main.main_permission_hint.* +import kotlinx.android.synthetic.main.main_syncing.* import javax.inject.Inject class MainActivity : QkThemedActivity(), MainView { @@ -80,10 +84,10 @@ class MainActivity : QkThemedActivity(), MainView { override val onNewIntentIntent: Subject = PublishSubject.create() override val activityResumedIntent: Subject = PublishSubject.create() - override val queryChangedIntent by lazy { binding.toolbarSearch.textChanges() } - override val composeIntent by lazy { binding.compose.clicks() } + override val queryChangedIntent by lazy { toolbarSearch.textChanges() } + override val composeIntent by lazy { compose.clicks() } override val drawerOpenIntent: Observable by lazy { - binding.drawerLayout + drawerLayout .drawerOpen(Gravity.START) .doOnNext { dismissKeyboard() } } @@ -91,32 +95,31 @@ class MainActivity : QkThemedActivity(), MainView { override val navigationIntent: Observable by lazy { Observable.merge(listOf( backPressedSubject, - binding.drawer.inbox.clicks().map { NavItem.INBOX }, - binding.drawer.archived.clicks().map { NavItem.ARCHIVED }, - binding.drawer.backup.clicks().map { NavItem.BACKUP }, - binding.drawer.scheduled.clicks().map { NavItem.SCHEDULED }, - binding.drawer.blocking.clicks().map { NavItem.BLOCKING }, - binding.drawer.settings.clicks().map { NavItem.SETTINGS }, - binding.drawer.plus.clicks().map { NavItem.PLUS }, - binding.drawer.help.clicks().map { NavItem.HELP }, - binding.drawer.invite.clicks().map { NavItem.INVITE })) + inbox.clicks().map { NavItem.INBOX }, + archived.clicks().map { NavItem.ARCHIVED }, + backup.clicks().map { NavItem.BACKUP }, + scheduled.clicks().map { NavItem.SCHEDULED }, + blocking.clicks().map { NavItem.BLOCKING }, + settings.clicks().map { NavItem.SETTINGS }, + plus.clicks().map { NavItem.PLUS }, + help.clicks().map { NavItem.HELP }, + invite.clicks().map { NavItem.INVITE })) } override val optionsItemIntent: Subject = PublishSubject.create() - override val plusBannerIntent by lazy { binding.drawer.plusBanner.clicks() } - override val dismissRatingIntent by lazy { binding.drawer.rateDismiss.clicks() } - override val rateIntent by lazy { binding.drawer.rateOkay.clicks() } + override val plusBannerIntent by lazy { plusBanner.clicks() } + override val dismissRatingIntent by lazy { rateDismiss.clicks() } + override val rateIntent by lazy { rateOkay.clicks() } override val conversationsSelectedIntent by lazy { conversationsAdapter.selectionChanges } override val confirmDeleteIntent: Subject> = PublishSubject.create() override val swipeConversationIntent by lazy { itemTouchCallback.swipes } override val changelogMoreIntent by lazy { changelogDialog.moreClicks } override val undoArchiveIntent: Subject = PublishSubject.create() - override val snackbarButtonIntent by lazy { binding.snackbar.button.clicks() } + override val snackbarButtonIntent: Subject = PublishSubject.create() - private val binding by viewBinding(MainActivityBinding::inflate) private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[MainViewModel::class.java] } - private val toggle by lazy { ActionBarDrawerToggle(this, binding.drawerLayout, binding.toolbar, R.string.main_drawer_open_cd, 0) } + private val toggle by lazy { ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.main_drawer_open_cd, 0) } private val itemTouchHelper by lazy { ItemTouchHelper(itemTouchCallback) } - private val progressAnimator by lazy { ObjectAnimator.ofInt(binding.syncing.progress, "progress", 0, 0) } + private val progressAnimator by lazy { ObjectAnimator.ofInt(syncingProgress, "progress", 0, 0) } private val changelogDialog by lazy { ChangelogDialog(this) } private val snackbar by lazy { findViewById(R.id.snackbar) } private val syncing by lazy { findViewById(R.id.syncing) } @@ -125,21 +128,32 @@ class MainActivity : QkThemedActivity(), MainView { override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.main_activity) viewModel.bindView(this) onNewIntentIntent.onNext(intent) + (snackbar as? ViewStub)?.setOnInflateListener { _, _ -> + snackbarButton.clicks() + .autoDisposable(scope(Lifecycle.Event.ON_DESTROY)) + .subscribe(snackbarButtonIntent) + } + + (syncing as? ViewStub)?.setOnInflateListener { _, _ -> + syncingProgress?.progressTintList = ColorStateList.valueOf(theme.blockingFirst().theme) + syncingProgress?.indeterminateTintList = ColorStateList.valueOf(theme.blockingFirst().theme) + } + toggle.syncState() - binding.toolbar.setNavigationOnClickListener { + toolbar.setNavigationOnClickListener { dismissKeyboard() homeIntent.onNext(Unit) } itemTouchCallback.adapter = conversationsAdapter - conversationsAdapter.autoScrollToStart(binding.recyclerView) + conversationsAdapter.autoScrollToStart(recyclerView) // Don't allow clicks to pass through the drawer layout - binding.drawer.root.clicks().autoDisposable(scope()).subscribe() + drawer.clicks().autoDisposable(scope()).subscribe() // Set the theme color tint to the recyclerView, progressbar, and FAB theme @@ -153,28 +167,28 @@ class MainActivity : QkThemedActivity(), MainView { resolveThemeColor(android.R.attr.textColorSecondary) .let { textSecondary -> ColorStateList(states, intArrayOf(theme.theme, textSecondary)) } .let { tintList -> - binding.drawer.inboxIcon.imageTintList = tintList - binding.drawer.archivedIcon.imageTintList = tintList + inboxIcon.imageTintList = tintList + archivedIcon.imageTintList = tintList } // Miscellaneous views - listOf(binding.drawer.plusBadge1, binding.drawer.plusBadge2).forEach { badge -> + listOf(plusBadge1, plusBadge2).forEach { badge -> badge.setBackgroundTint(theme.theme) badge.setTextColor(theme.textPrimary) } - binding.syncing.progress.progressTintList = ColorStateList.valueOf(theme.theme) - binding.syncing.progress.indeterminateTintList = ColorStateList.valueOf(theme.theme) - binding.drawer.plusIcon.setTint(theme.theme) - binding.drawer.rateIcon.setTint(theme.theme) - binding.compose.setBackgroundTint(theme.theme) + syncingProgress?.progressTintList = ColorStateList.valueOf(theme.theme) + syncingProgress?.indeterminateTintList = ColorStateList.valueOf(theme.theme) + plusIcon.setTint(theme.theme) + rateIcon.setTint(theme.theme) + compose.setBackgroundTint(theme.theme) // Set the FAB compose icon color - binding.compose.setTint(theme.textPrimary) + compose.setTint(theme.textPrimary) } // These theme attributes don't apply themselves on API 21 if (Build.VERSION.SDK_INT <= 22) { - binding.toolbarSearch.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) + toolbarSearch.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) } } @@ -213,46 +227,46 @@ class MainActivity : QkThemedActivity(), MainView { else -> 0 } - binding.toolbarSearch.setVisible(state.page is Inbox && state.page.selected == 0 || state.page is Searching) - binding.toolbarTitle.setVisible(binding.toolbarSearch.visibility != View.VISIBLE) + toolbarSearch.setVisible(state.page is Inbox && state.page.selected == 0 || state.page is Searching) + toolbarTitle.setVisible(toolbarSearch.visibility != View.VISIBLE) - binding.toolbar.menu.findItem(R.id.archive)?.isVisible = state.page is Inbox && selectedConversations != 0 - binding.toolbar.menu.findItem(R.id.unarchive)?.isVisible = state.page is Archived && selectedConversations != 0 - binding.toolbar.menu.findItem(R.id.delete)?.isVisible = selectedConversations != 0 - binding.toolbar.menu.findItem(R.id.add)?.isVisible = addContact && selectedConversations != 0 - binding.toolbar.menu.findItem(R.id.pin)?.isVisible = markPinned && selectedConversations != 0 - binding.toolbar.menu.findItem(R.id.unpin)?.isVisible = !markPinned && selectedConversations != 0 - binding.toolbar.menu.findItem(R.id.read)?.isVisible = markRead && selectedConversations != 0 - binding.toolbar.menu.findItem(R.id.unread)?.isVisible = !markRead && selectedConversations != 0 - binding.toolbar.menu.findItem(R.id.block)?.isVisible = selectedConversations != 0 + toolbar.menu.findItem(R.id.archive)?.isVisible = state.page is Inbox && selectedConversations != 0 + toolbar.menu.findItem(R.id.unarchive)?.isVisible = state.page is Archived && selectedConversations != 0 + toolbar.menu.findItem(R.id.delete)?.isVisible = selectedConversations != 0 + toolbar.menu.findItem(R.id.add)?.isVisible = addContact && selectedConversations != 0 + toolbar.menu.findItem(R.id.pin)?.isVisible = markPinned && selectedConversations != 0 + toolbar.menu.findItem(R.id.unpin)?.isVisible = !markPinned && selectedConversations != 0 + toolbar.menu.findItem(R.id.read)?.isVisible = markRead && selectedConversations != 0 + toolbar.menu.findItem(R.id.unread)?.isVisible = !markRead && selectedConversations != 0 + toolbar.menu.findItem(R.id.block)?.isVisible = selectedConversations != 0 - listOf(binding.drawer.plusBadge1, binding.drawer.plusBadge2).forEach { badge -> + listOf(plusBadge1, plusBadge2).forEach { badge -> badge.isVisible = drawerBadgesExperiment.variant && !state.upgraded } - binding.drawer.plus.isVisible = state.upgraded - binding.drawer.plusBanner.isVisible = !state.upgraded - binding.drawer.rateLayout.setVisible(state.showRating) + plus.isVisible = state.upgraded + plusBanner.isVisible = !state.upgraded + rateLayout.setVisible(state.showRating) - binding.compose.setVisible(state.page is Inbox || state.page is Archived) - conversationsAdapter.emptyView = binding.empty.takeIf { state.page is Inbox || state.page is Archived } - searchAdapter.emptyView = binding.empty.takeIf { state.page is Searching } + compose.setVisible(state.page is Inbox || state.page is Archived) + conversationsAdapter.emptyView = empty.takeIf { state.page is Inbox || state.page is Archived } + searchAdapter.emptyView = empty.takeIf { state.page is Searching } when (state.page) { is Inbox -> { showBackButton(state.page.selected > 0) title = getString(R.string.main_title_selected, state.page.selected) - if (binding.recyclerView.adapter !== conversationsAdapter) binding.recyclerView.adapter = conversationsAdapter + if (recyclerView.adapter !== conversationsAdapter) recyclerView.adapter = conversationsAdapter conversationsAdapter.updateData(state.page.data) - itemTouchHelper.attachToRecyclerView(binding.recyclerView) - binding.empty.setText(R.string.inbox_empty_text) + itemTouchHelper.attachToRecyclerView(recyclerView) + empty.setText(R.string.inbox_empty_text) } is Searching -> { showBackButton(true) - if (binding.recyclerView.adapter !== searchAdapter) binding.recyclerView.adapter = searchAdapter + if (recyclerView.adapter !== searchAdapter) recyclerView.adapter = searchAdapter searchAdapter.data = state.page.data ?: listOf() itemTouchHelper.attachToRecyclerView(null) - binding.empty.setText(R.string.inbox_search_empty_text) + empty.setText(R.string.inbox_search_empty_text) } is Archived -> { @@ -261,20 +275,20 @@ class MainActivity : QkThemedActivity(), MainView { true -> getString(R.string.main_title_selected, state.page.selected) false -> getString(R.string.title_archived) } - if (binding.recyclerView.adapter !== conversationsAdapter) binding.recyclerView.adapter = conversationsAdapter + if (recyclerView.adapter !== conversationsAdapter) recyclerView.adapter = conversationsAdapter conversationsAdapter.updateData(state.page.data) itemTouchHelper.attachToRecyclerView(null) - binding.empty.setText(R.string.archived_empty_text) + empty.setText(R.string.archived_empty_text) } } - binding.drawer.inbox.isActivated = state.page is Inbox - binding.drawer.archived.isActivated = state.page is Archived + inbox.isActivated = state.page is Inbox + archived.isActivated = state.page is Archived - if (binding.drawerLayout.isDrawerOpen(GravityCompat.START) && !state.drawerOpen) { - binding.drawerLayout.closeDrawer(GravityCompat.START) - } else if (!binding.drawerLayout.isDrawerVisible(GravityCompat.START) && state.drawerOpen) { - binding.drawerLayout.openDrawer(GravityCompat.START) + if (drawerLayout.isDrawerOpen(GravityCompat.START) && !state.drawerOpen) { + drawerLayout.closeDrawer(GravityCompat.START) + } else if (!drawerLayout.isDrawerVisible(GravityCompat.START) && state.drawerOpen) { + drawerLayout.openDrawer(GravityCompat.START) } when (state.syncing) { @@ -285,30 +299,30 @@ class MainActivity : QkThemedActivity(), MainView { is SyncRepository.SyncProgress.Running -> { syncing.isVisible = true - binding.syncing.progress.max = state.syncing.max - progressAnimator.apply { setIntValues(binding.syncing.progress.progress, state.syncing.progress) }.start() - binding.syncing.progress.isIndeterminate = state.syncing.indeterminate + syncingProgress.max = state.syncing.max + progressAnimator.apply { setIntValues(syncingProgress.progress, state.syncing.progress) }.start() + syncingProgress.isIndeterminate = state.syncing.indeterminate snackbar.isVisible = false } } when { !state.defaultSms -> { - binding.snackbar.title.setText(R.string.main_default_sms_title) - binding.snackbar.message.setText(R.string.main_default_sms_message) - binding.snackbar.button.setText(R.string.main_default_sms_change) + snackbarTitle?.setText(R.string.main_default_sms_title) + snackbarMessage?.setText(R.string.main_default_sms_message) + snackbarButton?.setText(R.string.main_default_sms_change) } !state.smsPermission -> { - binding.snackbar.title.setText(R.string.main_permission_required) - binding.snackbar.message.setText(R.string.main_permission_sms) - binding.snackbar.button.setText(R.string.main_permission_allow) + snackbarTitle?.setText(R.string.main_permission_required) + snackbarMessage?.setText(R.string.main_permission_sms) + snackbarButton?.setText(R.string.main_permission_allow) } !state.contactPermission -> { - binding.snackbar.title.setText(R.string.main_permission_required) - binding.snackbar.message.setText(R.string.main_permission_contacts) - binding.snackbar.button.setText(R.string.main_permission_allow) + snackbarTitle?.setText(R.string.main_permission_required) + snackbarMessage?.setText(R.string.main_permission_contacts) + snackbarButton?.setText(R.string.main_permission_allow) } } } @@ -329,7 +343,7 @@ class MainActivity : QkThemedActivity(), MainView { } override fun showBackButton(show: Boolean) { - toggle.onDrawerSlide(binding.drawer.root, if (show) 1f else 0f) + toggle.onDrawerSlide(drawer, if (show) 1f else 0f) toggle.drawerArrowDrawable.color = when (show) { true -> resolveThemeColor(android.R.attr.textColorSecondary) false -> resolveThemeColor(android.R.attr.textColorPrimary) @@ -349,7 +363,7 @@ class MainActivity : QkThemedActivity(), MainView { override fun clearSearch() { dismissKeyboard() - binding.toolbarSearch.text = null + toolbarSearch.text = null } override fun clearSelection() { @@ -357,7 +371,7 @@ class MainActivity : QkThemedActivity(), MainView { } override fun themeChanged() { - binding.recyclerView.scrapViews() + recyclerView.scrapViews() } override fun showBlockingDialog(conversations: List, block: Boolean) { @@ -379,7 +393,7 @@ class MainActivity : QkThemedActivity(), MainView { } override fun showArchivedSnackbar() { - Snackbar.make(binding.drawerLayout, R.string.toast_archived, Snackbar.LENGTH_LONG).apply { + Snackbar.make(drawerLayout, R.string.toast_archived, Snackbar.LENGTH_LONG).apply { setAction(R.string.button_undo) { undoArchiveIntent.onNext(Unit) } setActionTextColor(colors.theme().theme) show() diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/SearchAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/SearchAdapter.kt index e59dde89e..9a964a208 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/SearchAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/SearchAdapter.kt @@ -31,9 +31,10 @@ import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.DateFormatter import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.databinding.SearchListItemBinding import com.moez.QKSMS.extensions.removeAccents import com.moez.QKSMS.model.SearchResult +import kotlinx.android.synthetic.main.search_list_item.* +import kotlinx.android.synthetic.main.search_list_item.view.* import javax.inject.Inject class SearchAdapter @Inject constructor( @@ -41,24 +42,26 @@ class SearchAdapter @Inject constructor( private val context: Context, private val dateFormatter: DateFormatter, private val navigator: Navigator -) : QkAdapter() { +) : QkAdapter() { private val highlightColor: Int by lazy { colors.theme().highlight } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, SearchListItemBinding::inflate).apply { - binding.root.setOnClickListener { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + val view = layoutInflater.inflate(R.layout.search_list_item, parent, false) + return QkViewHolder(view).apply { + view.setOnClickListener { val result = getItem(adapterPosition) navigator.showConversation(result.conversation.id, result.query.takeIf { result.messages > 0 }) } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val previous = data.getOrNull(position - 1) val result = getItem(position) - holder.binding.resultsHeader.setVisible(result.messages > 0 && previous?.messages == 0) + holder.resultsHeader.setVisible(result.messages > 0 && previous?.messages == 0) val query = result.query val title = SpannableString(result.conversation.getTitle()) @@ -68,23 +71,23 @@ class SearchAdapter @Inject constructor( title.setSpan(BackgroundColorSpan(highlightColor), index, index + query.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) index = title.indexOf(query, index + query.length, true) } - holder.binding.title.text = title + holder.title.text = title - holder.binding.avatars.recipients = result.conversation.recipients + holder.avatars.recipients = result.conversation.recipients when (result.messages == 0) { true -> { - holder.binding.date.setVisible(true) - holder.binding.date.text = dateFormatter.getConversationTimestamp(result.conversation.date) - holder.binding.snippet.text = when (result.conversation.me) { + holder.date.setVisible(true) + holder.date.text = dateFormatter.getConversationTimestamp(result.conversation.date) + holder.snippet.text = when (result.conversation.me) { true -> context.getString(R.string.main_sender_you, result.conversation.snippet) false -> result.conversation.snippet } } false -> { - holder.binding.date.setVisible(false) - holder.binding.snippet.text = context.getString(R.string.main_message_results, result.messages) + holder.date.setVisible(false) + holder.snippet.text = context.getString(R.string.main_message_results, result.messages) } } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/notificationprefs/NotificationPrefsActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/notificationprefs/NotificationPrefsActivity.kt index 570ca299d..210b5d3fe 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/notificationprefs/NotificationPrefsActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/notificationprefs/NotificationPrefsActivity.kt @@ -33,16 +33,15 @@ import com.moez.QKSMS.common.QkDialog import com.moez.QKSMS.common.base.QkThemedActivity import com.moez.QKSMS.common.util.extensions.animateLayoutChanges import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.common.util.extensions.viewBinding import com.moez.QKSMS.common.widget.PreferenceView -import com.moez.QKSMS.common.widget.QkSwitch -import com.moez.QKSMS.databinding.NotificationPrefsActivityBinding import com.uber.autodispose.android.lifecycle.scope import com.uber.autodispose.autoDisposable import dagger.android.AndroidInjection import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.notification_prefs_activity.* +import kotlinx.android.synthetic.main.settings_switch_widget.view.* import javax.inject.Inject class NotificationPrefsActivity : QkThemedActivity(), NotificationPrefsView { @@ -56,7 +55,6 @@ class NotificationPrefsActivity : QkThemedActivity(), NotificationPrefsView { override val ringtoneSelectedIntent: Subject = PublishSubject.create() override val actionsSelectedIntent by lazy { actionsDialog.adapter.menuItemClicks } - private val binding by viewBinding(NotificationPrefsActivityBinding::inflate) private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[NotificationPrefsViewModel::class.java] } @@ -64,27 +62,27 @@ class NotificationPrefsActivity : QkThemedActivity(), NotificationPrefsView { override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.notification_prefs_activity) setTitle(R.string.title_notification_prefs) showBackButton(true) viewModel.bindView(this) - binding.preferences.postDelayed({ binding.preferences.animateLayoutChanges = true }, 100) + preferences.postDelayed({ preferences?.animateLayoutChanges = true }, 100) val hasOreo = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - binding.notificationsO.setVisible(hasOreo) - binding.notifications.setVisible(!hasOreo) - binding.vibration.setVisible(!hasOreo) - binding.ringtone.setVisible(!hasOreo) + notificationsO.setVisible(hasOreo) + notifications.setVisible(!hasOreo) + vibration.setVisible(!hasOreo) + ringtone.setVisible(!hasOreo) previewModeDialog.setTitle(R.string.settings_notification_previews_title) previewModeDialog.adapter.setData(R.array.notification_preview_options) actionsDialog.adapter.setData(R.array.notification_actions) // Listen to clicks for all of the preferences - (0 until binding.preferences.childCount) - .map { index -> binding.preferences.getChildAt(index) } + (0 until preferences.childCount) + .map { index -> preferences.getChildAt(index) } .mapNotNull { view -> view as? PreferenceView } .map { preference -> preference.clicks().map { preference } } .let { Observable.merge(it) } @@ -97,29 +95,29 @@ class NotificationPrefsActivity : QkThemedActivity(), NotificationPrefsView { title = state.conversationTitle } - binding.notifications.widget().isChecked = state.notificationsEnabled - binding.previews.summary = state.previewSummary + notifications.checkbox.isChecked = state.notificationsEnabled + previews.summary = state.previewSummary previewModeDialog.adapter.selectedItem = state.previewId - binding.wake.widget().isChecked = state.wakeEnabled - binding.vibration.widget().isChecked = state.vibrationEnabled - binding.ringtone.summary = state.ringtoneName - - binding.actionsDivider.isVisible = state.threadId == 0L - binding.actionsTitle.isVisible = state.threadId == 0L - binding.action1.isVisible = state.threadId == 0L - binding.action1.summary = state.action1Summary - binding.action2.isVisible = state.threadId == 0L - binding.action2.summary = state.action2Summary - binding.action3.isVisible = state.threadId == 0L - binding.action3.summary = state.action3Summary - - binding.qkreplyDivider.isVisible = state.threadId == 0L - binding.qkreplyTitle.isVisible = state.threadId == 0L - binding.qkreply.widget().isChecked = state.qkReplyEnabled - binding.qkreply.isVisible = state.threadId == 0L - binding.qkreplyTapDismiss.isVisible = state.threadId == 0L - binding.qkreplyTapDismiss.isEnabled = state.qkReplyEnabled - binding.qkreplyTapDismiss.widget().isChecked = state.qkReplyTapDismiss + wake.checkbox.isChecked = state.wakeEnabled + vibration.checkbox.isChecked = state.vibrationEnabled + ringtone.summary = state.ringtoneName + + actionsDivider.isVisible = state.threadId == 0L + actionsTitle.isVisible = state.threadId == 0L + action1.isVisible = state.threadId == 0L + action1.summary = state.action1Summary + action2.isVisible = state.threadId == 0L + action2.summary = state.action2Summary + action3.isVisible = state.threadId == 0L + action3.summary = state.action3Summary + + qkreplyDivider.isVisible = state.threadId == 0L + qkreplyTitle.isVisible = state.threadId == 0L + qkreply.checkbox.isChecked = state.qkReplyEnabled + qkreply.isVisible = state.threadId == 0L + qkreplyTapDismiss.isVisible = state.threadId == 0L + qkreplyTapDismiss.isEnabled = state.qkReplyEnabled + qkreplyTapDismiss.checkbox.isChecked = state.qkReplyTapDismiss } override fun showPreviewModeDialog() = previewModeDialog.show(this) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/plus/PlusActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/plus/PlusActivity.kt index b8a2ec9a6..eb589d764 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/plus/PlusActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/plus/PlusActivity.kt @@ -24,6 +24,7 @@ import androidx.core.view.children import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders import com.jakewharton.rxbinding2.view.clicks +import com.jakewharton.rxbinding2.view.enabled import com.moez.QKSMS.BuildConfig import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkThemedActivity @@ -32,12 +33,14 @@ import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.common.util.extensions.viewBinding import com.moez.QKSMS.common.widget.PreferenceView -import com.moez.QKSMS.databinding.QksmsPlusActivityBinding import com.moez.QKSMS.feature.plus.experiment.UpgradeButtonExperiment import com.moez.QKSMS.manager.BillingManager import dagger.android.AndroidInjection +import io.reactivex.Observable +import kotlinx.android.synthetic.main.collapsing_toolbar.* +import kotlinx.android.synthetic.main.preference_view.view.* +import kotlinx.android.synthetic.main.qksms_plus_activity.* import javax.inject.Inject class PlusActivity : QkThemedActivity(), PlusView { @@ -46,68 +49,67 @@ class PlusActivity : QkThemedActivity(), PlusView { @Inject lateinit var upgradeButtonExperiment: UpgradeButtonExperiment @Inject lateinit var viewModelFactory: ViewModelProvider.Factory - private val binding by viewBinding(QksmsPlusActivityBinding::inflate) private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[PlusViewModel::class.java] } - override val upgradeIntent by lazy { binding.upgrade.clicks() } - override val upgradeDonateIntent by lazy { binding.upgradeDonate.clicks() } - override val donateIntent by lazy { binding.donate.clicks() } - override val themeClicks by lazy { binding.themes.clicks() } - override val scheduleClicks by lazy { binding.schedule.clicks() } - override val backupClicks by lazy { binding.backup.clicks() } - override val delayedClicks by lazy { binding.delayed.clicks() } - override val nightClicks by lazy { binding.night.clicks() } + override val upgradeIntent by lazy { upgrade.clicks() } + override val upgradeDonateIntent by lazy { upgradeDonate.clicks() } + override val donateIntent by lazy { donate.clicks() } + override val themeClicks by lazy { themes.clicks() } + override val scheduleClicks by lazy { schedule.clicks() } + override val backupClicks by lazy { backup.clicks() } + override val delayedClicks by lazy { delayed.clicks() } + override val nightClicks by lazy { night.clicks() } override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.qksms_plus_activity) setTitle(R.string.title_qksms_plus) showBackButton(true) viewModel.bindView(this) - binding.free.setVisible(false) + free.setVisible(false) if (!prefs.systemFont.get()) { fontProvider.getLato { lato -> val typeface = Typeface.create(lato, Typeface.BOLD) - binding.appBarLayout.collapsingToolbar.setCollapsedTitleTypeface(typeface) - binding.appBarLayout.collapsingToolbar.setExpandedTitleTypeface(typeface) + collapsingToolbar.setCollapsedTitleTypeface(typeface) + collapsingToolbar.setExpandedTitleTypeface(typeface) } } // Make the list titles bold - binding.linearLayout.children - .mapNotNull { view -> view as? PreferenceView } - .map { preferenceView -> preferenceView.binding.titleView } + linearLayout.children + .mapNotNull { it as? PreferenceView } + .map { it.titleView } .forEach { it.setTypeface(it.typeface, Typeface.BOLD) } val textPrimary = resolveThemeColor(android.R.attr.textColorPrimary) - binding.appBarLayout.collapsingToolbar.setCollapsedTitleTextColor(textPrimary) - binding.appBarLayout.collapsingToolbar.setExpandedTitleColor(textPrimary) + collapsingToolbar.setCollapsedTitleTextColor(textPrimary) + collapsingToolbar.setExpandedTitleColor(textPrimary) val theme = colors.theme().theme - binding.donate.setBackgroundTint(theme) - binding.upgrade.setBackgroundTint(theme) - binding.thanksIcon.setTint(theme) + donate.setBackgroundTint(theme) + upgrade.setBackgroundTint(theme) + thanksIcon.setTint(theme) } override fun render(state: PlusState) { - binding.description.text = getString(R.string.qksms_plus_description_summary, state.upgradePrice) - binding.upgrade.text = getString(upgradeButtonExperiment.variant, state.upgradePrice, state.currency) - binding.upgradeDonate.text = getString(R.string.qksms_plus_upgrade_donate, state.upgradeDonatePrice, state.currency) + description.text = getString(R.string.qksms_plus_description_summary, state.upgradePrice) + upgrade.text = getString(upgradeButtonExperiment.variant, state.upgradePrice, state.currency) + upgradeDonate.text = getString(R.string.qksms_plus_upgrade_donate, state.upgradeDonatePrice, state.currency) val fdroid = BuildConfig.FLAVOR == "noAnalytics" - binding.free.setVisible(fdroid) - binding.toUpgrade.setVisible(!fdroid && !state.upgraded) - binding.upgraded.setVisible(!fdroid && state.upgraded) + free.setVisible(fdroid) + toUpgrade.setVisible(!fdroid && !state.upgraded) + upgraded.setVisible(!fdroid && state.upgraded) - binding.themes.isEnabled = state.upgraded - binding.schedule.isEnabled = state.upgraded - binding.backup.isEnabled = state.upgraded - binding.delayed.isEnabled = state.upgraded - binding.night.isEnabled = state.upgraded + themes.isEnabled = state.upgraded + schedule.isEnabled = state.upgraded + backup.isEnabled = state.upgraded + delayed.isEnabled = state.upgraded + night.isEnabled = state.upgraded } override fun initiatePurchaseFlow(billingManager: BillingManager, sku: String) { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/qkreply/QkReplyActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/qkreply/QkReplyActivity.kt index c7237397c..392196d41 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/qkreply/QkReplyActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/qkreply/QkReplyActivity.kt @@ -36,12 +36,11 @@ import com.moez.QKSMS.common.util.extensions.autoScrollToStart import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.QkreplyActivityBinding import com.moez.QKSMS.feature.compose.MessagesAdapter import dagger.android.AndroidInjection import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.qkreply_activity.* import javax.inject.Inject class QkReplyActivity : QkThemedActivity(), QkReplyView { @@ -50,11 +49,10 @@ class QkReplyActivity : QkThemedActivity(), QkReplyView { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory override val menuItemIntent: Subject = PublishSubject.create() - override val textChangedIntent by lazy { binding.message.textChanges() } - override val changeSimIntent by lazy { binding.sim.clicks() } - override val sendIntent by lazy { binding.send.clicks() } + override val textChangedIntent by lazy { message.textChanges() } + override val changeSimIntent by lazy { sim.clicks() } + override val sendIntent by lazy { send.clicks() } - private val binding by viewBinding(QkreplyActivityBinding::inflate) private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[QkReplyViewModel::class.java] } override fun onCreate(savedInstanceState: Bundle?) { @@ -63,27 +61,27 @@ class QkReplyActivity : QkThemedActivity(), QkReplyView { super.onCreate(savedInstanceState) setFinishOnTouchOutside(prefs.qkreplyTapDismiss.get()) - setContentView(binding.root) + setContentView(R.layout.qkreply_activity) window.setBackgroundDrawable(null) window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) viewModel.bindView(this) - binding.toolbar.clipToOutline = true + toolbar.clipToOutline = true - binding.messages.adapter = adapter - binding.messages.adapter?.autoScrollToStart(binding.messages) - binding.messages.adapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { - override fun onChanged() = binding.messages.scrollToPosition(adapter.itemCount - 1) + messages.adapter = adapter + messages.adapter?.autoScrollToStart(messages) + messages.adapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { + override fun onChanged() = messages.scrollToPosition(adapter.itemCount - 1) }) // These theme attributes don't apply themselves on API 21 if (Build.VERSION.SDK_INT <= 22) { - binding.toolbar.setBackgroundTint(resolveThemeColor(R.attr.colorPrimary)) - binding.background.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) - binding.messageBackground.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) - binding.composeBackgroundGradient.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) - binding.composeBackgroundSolid.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) + toolbar.setBackgroundTint(resolveThemeColor(R.attr.colorPrimary)) + background.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) + messageBackground.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) + composeBackgroundGradient.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) + composeBackgroundSolid.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) } } @@ -96,24 +94,24 @@ class QkReplyActivity : QkThemedActivity(), QkReplyView { title = state.title - binding.toolbar.menu.findItem(R.id.expand)?.isVisible = !state.expanded - binding.toolbar.menu.findItem(R.id.collapse)?.isVisible = state.expanded + toolbar.menu.findItem(R.id.expand)?.isVisible = !state.expanded + toolbar.menu.findItem(R.id.collapse)?.isVisible = state.expanded adapter.data = state.data - binding.counter.text = state.remaining - binding.counter.setVisible(binding.counter.text.isNotBlank()) + counter.text = state.remaining + counter.setVisible(counter.text.isNotBlank()) - binding.sim.setVisible(state.subscription != null) - binding.sim.contentDescription = getString(R.string.compose_sim_cd, state.subscription?.displayName) - binding.simIndex.text = "${state.subscription?.simSlotIndex?.plus(1)}" + sim.setVisible(state.subscription != null) + sim.contentDescription = getString(R.string.compose_sim_cd, state.subscription?.displayName) + simIndex.text = "${state.subscription?.simSlotIndex?.plus(1)}" - binding.send.isEnabled = state.canSend - binding.send.imageAlpha = if (state.canSend) 255 else 128 + send.isEnabled = state.canSend + send.imageAlpha = if (state.canSend) 255 else 128 } override fun setDraft(draft: String) { - binding.message.setText(draft) + message.setText(draft) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledActivity.kt index 669d8f9c5..9bcc3af5f 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledActivity.kt @@ -30,9 +30,9 @@ import com.moez.QKSMS.common.base.QkThemedActivity import com.moez.QKSMS.common.util.FontProvider import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.ScheduledActivityBinding import dagger.android.AndroidInjection +import kotlinx.android.synthetic.main.collapsing_toolbar.* +import kotlinx.android.synthetic.main.scheduled_activity.* import javax.inject.Inject @@ -45,16 +45,15 @@ class ScheduledActivity : QkThemedActivity(), ScheduledView { override val messageClickIntent by lazy { messageAdapter.clicks } override val messageMenuIntent by lazy { dialog.adapter.menuItemClicks } - override val composeIntent by lazy { binding.compose.clicks() } - override val upgradeIntent by lazy { binding.upgrade.clicks() } + override val composeIntent by lazy { compose.clicks() } + override val upgradeIntent by lazy { upgrade.clicks() } - private val binding by viewBinding(ScheduledActivityBinding::inflate) private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[ScheduledViewModel::class.java] } override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.scheduled_activity) setTitle(R.string.scheduled_title) showBackButton(true) viewModel.bindView(this) @@ -62,33 +61,33 @@ class ScheduledActivity : QkThemedActivity(), ScheduledView { if (!prefs.systemFont.get()) { fontProvider.getLato { lato -> val typeface = Typeface.create(lato, Typeface.BOLD) - binding.appBarLayout.collapsingToolbar.setCollapsedTitleTypeface(typeface) - binding.appBarLayout.collapsingToolbar.setExpandedTitleTypeface(typeface) + collapsingToolbar.setCollapsedTitleTypeface(typeface) + collapsingToolbar.setExpandedTitleTypeface(typeface) } } dialog.title = getString(R.string.scheduled_options_title) dialog.adapter.setData(R.array.scheduled_options) - messageAdapter.emptyView = binding.empty - binding.messages.adapter = messageAdapter + messageAdapter.emptyView = empty + messages.adapter = messageAdapter colors.theme().let { theme -> - binding.sampleMessage.setBackgroundTint(theme.theme) - binding.sampleMessage.setTextColor(theme.textPrimary) - binding.compose.setTint(theme.textPrimary) - binding.compose.setBackgroundTint(theme.theme) - binding.upgrade.setBackgroundTint(theme.theme) - binding.upgradeIcon.setTint(theme.textPrimary) - binding.upgradeLabel.setTextColor(theme.textPrimary) + sampleMessage.setBackgroundTint(theme.theme) + sampleMessage.setTextColor(theme.textPrimary) + compose.setTint(theme.textPrimary) + compose.setBackgroundTint(theme.theme) + upgrade.setBackgroundTint(theme.theme) + upgradeIcon.setTint(theme.textPrimary) + upgradeLabel.setTextColor(theme.textPrimary) } } override fun render(state: ScheduledState) { messageAdapter.updateData(state.scheduledMessages) - binding.compose.isVisible = state.upgraded - binding.upgrade.isVisible = !state.upgraded + compose.isVisible = state.upgraded + upgrade.isVisible = !state.upgraded } override fun showMessageOptions() { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAdapter.kt index 2a66db1bb..23c09227c 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAdapter.kt @@ -20,13 +20,14 @@ package com.moez.QKSMS.feature.scheduled import android.content.Context import android.net.Uri +import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkRealmAdapter import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.DateFormatter -import com.moez.QKSMS.databinding.ScheduledMessageListItemBinding import com.moez.QKSMS.model.Contact import com.moez.QKSMS.model.Recipient import com.moez.QKSMS.model.ScheduledMessage @@ -34,6 +35,8 @@ import com.moez.QKSMS.repository.ContactRepository import com.moez.QKSMS.util.PhoneNumberUtils import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.scheduled_message_list_item.* +import kotlinx.android.synthetic.main.scheduled_message_list_item.view.* import javax.inject.Inject class ScheduledMessageAdapter @Inject constructor( @@ -41,7 +44,7 @@ class ScheduledMessageAdapter @Inject constructor( private val contactRepo: ContactRepository, private val dateFormatter: DateFormatter, private val phoneNumberUtils: PhoneNumberUtils -) : QkRealmAdapter() { +) : QkRealmAdapter() { private val contacts by lazy { contactRepo.getContacts() } private val contactCache = ContactCache() @@ -49,34 +52,36 @@ class ScheduledMessageAdapter @Inject constructor( val clicks: Subject = PublishSubject.create() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, ScheduledMessageListItemBinding::inflate).apply { - binding.attachments.adapter = ScheduledMessageAttachmentAdapter(context) - binding.attachments.setRecycledViewPool(imagesViewPool) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.scheduled_message_list_item, parent, false) - binding.root.setOnClickListener { + view.attachments.adapter = ScheduledMessageAttachmentAdapter(context) + view.attachments.setRecycledViewPool(imagesViewPool) + + return QkViewHolder(view).apply { + view.setOnClickListener { val message = getItem(adapterPosition) ?: return@setOnClickListener clicks.onNext(message.id) } } } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val message = getItem(position) ?: return // GroupAvatarView only accepts recipients, so map the phone numbers to recipients - holder.binding.avatars.recipients = message.recipients.map { address -> Recipient(address = address) } + holder.avatars.recipients = message.recipients.map { address -> Recipient(address = address) } - holder.binding.recipients.text = message.recipients.joinToString(",") { address -> + holder.recipients.text = message.recipients.joinToString(",") { address -> contactCache[address]?.name?.takeIf { it.isNotBlank() } ?: address } - holder.binding.date.text = dateFormatter.getScheduledTimestamp(message.date) - holder.binding.body.text = message.body + holder.date.text = dateFormatter.getScheduledTimestamp(message.date) + holder.body.text = message.body - val adapter = holder.binding.attachments.adapter as ScheduledMessageAttachmentAdapter + val adapter = holder.attachments.adapter as ScheduledMessageAttachmentAdapter adapter.data = message.attachments.map(Uri::parse) - holder.binding.attachments.isVisible = message.attachments.isNotEmpty() + holder.attachments.isVisible = message.attachments.isNotEmpty() } /** diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAttachmentAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAttachmentAdapter.kt index 80b7b9a4b..558c8af7a 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAttachmentAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAttachmentAdapter.kt @@ -20,27 +20,31 @@ package com.moez.QKSMS.feature.scheduled import android.content.Context import android.net.Uri +import android.view.LayoutInflater import android.view.ViewGroup +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter import com.moez.QKSMS.common.base.QkViewHolder -import com.moez.QKSMS.databinding.ScheduledMessageImageListItemBinding import com.moez.QKSMS.util.GlideApp +import kotlinx.android.synthetic.main.attachment_image_list_item.view.* +import kotlinx.android.synthetic.main.scheduled_message_image_list_item.* import javax.inject.Inject class ScheduledMessageAttachmentAdapter @Inject constructor( private val context: Context -) : QkAdapter() { +) : QkAdapter() { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, ScheduledMessageImageListItemBinding::inflate).apply { - binding.thumbnail.clipToOutline = true - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.scheduled_message_image_list_item, parent, false) + view.thumbnail.clipToOutline = true + + return QkViewHolder(view) } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val attachment = getItem(position) - GlideApp.with(context).load(attachment).into(holder.binding.thumbnail) + GlideApp.with(context).load(attachment).into(holder.thumbnail) } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsActivity.kt index 95276b1b5..0d2bd59ee 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsActivity.kt @@ -22,22 +22,21 @@ import android.os.Bundle import com.bluelinelabs.conductor.Conductor import com.bluelinelabs.conductor.Router import com.bluelinelabs.conductor.RouterTransaction +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkThemedActivity -import com.moez.QKSMS.common.util.extensions.viewBinding -import com.moez.QKSMS.databinding.ContainerActivityBinding import dagger.android.AndroidInjection +import kotlinx.android.synthetic.main.container_activity.* class SettingsActivity : QkThemedActivity() { - private val binding by viewBinding(ContainerActivityBinding::inflate) private lateinit var router: Router override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) - setContentView(binding.root) + setContentView(R.layout.container_activity) - router = Conductor.attachRouter(this, binding.container, savedInstanceState) + router = Conductor.attachRouter(this, container, savedInstanceState) if (!router.hasRootController()) { router.setRoot(RouterTransaction.with(SettingsController())) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsController.kt index 5159f07e1..f09adc3e9 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsController.kt @@ -43,7 +43,6 @@ import com.moez.QKSMS.common.util.extensions.setVisible import com.moez.QKSMS.common.widget.PreferenceView import com.moez.QKSMS.common.widget.QkSwitch import com.moez.QKSMS.common.widget.TextInputDialog -import com.moez.QKSMS.databinding.SettingsControllerBinding import com.moez.QKSMS.feature.settings.about.AboutController import com.moez.QKSMS.feature.settings.autodelete.AutoDeleteDialog import com.moez.QKSMS.feature.settings.swipe.SwipeActionsController @@ -59,12 +58,14 @@ import io.reactivex.subjects.Subject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withContext +import kotlinx.android.synthetic.main.settings_controller.* +import kotlinx.android.synthetic.main.settings_controller.view.* +import kotlinx.android.synthetic.main.settings_switch_widget.view.* +import kotlinx.android.synthetic.main.settings_theme_widget.* import javax.inject.Inject import kotlin.coroutines.resume -class SettingsController : QkController( - SettingsControllerBinding::inflate -), SettingsView { +class SettingsController : QkController(), SettingsView { @Inject lateinit var context: Context @Inject lateinit var colors: Colors @@ -88,11 +89,12 @@ class SettingsController : QkController = PublishSubject.create() private val autoDeleteSubject: Subject = PublishSubject.create() - private val progressAnimator by lazy { ObjectAnimator.ofInt(binding.syncingProgress, "progress", 0, 0) } + private val progressAnimator by lazy { ObjectAnimator.ofInt(syncingProgress, "progress", 0, 0) } init { appComponent.inject(this) retainViewMode = RetainViewMode.RETAIN_DETACH + layoutRes = R.layout.settings_controller colors.themeObservable() .autoDisposable(scope()) @@ -100,7 +102,7 @@ class SettingsController : QkController= 29) { true -> nightModeDialog.adapter.setData(R.array.night_modes) @@ -112,7 +114,7 @@ class SettingsController : QkController = (0 until binding.preferences.childCount) - .map { index -> binding.preferences.getChildAt(index) } + override fun preferenceClicks(): Observable = (0 until preferences.childCount) + .map { index -> preferences.getChildAt(index) } .mapNotNull { view -> view as? PreferenceView } .map { preference -> preference.clicks().map { preference } } .let { preferences -> Observable.merge(preferences) } - override fun aboutLongClicks(): Observable<*> = binding.about.longClicks() + override fun aboutLongClicks(): Observable<*> = about.longClicks() override fun viewQksmsPlusClicks(): Observable<*> = viewQksmsPlusSubject @@ -149,64 +151,63 @@ class SettingsController : QkController = mmsSizeDialog.adapter.menuItemClicks override fun render(state: SettingsState) { - binding.theme.widget().setBackgroundTint(state.theme) - binding.night.summary = state.nightModeSummary + themePreview.setBackgroundTint(state.theme) + night.summary = state.nightModeSummary nightModeDialog.adapter.selectedItem = state.nightModeId - binding.nightStart.setVisible(state.nightModeId == Preferences.NIGHT_MODE_AUTO) - binding.nightStart.summary = state.nightStart - binding.nightEnd.setVisible(state.nightModeId == Preferences.NIGHT_MODE_AUTO) - binding.nightEnd.summary = state.nightEnd + nightStart.setVisible(state.nightModeId == Preferences.NIGHT_MODE_AUTO) + nightStart.summary = state.nightStart + nightEnd.setVisible(state.nightModeId == Preferences.NIGHT_MODE_AUTO) + nightEnd.summary = state.nightEnd - binding.black.setVisible(state.nightModeId != Preferences.NIGHT_MODE_OFF) - binding.black.widget().isChecked = state.black + black.setVisible(state.nightModeId != Preferences.NIGHT_MODE_OFF) + black.checkbox.isChecked = state.black - binding.autoEmoji.widget().isChecked = state.autoEmojiEnabled + autoEmoji.checkbox.isChecked = state.autoEmojiEnabled - binding.delayed.summary = state.sendDelaySummary + delayed.summary = state.sendDelaySummary sendDelayDialog.adapter.selectedItem = state.sendDelayId - binding.delivery.widget().isChecked = state.deliveryEnabled + delivery.checkbox.isChecked = state.deliveryEnabled - binding.signature.summary = state.signature.takeIf { it.isNotBlank() } + signature.summary = state.signature.takeIf { it.isNotBlank() } ?: context.getString(R.string.settings_signature_summary) - binding.textSize.summary = state.textSizeSummary + textSize.summary = state.textSizeSummary textSizeDialog.adapter.selectedItem = state.textSizeId - binding.autoColor.widget().isChecked = state.autoColor + autoColor.checkbox.isChecked = state.autoColor - binding.systemFont.widget().isChecked = state.systemFontEnabled + systemFont.checkbox.isChecked = state.systemFontEnabled - binding.unicode.widget().isChecked = state.stripUnicodeEnabled - binding.mobileOnly.widget().isChecked = state.mobileOnly + unicode.checkbox.isChecked = state.stripUnicodeEnabled + mobileOnly.checkbox.isChecked = state.mobileOnly - binding.autoDelete.summary = when (state.autoDelete) { + autoDelete.summary = when (state.autoDelete) { 0 -> context.getString(R.string.settings_auto_delete_never) else -> context.resources.getQuantityString( R.plurals.settings_auto_delete_summary, state.autoDelete, state.autoDelete) } - binding.longAsMms.widget().isChecked = state.longAsMms + longAsMms.checkbox.isChecked = state.longAsMms - binding.mmsSize.summary = state.maxMmsSizeSummary + mmsSize.summary = state.maxMmsSizeSummary mmsSizeDialog.adapter.selectedItem = state.maxMmsSizeId when (state.syncProgress) { - is SyncRepository.SyncProgress.Idle -> binding.syncingProgress.isVisible = false + is SyncRepository.SyncProgress.Idle -> syncingProgress.isVisible = false is SyncRepository.SyncProgress.Running -> { - binding.syncingProgress.isVisible = true - binding.syncingProgress.max = state.syncProgress.max - progressAnimator.apply { setIntValues(binding.syncingProgress.progress, state.syncProgress.progress) } - .start() - binding.syncingProgress.isIndeterminate = state.syncProgress.indeterminate + syncingProgress.isVisible = true + syncingProgress.max = state.syncProgress.max + progressAnimator.apply { setIntValues(syncingProgress.progress, state.syncProgress.progress) }.start() + syncingProgress.isIndeterminate = state.syncProgress.indeterminate } } } override fun showQksmsPlusSnackbar() { view?.run { - Snackbar.make(binding.root, R.string.toast_qksms_plus, Snackbar.LENGTH_LONG).run { + Snackbar.make(contentView, R.string.toast_qksms_plus, Snackbar.LENGTH_LONG).run { setAction(R.string.button_more) { viewQksmsPlusSubject.onNext(Unit) } setActionTextColor(colors.theme().theme) show() diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/settings/about/AboutController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/settings/about/AboutController.kt index ec81ea094..7385a29c9 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/settings/about/AboutController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/settings/about/AboutController.kt @@ -24,23 +24,22 @@ import com.moez.QKSMS.BuildConfig import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkController import com.moez.QKSMS.common.widget.PreferenceView -import com.moez.QKSMS.databinding.AboutControllerBinding import com.moez.QKSMS.injection.appComponent import io.reactivex.Observable +import kotlinx.android.synthetic.main.about_controller.* import javax.inject.Inject -class AboutController : QkController( - AboutControllerBinding::inflate -), AboutView { +class AboutController : QkController(), AboutView { @Inject override lateinit var presenter: AboutPresenter init { appComponent.inject(this) + layoutRes = R.layout.about_controller } override fun onViewCreated() { - binding.version.summary = BuildConfig.VERSION_NAME + version.summary = BuildConfig.VERSION_NAME } override fun onAttach(view: View) { @@ -50,8 +49,8 @@ class AboutController : QkController = (0 until binding.preferences.childCount) - .map { index -> binding.preferences.getChildAt(index) } + override fun preferenceClicks(): Observable = (0 until preferences.childCount) + .map { index -> preferences.getChildAt(index) } .mapNotNull { view -> view as? PreferenceView } .map { preference -> preference.clicks().map { preference } } .let { preferences -> Observable.merge(preferences) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/settings/autodelete/AutoDeleteDialog.kt b/presentation/src/main/java/com/moez/QKSMS/feature/settings/autodelete/AutoDeleteDialog.kt index 260b0f4fe..8f55c1413 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/settings/autodelete/AutoDeleteDialog.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/settings/autodelete/AutoDeleteDialog.kt @@ -20,29 +20,30 @@ package com.moez.QKSMS.feature.settings.autodelete import android.app.Activity import android.content.DialogInterface +import android.view.LayoutInflater import androidx.appcompat.app.AlertDialog import com.moez.QKSMS.R -import com.moez.QKSMS.databinding.SettingsAutoDeleteDialogBinding +import kotlinx.android.synthetic.main.settings_auto_delete_dialog.view.* class AutoDeleteDialog(context: Activity, listener: (Int) -> Unit) : AlertDialog(context) { - private val binding = SettingsAutoDeleteDialogBinding.inflate(context.layoutInflater) + private val layout = LayoutInflater.from(context).inflate(R.layout.settings_auto_delete_dialog, null) init { - setView(binding.root) + setView(layout) setTitle(R.string.settings_auto_delete) setMessage(context.getString(R.string.settings_auto_delete_dialog_message)) setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(R.string.button_cancel)) { _, _ -> } setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.settings_auto_delete_never)) { _, _ -> listener(0) } setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.button_save)) { _, _ -> - listener(binding.field.text.toString().toIntOrNull() ?: 0) + listener(layout.field.text.toString().toIntOrNull() ?: 0) } } fun setExpiry(days: Int): AutoDeleteDialog { when (days) { - 0 -> binding.field.text = null - else -> binding.field.setText(days.toString()) + 0 -> layout.field.text = null + else -> layout.field.setText(days.toString()) } return this } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/settings/swipe/SwipeActionsController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/settings/swipe/SwipeActionsController.kt index 2d53d7c30..8121ad443 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/settings/swipe/SwipeActionsController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/settings/swipe/SwipeActionsController.kt @@ -28,20 +28,16 @@ import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.animateLayoutChanges import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.databinding.SwipeActionsControllerBinding import com.moez.QKSMS.injection.appComponent -import com.uber.autodispose.android.autoDisposable -import com.uber.autodispose.android.lifecycle.autoDisposable import com.uber.autodispose.android.lifecycle.scope import com.uber.autodispose.autoDisposable import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.swipe_actions_controller.* import javax.inject.Inject -class SwipeActionsController : - QkController( - SwipeActionsControllerBinding::inflate), SwipeActionsView { +class SwipeActionsController : QkController(), SwipeActionsView { @Inject override lateinit var presenter: SwipeActionsPresenter @Inject lateinit var actionsDialog: QkDialog @@ -54,24 +50,25 @@ class SwipeActionsController : init { appComponent.inject(this) + layoutRes = R.layout.swipe_actions_controller actionsDialog.adapter.setData(R.array.settings_swipe_actions) } override fun onViewCreated() { colors.theme().let { theme -> - binding.rightIcon.setBackgroundTint(theme.theme) - binding.rightIcon.setTint(theme.textPrimary) - binding.leftIcon.setBackgroundTint(theme.theme) - binding.leftIcon.setTint(theme.textPrimary) + rightIcon.setBackgroundTint(theme.theme) + rightIcon.setTint(theme.textPrimary) + leftIcon.setBackgroundTint(theme.theme) + leftIcon.setTint(theme.textPrimary) } - binding.right.postDelayed({ binding.right.animateLayoutChanges = true }, 100) - binding.left.postDelayed({ binding.left.animateLayoutChanges = true }, 100) + right.postDelayed({ right?.animateLayoutChanges = true }, 100) + left.postDelayed({ left?.animateLayoutChanges = true }, 100) Observable.merge( - binding.right.clicks().map { SwipeActionsView.Action.RIGHT }, - binding.left.clicks().map { SwipeActionsView.Action.LEFT }) + right.clicks().map { SwipeActionsView.Action.RIGHT }, + left.clicks().map { SwipeActionsView.Action.LEFT }) .autoDisposable(scope()) .subscribe(actionClicks) } @@ -93,13 +90,13 @@ class SwipeActionsController : } override fun render(state: SwipeActionsState) { - binding.rightIcon.isVisible = state.rightIcon != 0 - binding.rightIcon.setImageResource(state.rightIcon) - binding.rightLabel.text = state.rightLabel + rightIcon.isVisible = state.rightIcon != 0 + rightIcon.setImageResource(state.rightIcon) + rightLabel.text = state.rightLabel - binding.leftIcon.isVisible = state.leftIcon != 0 - binding.leftIcon.setImageResource(state.leftIcon) - binding.leftLabel.text = state.leftLabel + leftIcon.isVisible = state.leftIcon != 0 + leftIcon.setImageResource(state.leftIcon) + leftLabel.text = state.leftLabel } } \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/HSVPickerView.kt b/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/HSVPickerView.kt index fdc0af525..155224433 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/HSVPickerView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/HSVPickerView.kt @@ -23,14 +23,15 @@ import android.graphics.Color import android.graphics.drawable.GradientDrawable import android.util.AttributeSet import android.view.MotionEvent +import android.view.View import androidx.constraintlayout.widget.ConstraintLayout +import com.moez.QKSMS.R import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint -import com.moez.QKSMS.common.util.extensions.viewBinding import com.moez.QKSMS.common.util.extensions.within -import com.moez.QKSMS.databinding.HsvPickerViewBinding import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.hsv_picker_view.view.* class HSVPickerView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null @@ -38,8 +39,6 @@ class HSVPickerView @JvmOverloads constructor( val selectedColor: Subject = BehaviorSubject.create() - private val binding = viewBinding(HsvPickerViewBinding::inflate) - private val hues = arrayOf(0xFFFF0000, 0xFFFFFF00, 0xFF00FF00, 0xFF00FFFF, 0xFF0000FF, 0xFFFF00FF, 0xFFFF0000) .map { it.toInt() }.toIntArray() @@ -53,10 +52,12 @@ class HSVPickerView @JvmOverloads constructor( } init { + View.inflate(context, R.layout.hsv_picker_view, this) + var swatchX = 0f var swatchY = 0f - binding.saturation.setOnTouchListener { _, event -> + saturation.setOnTouchListener { _, event -> setupBounds() when (event.action) { MotionEvent.ACTION_DOWN -> { @@ -67,8 +68,8 @@ class HSVPickerView @JvmOverloads constructor( MotionEvent.ACTION_MOVE -> { // Calculate the new x/y position - binding.swatch.x = (event.rawX + swatchX + min).within(min, max) - binding.swatch.y = (event.rawY + swatchY + min).within(min, max) + swatch.x = (event.rawX + swatchX + min).within(min, max) + swatch.y = (event.rawY + swatchY + min).within(min, max) updateSelectedColor() } @@ -84,7 +85,7 @@ class HSVPickerView @JvmOverloads constructor( var hueThumbX = 0f - binding.hueGroup.setOnTouchListener { _, event -> + hueGroup.setOnTouchListener { _, event -> setupBounds() when (event.action) { MotionEvent.ACTION_DOWN -> { @@ -95,8 +96,8 @@ class HSVPickerView @JvmOverloads constructor( MotionEvent.ACTION_MOVE -> { val x = (event.rawX + hueThumbX + min).within(min, max) - binding.hueThumb.x = x - hue = (binding.hueThumb.x - min) / (max - min) * 360 + hueThumb.x = x + hue = (hueThumb.x - min) / (max - min) * 360 updateSelectedColor() } @@ -110,14 +111,14 @@ class HSVPickerView @JvmOverloads constructor( true } - binding.hueTrack.clipToOutline = true - binding.hueTrack.setImageDrawable(GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, hues)) + hueTrack.clipToOutline = true + hueTrack.setImageDrawable(GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, hues)) } private fun setupBounds() { if (min == 0f || max == 0f) { - min = binding.saturation.x - binding.swatch.width / 2 - max = min + binding.saturation.width + min = saturation.x - swatch.width / 2 + max = min + saturation.width } } @@ -125,10 +126,10 @@ class HSVPickerView @JvmOverloads constructor( setupBounds() val range = max - min - val hsv = floatArrayOf(hue, (binding.swatch.x - min) / range, 1 - (binding.swatch.y - min) / range) + val hsv = floatArrayOf(hue, (swatch.x - min) / range, 1 - (swatch.y - min) / range) val color = Color.HSVToColor(hsv) - binding.swatch.setTint(color) + swatch.setTint(color) selectedColor.onNext(color) } @@ -144,9 +145,9 @@ class HSVPickerView @JvmOverloads constructor( setupBounds() val range = max - min - binding.hueThumb.x = range * hsv[0] / 360 + min - binding.swatch.x = range * hsv[1] + min - binding.swatch.y = range * (1 - hsv[2]) + min + hueThumb.x = range * hsv[0] / 360 + min + swatch.x = range * hsv[1] + min + swatch.y = range * (1 - hsv[2]) + min updateSelectedColor() } @@ -155,7 +156,7 @@ class HSVPickerView @JvmOverloads constructor( private fun updateHue() { val hsv = floatArrayOf(hue, 1f, 1f) val tint = Color.HSVToColor(hsv) - binding.saturation.setBackgroundTint(tint) + saturation.setBackgroundTint(tint) } } \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/ThemeAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/ThemeAdapter.kt index 3993551b4..cf99614e7 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/ThemeAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/ThemeAdapter.kt @@ -25,6 +25,7 @@ import android.view.ViewGroup import com.google.android.flexbox.FlexDirection import com.google.android.flexbox.FlexWrap import com.google.android.flexbox.FlexboxLayout +import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkAdapter import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.Colors @@ -32,16 +33,17 @@ import com.moez.QKSMS.common.util.extensions.dpToPx import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.databinding.ThemeListItemBinding -import com.moez.QKSMS.databinding.ThemePaletteListItemBinding import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.theme_list_item.view.* +import kotlinx.android.synthetic.main.theme_palette_list_item.* +import kotlinx.android.synthetic.main.theme_palette_list_item.view.* import javax.inject.Inject class ThemeAdapter @Inject constructor( private val context: Context, private val colors: Colors -) : QkAdapter, ThemePaletteListItemBinding>() { +) : QkAdapter>() { val colorSelected: Subject = PublishSubject.create() @@ -59,14 +61,15 @@ class ThemeAdapter @Inject constructor( private var iconTint = 0 - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - return QkViewHolder(parent, ThemePaletteListItemBinding::inflate).apply { - binding.palette.flexWrap = FlexWrap.WRAP - binding.palette.flexDirection = FlexDirection.ROW - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.theme_palette_list_item, parent, false) + view.palette.flexWrap = FlexWrap.WRAP + view.palette.flexDirection = FlexDirection.ROW + + return QkViewHolder(view) } - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { val palette = getItem(position) val screenWidth = Resources.getSystem().displayMetrics.widthPixels @@ -78,15 +81,15 @@ class ThemeAdapter @Inject constructor( } val swatchPadding = (screenWidth - size * 5) / 12 - holder.binding.palette.removeAllViews() - holder.binding.palette.setPadding(swatchPadding, swatchPadding, swatchPadding, swatchPadding) + holder.palette.removeAllViews() + holder.palette.setPadding(swatchPadding, swatchPadding, swatchPadding, swatchPadding) (palette.subList(0, 5) + palette.subList(5, 10).reversed()) .mapIndexed { index, color -> - ThemeListItemBinding.inflate(LayoutInflater.from(context), holder.binding.palette, false).apply { + LayoutInflater.from(context).inflate(R.layout.theme_list_item, holder.palette, false).apply { // Send clicks to the selected subject - root.setOnClickListener { colorSelected.onNext(color) } + setOnClickListener { colorSelected.onNext(color) } // Apply the color to the view theme.setBackgroundTint(color) @@ -96,15 +99,15 @@ class ThemeAdapter @Inject constructor( check.setTint(iconTint) // Update the size so that the spacing is perfectly even - root.layoutParams = (root.layoutParams as FlexboxLayout.LayoutParams).apply { + layoutParams = (layoutParams as FlexboxLayout.LayoutParams).apply { height = size width = size isWrapBefore = index % 5 == 0 setMargins(swatchPadding, swatchPadding, swatchPadding, swatchPadding) } - }.root + } } - .forEach { theme -> holder.binding.palette.addView(theme) } + .forEach { theme -> holder.palette.addView(theme) } } } \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/ThemePickerController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/ThemePickerController.kt index 7c6301406..ae4dc56f2 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/ThemePickerController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/themepicker/ThemePickerController.kt @@ -29,19 +29,18 @@ import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.dpToPx import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setVisible -import com.moez.QKSMS.databinding.ThemePickerControllerBinding import com.moez.QKSMS.feature.themepicker.injection.ThemePickerModule import com.moez.QKSMS.injection.appComponent import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.theme_picker_controller.* +import kotlinx.android.synthetic.main.theme_picker_hsv.* import javax.inject.Inject class ThemePickerController( val recipientId: Long = 0L -) : QkController( - ThemePickerControllerBinding::inflate -), ThemePickerView { +) : QkController(), ThemePickerView { @Inject override lateinit var presenter: ThemePickerPresenter @@ -57,17 +56,19 @@ class ThemePickerController( .themePickerModule(ThemePickerModule(this)) .build() .inject(this) + + layoutRes = R.layout.theme_picker_controller } override fun onViewCreated() { - binding.pager.offscreenPageLimit = 1 - binding.pager.adapter = themePagerAdapter - binding.tabs.pager = binding.pager + pager.offscreenPageLimit = 1 + pager.adapter = themePagerAdapter + tabs.pager = pager themeAdapter.data = colors.materialColors - binding.materialColors.layoutManager = LinearLayoutManager(activity) - binding.materialColors.adapter = themeAdapter + materialColors.layoutManager = LinearLayoutManager(activity) + materialColors.adapter = themeAdapter } override fun onAttach(view: View) { @@ -85,13 +86,12 @@ class ThemePickerController( super.onDetach(view) themedActivity?.supportActionBar?.let { toolbar -> - ObjectAnimator.ofFloat(toolbar, "elevation", toolbar.elevation, 8.dpToPx(toolbar.themedContext).toFloat()) - .start() + ObjectAnimator.ofFloat(toolbar, "elevation", toolbar.elevation, 8.dpToPx(toolbar.themedContext).toFloat()).start() } } override fun showQksmsPlusSnackbar() { - Snackbar.make(binding.contentView, R.string.toast_qksms_plus, Snackbar.LENGTH_LONG).run { + Snackbar.make(contentView, R.string.toast_qksms_plus, Snackbar.LENGTH_LONG).run { setAction(R.string.button_more) { viewQksmsPlusSubject.onNext(Unit) } setActionTextColor(colors.theme().theme) show() @@ -100,26 +100,26 @@ class ThemePickerController( override fun themeSelected(): Observable = themeAdapter.colorSelected - override fun hsvThemeSelected(): Observable = binding.hsvPicker.picker.selectedColor + override fun hsvThemeSelected(): Observable = picker.selectedColor - override fun clearHsvThemeClicks(): Observable<*> = binding.hsvPicker.clear.clicks() + override fun clearHsvThemeClicks(): Observable<*> = clear.clicks() - override fun applyHsvThemeClicks(): Observable<*> = binding.hsvPicker.apply.clicks() + override fun applyHsvThemeClicks(): Observable<*> = apply.clicks() override fun viewQksmsPlusClicks(): Observable<*> = viewQksmsPlusSubject override fun render(state: ThemePickerState) { - binding.tabs.setRecipientId(state.recipientId) + tabs.setRecipientId(state.recipientId) - binding.hsvPicker.hex.setText(Integer.toHexString(state.newColor).takeLast(6)) + hex.setText(Integer.toHexString(state.newColor).takeLast(6)) - binding.hsvPicker.applyGroup.setVisible(state.applyThemeVisible) - binding.hsvPicker.apply.setBackgroundTint(state.newColor) - binding.hsvPicker.apply.setTextColor(state.newTextColor) + applyGroup.setVisible(state.applyThemeVisible) + apply.setBackgroundTint(state.newColor) + apply.setTextColor(state.newTextColor) } override fun setCurrentTheme(color: Int) { - binding.hsvPicker.picker.setColor(color) + picker.setColor(color) themeAdapter.selectedColor = color } diff --git a/presentation/src/main/res/layout/collapsing_toolbar.xml b/presentation/src/main/res/layout/collapsing_toolbar.xml index 5f2ad571f..1994eb710 100644 --- a/presentation/src/main/res/layout/collapsing_toolbar.xml +++ b/presentation/src/main/res/layout/collapsing_toolbar.xml @@ -20,6 +20,7 @@ diff --git a/presentation/src/main/res/layout/contact_chip_detailed.xml b/presentation/src/main/res/layout/contact_chip_detailed.xml index 64ab9a592..786e160fd 100755 --- a/presentation/src/main/res/layout/contact_chip_detailed.xml +++ b/presentation/src/main/res/layout/contact_chip_detailed.xml @@ -17,21 +17,25 @@ ~ You should have received a copy of the GNU General Public License ~ along with QKSMS. If not, see . --> - + android:layout_margin="8dp" + android:background="@drawable/rounded_rectangle_2dp" + android:elevation="8dp" + android:gravity="center_vertical" + android:paddingStart="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + tools:backgroundTint="@color/tools_theme"> @@ -80,4 +84,4 @@ app:layout_constraintEnd_toEndOf="parent" tools:tint="@color/white" /> - \ No newline at end of file + \ No newline at end of file diff --git a/presentation/src/main/res/layout/main_activity.xml b/presentation/src/main/res/layout/main_activity.xml index 38de075e9..4b9bebf2a 100644 --- a/presentation/src/main/res/layout/main_activity.xml +++ b/presentation/src/main/res/layout/main_activity.xml @@ -121,20 +121,20 @@ android:background="?android:attr/divider" app:layout_constraintBottom_toTopOf="@id/snackbar" /> - - @@ -146,4 +146,4 @@ android:layout_height="match_parent" android:layout_gravity="start" /> - + \ No newline at end of file diff --git a/presentation/src/main/res/layout/main_permission_hint.xml b/presentation/src/main/res/layout/main_permission_hint.xml index c7e9bd540..932134456 100644 --- a/presentation/src/main/res/layout/main_permission_hint.xml +++ b/presentation/src/main/res/layout/main_permission_hint.xml @@ -24,22 +24,22 @@ android:layout_height="wrap_content"> - + \ No newline at end of file diff --git a/presentation/src/main/res/layout/main_syncing.xml b/presentation/src/main/res/layout/main_syncing.xml index 8f18bc38a..d3b17e59c 100644 --- a/presentation/src/main/res/layout/main_syncing.xml +++ b/presentation/src/main/res/layout/main_syncing.xml @@ -23,7 +23,7 @@ android:orientation="vertical"> - - - - - + - + . --> - + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:paddingStart="8dp" + android:paddingEnd="8dp"> + + + + \ No newline at end of file