From 22bed19d904385740c5230261411e468255c463c Mon Sep 17 00:00:00 2001 From: Konrad Pozniak <connyduck@users.noreply.github.com> Date: Sun, 7 Mar 2021 19:06:05 +0100 Subject: [PATCH] migrating to ViewBinding part 3: EmojiPreference (#2094) --- .../components/preference/EmojiPreference.kt | 145 ++++++++---------- .../tusky/util/EmojiCompatFont.kt | 8 +- app/src/main/res/layout/item_emoji_pref.xml | 33 ++-- 3 files changed, 83 insertions(+), 103 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/preference/EmojiPreference.kt b/app/src/main/java/com/keylesspalace/tusky/components/preference/EmojiPreference.kt index c0e538a9..2d32723f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/preference/EmojiPreference.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/preference/EmojiPreference.kt @@ -8,14 +8,23 @@ import android.os.Build import android.util.Log import android.view.LayoutInflater import android.view.View -import android.widget.* +import android.widget.RadioButton +import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.preference.Preference import androidx.preference.PreferenceManager import com.keylesspalace.tusky.R import com.keylesspalace.tusky.SplashActivity +import com.keylesspalace.tusky.databinding.DialogEmojicompatBinding +import com.keylesspalace.tusky.databinding.ItemEmojiPrefBinding import com.keylesspalace.tusky.util.EmojiCompatFont +import com.keylesspalace.tusky.util.EmojiCompatFont.Companion.BLOBMOJI import com.keylesspalace.tusky.util.EmojiCompatFont.Companion.FONTS +import com.keylesspalace.tusky.util.EmojiCompatFont.Companion.NOTOEMOJI +import com.keylesspalace.tusky.util.EmojiCompatFont.Companion.SYSTEM_DEFAULT +import com.keylesspalace.tusky.util.EmojiCompatFont.Companion.TWEMOJI +import com.keylesspalace.tusky.util.hide +import com.keylesspalace.tusky.util.show import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import okhttp3.OkHttpClient @@ -50,94 +59,85 @@ class EmojiPreference( } override fun onClick() { - val view = LayoutInflater.from(context).inflate(R.layout.dialog_emojicompat, null) - viewIds.forEachIndexed { index, viewId -> - setupItem(view.findViewById(viewId), FONTS[index]) - } + val binding = DialogEmojicompatBinding.inflate(LayoutInflater.from(context)) + + setupItem(BLOBMOJI, binding.itemBlobmoji) + setupItem(TWEMOJI, binding.itemTwemoji) + setupItem(NOTOEMOJI, binding.itemNotoemoji) + setupItem(SYSTEM_DEFAULT, binding.itemNomoji) + AlertDialog.Builder(context) - .setView(view) + .setView(binding.root) .setPositiveButton(android.R.string.ok) { _, _ -> onDialogOk() } .setNegativeButton(android.R.string.cancel, null) .show() } - private fun setupItem(container: View, font: EmojiCompatFont) { - val title: TextView = container.findViewById(R.id.emojicompat_name) - val caption: TextView = container.findViewById(R.id.emojicompat_caption) - val thumb: ImageView = container.findViewById(R.id.emojicompat_thumb) - val download: ImageButton = container.findViewById(R.id.emojicompat_download) - val cancel: ImageButton = container.findViewById(R.id.emojicompat_download_cancel) - val radio: RadioButton = container.findViewById(R.id.emojicompat_radio) - + private fun setupItem(font: EmojiCompatFont, binding: ItemEmojiPrefBinding) { // Initialize all the views - title.text = font.getDisplay(container.context) - caption.setText(font.caption) - thumb.setImageResource(font.img) + binding.emojiName.text = font.getDisplay(context) + binding.emojiCaption.setText(font.caption) + binding.emojiThumbnail.setImageResource(font.img) // There needs to be a list of all the radio buttons in order to uncheck them when one is selected - radioButtons.add(radio) - updateItem(font, container) + radioButtons.add(binding.emojiRadioButton) + updateItem(font, binding) // Set actions - download.setOnClickListener { startDownload(font, container) } - cancel.setOnClickListener { cancelDownload(font, container) } - radio.setOnClickListener { radioButton: View -> select(font, radioButton as RadioButton) } - container.setOnClickListener { containerView: View -> - select(font, containerView.findViewById(R.id.emojicompat_radio)) + binding.emojiDownload.setOnClickListener { startDownload(font, binding) } + binding.emojiDownloadCancel.setOnClickListener { cancelDownload(font, binding) } + binding.emojiRadioButton.setOnClickListener { radioButton: View -> select(font, radioButton as RadioButton) } + binding.root.setOnClickListener { + select(font, binding.emojiRadioButton) } } - private fun startDownload(font: EmojiCompatFont, container: View) { - val download: ImageButton = container.findViewById(R.id.emojicompat_download) - val caption: TextView = container.findViewById(R.id.emojicompat_caption) - val progressBar: ProgressBar = container.findViewById(R.id.emojicompat_progress) - val cancel: ImageButton = container.findViewById(R.id.emojicompat_download_cancel) - + private fun startDownload(font: EmojiCompatFont, binding: ItemEmojiPrefBinding) { // Switch to downloading style - download.visibility = View.GONE - caption.visibility = View.INVISIBLE - progressBar.visibility = View.VISIBLE - progressBar.progress = 0 - cancel.visibility = View.VISIBLE + binding.emojiDownload.hide() + binding.emojiCaption.visibility = View.INVISIBLE + binding.emojiProgress.show() + binding.emojiProgress.progress = 0 + binding.emojiDownloadCancel.show() font.downloadFontFile(context, okHttpClient) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { progress -> // The progress is returned as a float between 0 and 1, or -1 if it could not determined if (progress >= 0) { - progressBar.isIndeterminate = false - val max = progressBar.max.toFloat() + binding.emojiProgress.isIndeterminate = false + val max = binding.emojiProgress.max.toFloat() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - progressBar.setProgress((max * progress).toInt(), true) + binding.emojiProgress.setProgress((max * progress).toInt(), true) } else { - progressBar.progress = (max * progress).toInt() + binding.emojiProgress.progress = (max * progress).toInt() } } else { - progressBar.isIndeterminate = true + binding.emojiProgress.isIndeterminate = true } }, { Toast.makeText(context, R.string.download_failed, Toast.LENGTH_SHORT).show() - updateItem(font, container) + updateItem(font, binding) }, { - finishDownload(font, container) + finishDownload(font, binding) } ).also { downloadDisposables[font.id] = it } } - private fun cancelDownload(font: EmojiCompatFont, container: View) { - font.deleteDownloadedFile(container.context) + private fun cancelDownload(font: EmojiCompatFont, binding: ItemEmojiPrefBinding) { + font.deleteDownloadedFile(context) downloadDisposables[font.id]?.dispose() downloadDisposables[font.id] = null - updateItem(font, container) + updateItem(font, binding) } - private fun finishDownload(font: EmojiCompatFont, container: View) { - select(font, container.findViewById(R.id.emojicompat_radio)) - updateItem(font, container) + private fun finishDownload(font: EmojiCompatFont, binding: ItemEmojiPrefBinding) { + select(font, binding.emojiRadioButton) + updateItem(font, binding) // Set the flag to restart the app (because an update has been downloaded) if (selected === original && currentNeedsUpdate) { updated = true @@ -153,54 +153,43 @@ class EmojiPreference( */ private fun select(font: EmojiCompatFont, radio: RadioButton) { selected = font - // Uncheck all the other buttons - for (other in radioButtons) { - if (other !== radio) { - other.isChecked = false - } + radioButtons.forEach { radioButton -> + radioButton.isChecked = radioButton == radio } - radio.isChecked = true } /** * Called when a "consistent" state is reached, i.e. it's not downloading the font * * @param font The font to be displayed - * @param container The ConstraintLayout containing the item + * @param binding The ItemEmojiPrefBinding to show the item in */ - private fun updateItem(font: EmojiCompatFont, container: View) { - // Assignments - val download: ImageButton = container.findViewById(R.id.emojicompat_download) - val caption: TextView = container.findViewById(R.id.emojicompat_caption) - val progress: ProgressBar = container.findViewById(R.id.emojicompat_progress) - val cancel: ImageButton = container.findViewById(R.id.emojicompat_download_cancel) - val radio: RadioButton = container.findViewById(R.id.emojicompat_radio) - + private fun updateItem(font: EmojiCompatFont, binding: ItemEmojiPrefBinding) { // There's no download going on - progress.visibility = View.GONE - cancel.visibility = View.GONE - caption.visibility = View.VISIBLE + binding.emojiProgress.hide() + binding.emojiDownloadCancel.hide() + binding.emojiCaption.show() if (font.isDownloaded(context)) { // Make it selectable - download.visibility = View.GONE - radio.visibility = View.VISIBLE - container.isClickable = true + binding.emojiDownload.hide() + binding.emojiRadioButton.show() + binding.root.isClickable = true } else { // Make it downloadable - download.visibility = View.VISIBLE - radio.visibility = View.GONE - container.isClickable = false + binding.emojiDownload.show() + binding.emojiRadioButton.hide() + binding.root.isClickable = false } // Select it if necessary if (font === selected) { - radio.isChecked = true + binding.emojiRadioButton.isChecked = true // Update available if (!font.isDownloaded(context)) { currentNeedsUpdate = true } } else { - radio.isChecked = false + binding.emojiRadioButton.isChecked = false } } @@ -246,13 +235,5 @@ class EmojiPreference( companion object { private const val TAG = "EmojiPreference" - - // Please note that this array must sorted in the same way as the fonts. - private val viewIds = intArrayOf( - R.id.item_nomoji, - R.id.item_blobmoji, - R.id.item_twemoji, - R.id.item_notoemoji - ) } } \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/util/EmojiCompatFont.kt b/app/src/main/java/com/keylesspalace/tusky/util/EmojiCompatFont.kt index 4697a1e9..d0a0e443 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/EmojiCompatFont.kt +++ b/app/src/main/java/com/keylesspalace/tusky/util/EmojiCompatFont.kt @@ -256,27 +256,27 @@ class EmojiCompatFont( private const val CHUNK_SIZE = 4096L // The system font gets some special behavior... - private val SYSTEM_DEFAULT = EmojiCompatFont("system-default", + val SYSTEM_DEFAULT = EmojiCompatFont("system-default", "System Default", R.string.caption_systememoji, R.drawable.ic_emoji_34dp, "", "0") - private val BLOBMOJI = EmojiCompatFont("Blobmoji", + val BLOBMOJI = EmojiCompatFont("Blobmoji", "Blobmoji", R.string.caption_blobmoji, R.drawable.ic_blobmoji, "https://tusky.app/hosted/emoji/BlobmojiCompat.ttf", "12.0.0" ) - private val TWEMOJI = EmojiCompatFont("Twemoji", + val TWEMOJI = EmojiCompatFont("Twemoji", "Twemoji", R.string.caption_twemoji, R.drawable.ic_twemoji, "https://tusky.app/hosted/emoji/TwemojiCompat.ttf", "12.0.0" ) - private val NOTOEMOJI = EmojiCompatFont("NotoEmoji", + val NOTOEMOJI = EmojiCompatFont("NotoEmoji", "Noto Emoji", R.string.caption_notoemoji, R.drawable.ic_notoemoji, diff --git a/app/src/main/res/layout/item_emoji_pref.xml b/app/src/main/res/layout/item_emoji_pref.xml index d8755a3d..a10a5ffe 100644 --- a/app/src/main/res/layout/item_emoji_pref.xml +++ b/app/src/main/res/layout/item_emoji_pref.xml @@ -2,7 +2,6 @@ <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/emojicompat_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" @@ -11,7 +10,7 @@ <!--This is a thumbnail picture--> <ImageView - android:id="@+id/emojicompat_thumb" + android:id="@+id/emojiThumbnail" android:layout_width="42dp" android:layout_height="42dp" android:layout_marginStart="16dp" @@ -25,22 +24,22 @@ <!--This is the font's name--> <TextView - android:id="@+id/emojicompat_name" + android:id="@+id/emojiName" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" android:layout_marginEnd="72dp" android:textColor="?android:textColorPrimary" android:textSize="?attr/status_text_medium" - app:layout_constraintBottom_toTopOf="@+id/emojicompat_caption" + app:layout_constraintBottom_toTopOf="@+id/emojiCaption" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@+id/emojicompat_thumb" + app:layout_constraintStart_toEndOf="@+id/emojiThumbnail" app:layout_constraintTop_toTopOf="parent" tools:text="@string/system_default" /> <!--A short caption…--> <TextView - android:id="@+id/emojicompat_caption" + android:id="@+id/emojiCaption" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="72dp" @@ -49,14 +48,14 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0" - app:layout_constraintStart_toStartOf="@id/emojicompat_name" - app:layout_constraintTop_toBottomOf="@id/emojicompat_name" + app:layout_constraintStart_toStartOf="@id/emojiName" + app:layout_constraintTop_toBottomOf="@id/emojiName" app:layout_constraintVertical_chainStyle="packed" tools:text="@string/caption_blobmoji" /> <!--This progress bar is shown while the font is downloading.--> <ProgressBar - android:id="@+id/emojicompat_progress" + android:id="@+id/emojiProgress" style="?android:attr/progressBarStyleHorizontal" android:layout_width="0dp" android:layout_height="wrap_content" @@ -65,12 +64,12 @@ android:indeterminate="false" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="@id/emojicompat_name" - app:layout_constraintTop_toBottomOf="@id/emojicompat_name" /> + app:layout_constraintStart_toStartOf="@id/emojiName" + app:layout_constraintTop_toBottomOf="@id/emojiName" /> <!--Click on it and the font will be downloaded!--> <ImageButton - android:id="@+id/emojicompat_download" + android:id="@+id/emojiDownload" android:layout_width="42dp" android:layout_height="42dp" android:background="?attr/selectableItemBackgroundBorderless" @@ -80,13 +79,13 @@ android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@id/emojicompat_caption" + app:layout_constraintStart_toEndOf="@id/emojiCaption" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/ic_file_download_black_24dp" /> <!--You should be able to cancel the download--> <ImageButton - android:id="@+id/emojicompat_download_cancel" + android:id="@+id/emojiDownloadCancel" android:layout_width="42dp" android:layout_height="42dp" android:background="?attr/selectableItemBackgroundBorderless" @@ -96,20 +95,20 @@ android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@id/emojicompat_name" + app:layout_constraintStart_toEndOf="@id/emojiName" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/ic_cancel_24dp" /> <!--You'll probably want to select an emoji font, don't you?--> <androidx.appcompat.widget.AppCompatRadioButton - android:id="@+id/emojicompat_radio" + android:id="@+id/emojiRadioButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="visible" app:buttonTint="@color/compound_button_color" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@id/emojicompat_name" + app:layout_constraintStart_toEndOf="@id/emojiName" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file