From e29003c79d0eb4aa20c1963f15d4381fc88bb443 Mon Sep 17 00:00:00 2001
From: Phil Oliver <3497406+poliver@users.noreply.github.com>
Date: Mon, 18 Aug 2025 13:36:35 -0400
Subject: [PATCH] Migrate custom emoji prefs to repo pattern (#2767)
---
.../mesh/ui/common/EmojiPickerViewModel.kt | 33 +++++++++++++++++++
.../mesh/ui/common/components/EmojiPicker.kt | 16 +++++++--
.../mesh/util/CustomRecentEmojiProvider.kt | 22 ++++---------
3 files changed, 53 insertions(+), 18 deletions(-)
create mode 100644 app/src/main/java/com/geeksville/mesh/ui/common/EmojiPickerViewModel.kt
diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/EmojiPickerViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/common/EmojiPickerViewModel.kt
new file mode 100644
index 000000000..b97cb8961
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/ui/common/EmojiPickerViewModel.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2025 Meshtastic LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.geeksville.mesh.ui.common
+
+import androidx.lifecycle.ViewModel
+import com.geeksville.mesh.android.prefs.CustomEmojiPrefs
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+
+@HiltViewModel
+class EmojiPickerViewModel @Inject constructor(private val customEmojiPrefs: CustomEmojiPrefs) : ViewModel() {
+
+ var customEmojiFrequency: String?
+ get() = customEmojiPrefs.customEmojiFrequency
+ set(value) {
+ customEmojiPrefs.customEmojiFrequency = value
+ }
+}
diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/components/EmojiPicker.kt b/app/src/main/java/com/geeksville/mesh/ui/common/components/EmojiPicker.kt
index 09ee28d46..7065134cc 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/common/components/EmojiPicker.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/common/components/EmojiPicker.kt
@@ -28,17 +28,29 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import androidx.emoji2.emojipicker.RecentEmojiProviderAdapter
+import androidx.hilt.navigation.compose.hiltViewModel
+import com.geeksville.mesh.ui.common.EmojiPickerViewModel
import com.geeksville.mesh.util.CustomRecentEmojiProvider
@Composable
-fun EmojiPicker(onDismiss: () -> Unit = {}, onConfirm: (String) -> Unit) {
+fun EmojiPicker(
+ viewModel: EmojiPickerViewModel = hiltViewModel(),
+ onDismiss: () -> Unit = {},
+ onConfirm: (String) -> Unit,
+) {
Column(verticalArrangement = Arrangement.Bottom) {
BackHandler { onDismiss() }
AndroidView(
factory = { context ->
androidx.emoji2.emojipicker.EmojiPickerView(context).apply {
clipToOutline = true
- setRecentEmojiProvider(RecentEmojiProviderAdapter(CustomRecentEmojiProvider(context)))
+ setRecentEmojiProvider(
+ RecentEmojiProviderAdapter(
+ CustomRecentEmojiProvider(viewModel.customEmojiFrequency) { updatedValue ->
+ viewModel.customEmojiFrequency = updatedValue
+ },
+ ),
+ )
setOnEmojiPickedListener { emoji ->
onDismiss()
onConfirm(emoji.emoji)
diff --git a/app/src/main/java/com/geeksville/mesh/util/CustomRecentEmojiProvider.kt b/app/src/main/java/com/geeksville/mesh/util/CustomRecentEmojiProvider.kt
index f6575638e..7a53307ad 100644
--- a/app/src/main/java/com/geeksville/mesh/util/CustomRecentEmojiProvider.kt
+++ b/app/src/main/java/com/geeksville/mesh/util/CustomRecentEmojiProvider.kt
@@ -17,19 +17,18 @@
package com.geeksville.mesh.util
-import android.content.Context
import androidx.emoji2.emojipicker.RecentEmojiAsyncProvider
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
/** Define a custom recent emoji provider which shows most frequently used emoji */
-class CustomRecentEmojiProvider(context: Context) : RecentEmojiAsyncProvider {
-
- private val sharedPreferences = context.getSharedPreferences(RECENT_EMOJI_LIST_FILE_NAME, Context.MODE_PRIVATE)
+class CustomRecentEmojiProvider(
+ private val customEmojiFrequency: String?,
+ private val onUpdateCustomEmojiFrequency: (updatedValue: String) -> Unit,
+) : RecentEmojiAsyncProvider {
private val emoji2Frequency: MutableMap by lazy {
- sharedPreferences
- .getString(PREF_KEY_CUSTOM_EMOJI_FREQ, null)
+ customEmojiFrequency
?.split(SPLIT_CHAR)
?.associate { entry ->
entry.split(KEY_VALUE_DELIMITER, limit = 2).takeIf { it.size == 2 }?.let { it[0] to it[1].toInt() }
@@ -43,19 +42,10 @@ class CustomRecentEmojiProvider(context: Context) : RecentEmojiAsyncProvider {
override fun recordSelection(emoji: String) {
emoji2Frequency[emoji] = (emoji2Frequency[emoji] ?: 0) + 1
- saveToPreferences()
- }
-
- private fun saveToPreferences() {
- sharedPreferences
- .edit()
- .putString(PREF_KEY_CUSTOM_EMOJI_FREQ, emoji2Frequency.entries.joinToString(SPLIT_CHAR))
- .apply()
+ onUpdateCustomEmojiFrequency(emoji2Frequency.entries.joinToString(SPLIT_CHAR))
}
companion object {
- private const val PREF_KEY_CUSTOM_EMOJI_FREQ = "pref_key_custom_emoji_freq"
- private const val RECENT_EMOJI_LIST_FILE_NAME = "org.geeksville.emoji.prefs"
private const val SPLIT_CHAR = ","
private const val KEY_VALUE_DELIMITER = "="
}