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 = "=" }