105 lines
3.9 KiB
Kotlin
105 lines
3.9 KiB
Kotlin
package com.rosetta.messenger.data
|
||
|
||
import android.content.Context
|
||
import android.content.SharedPreferences
|
||
import kotlinx.coroutines.flow.MutableStateFlow
|
||
import kotlinx.coroutines.flow.StateFlow
|
||
import kotlinx.coroutines.flow.asStateFlow
|
||
|
||
/**
|
||
* 📝 Менеджер черновиков сообщений (как в Telegram)
|
||
* Хранит текст из инпута для каждого диалога.
|
||
* При возврате в список чатов показывает "Draft: текст" красным цветом.
|
||
*
|
||
* Использует SharedPreferences для персистентности между перезапусками.
|
||
* Ключ: "draft_{account}_{opponentKey}" -> текст черновика
|
||
*/
|
||
object DraftManager {
|
||
|
||
private const val PREFS_NAME = "rosetta_drafts"
|
||
private const val KEY_PREFIX = "draft_"
|
||
|
||
private var prefs: SharedPreferences? = null
|
||
|
||
// 🔥 Реактивный Map: opponentKey -> draftText
|
||
// Обновляется при каждом изменении черновика для мгновенного обновления UI списка чатов
|
||
private val _drafts = MutableStateFlow<Map<String, String>>(emptyMap())
|
||
val drafts: StateFlow<Map<String, String>> = _drafts.asStateFlow()
|
||
|
||
private var currentAccount: String = ""
|
||
|
||
/** Инициализация с контекстом приложения */
|
||
fun init(context: Context) {
|
||
if (prefs == null) {
|
||
prefs = context.applicationContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||
}
|
||
}
|
||
|
||
/** Установить текущий аккаунт и загрузить его черновики */
|
||
fun setAccount(account: String) {
|
||
if (currentAccount == account) return
|
||
currentAccount = account
|
||
loadDraftsFromPrefs()
|
||
}
|
||
|
||
/** Сохранить черновик для диалога */
|
||
fun saveDraft(opponentKey: String, text: String) {
|
||
if (currentAccount.isEmpty()) return
|
||
|
||
val trimmed = text.trim()
|
||
val currentDrafts = _drafts.value.toMutableMap()
|
||
|
||
if (trimmed.isEmpty()) {
|
||
// Удаляем черновик если текст пустой
|
||
currentDrafts.remove(opponentKey)
|
||
prefs?.edit()?.remove(prefKey(opponentKey))?.apply()
|
||
} else {
|
||
currentDrafts[opponentKey] = trimmed
|
||
prefs?.edit()?.putString(prefKey(opponentKey), trimmed)?.apply()
|
||
}
|
||
|
||
_drafts.value = currentDrafts
|
||
}
|
||
|
||
/** Получить черновик для диалога */
|
||
fun getDraft(opponentKey: String): String? {
|
||
return _drafts.value[opponentKey]
|
||
}
|
||
|
||
/** Очистить черновик для диалога (после отправки сообщения) */
|
||
fun clearDraft(opponentKey: String) {
|
||
if (currentAccount.isEmpty()) return
|
||
|
||
val currentDrafts = _drafts.value.toMutableMap()
|
||
currentDrafts.remove(opponentKey)
|
||
_drafts.value = currentDrafts
|
||
|
||
prefs?.edit()?.remove(prefKey(opponentKey))?.apply()
|
||
}
|
||
|
||
/** Очистить все черновики (при смене аккаунта / логауте) */
|
||
fun clearAll() {
|
||
_drafts.value = emptyMap()
|
||
}
|
||
|
||
/** Загрузить черновики текущего аккаунта из SharedPreferences */
|
||
private fun loadDraftsFromPrefs() {
|
||
val allPrefs = prefs?.all ?: return
|
||
val prefix = "${KEY_PREFIX}${currentAccount}_"
|
||
val loaded = mutableMapOf<String, String>()
|
||
|
||
allPrefs.forEach { (key, value) ->
|
||
if (key.startsWith(prefix) && value is String && value.isNotEmpty()) {
|
||
val opponentKey = key.removePrefix(prefix)
|
||
loaded[opponentKey] = value
|
||
}
|
||
}
|
||
|
||
_drafts.value = loaded
|
||
}
|
||
|
||
private fun prefKey(opponentKey: String): String {
|
||
return "${KEY_PREFIX}${currentAccount}_${opponentKey}"
|
||
}
|
||
}
|