Persist quick send history safely

This commit is contained in:
Misaka
2026-05-17 17:10:01 +08:00
parent 19441399d0
commit 5f6e045e98
2 changed files with 78 additions and 7 deletions

View File

@@ -21,6 +21,7 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Switch
import android.widget.TextView
import org.json.JSONArray
class QuickSendActivity : Activity() {
private lateinit var input: EditText
@@ -459,6 +460,7 @@ class QuickSendActivity : Activity() {
}
if (ConnectionService.sendText(text) && (!appendEnter || ConnectionService.sendEnter())) {
saveHistory(text)
sendButton.background = roundedDrawable(Color.rgb(22, 163, 74), dp(26).toFloat())
sendIcon.setImageResource(R.drawable.ic_check_24)
sendIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)
@@ -472,6 +474,45 @@ class QuickSendActivity : Activity() {
}
}
private fun saveHistory(text: String) {
if (text.trim().isEmpty()) {
return
}
val prefs = getSharedPreferences(PREFS, Context.MODE_PRIVATE)
val currentHistory = readHistory()
val nextHistory = linkedSetOf(text)
currentHistory
.filter { it != text }
.take(MAX_HISTORY_ITEMS - 1)
.forEach { nextHistory.add(it) }
prefs.edit()
.putString(KEY_HISTORY, JSON_LIST_PREFIX + JSONArray(nextHistory.toList()).toString())
.apply()
}
private fun readHistory(): List<String> {
val rawValue = getSharedPreferences(PREFS, Context.MODE_PRIVATE).all[KEY_HISTORY]
return when (rawValue) {
is String -> decodeHistoryString(rawValue)
is Set<*> -> rawValue.filterIsInstance<String>()
else -> emptyList()
}
}
private fun decodeHistoryString(value: String): List<String> {
if (!value.startsWith(JSON_LIST_PREFIX)) {
return emptyList()
}
return runCatching {
val array = JSONArray(value.substring(JSON_LIST_PREFIX.length))
List(array.length()) { index -> array.optString(index) }
.filter { it.isNotEmpty() }
}.getOrDefault(emptyList())
}
private fun toggleAppendEnter() {
setAppendEnter(!appendEnter)
}
@@ -529,5 +570,8 @@ class QuickSendActivity : Activity() {
companion object {
private const val PREFS = "FlutterSharedPreferences"
private const val KEY_APPEND_ENTER = "flutter.append_enter"
private const val KEY_HISTORY = "flutter.send_history"
private const val JSON_LIST_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBhIGxpc3Qu!"
private const val MAX_HISTORY_ITEMS = 10
}
}

View File

@@ -221,7 +221,7 @@ class _InputSyncPageState extends State<InputSyncPage>
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
unawaited(_syncAppendEnterFromPrefs());
unawaited(_syncSharedPrefsFromDisk());
}
}
@@ -239,7 +239,7 @@ class _InputSyncPageState extends State<InputSyncPage>
prefs.getString(_portKey) ?? nativeState.port.toString();
clearAfterSend = prefs.getBool(_clearAfterSendKey) ?? false;
appendEnter = prefs.getBool(_appendEnterKey) ?? false;
sendHistory = prefs.getStringList(_historyKey) ?? [];
sendHistory = _readHistory(prefs);
connection = nativeState;
headerExpanded = !nativeState.connected;
});
@@ -459,18 +459,45 @@ class _InputSyncPageState extends State<InputSyncPage>
});
}
Future<void> _syncAppendEnterFromPrefs() async {
Future<void> _syncSharedPrefsFromDisk() async {
final prefs = await SharedPreferences.getInstance();
await prefs.reload();
final nextAppendEnter = prefs.getBool(_appendEnterKey) ?? false;
if (!mounted || nextAppendEnter == appendEnter) {
final nextHistory = _readHistory(prefs);
if (!mounted) {
return;
}
if (nextAppendEnter != appendEnter ||
!_stringListsEqual(nextHistory, sendHistory)) {
setState(() {
appendEnter = nextAppendEnter;
sendHistory = nextHistory;
});
}
}
bool _stringListsEqual(List<String> left, List<String> right) {
if (left.length != right.length) {
return false;
}
for (var index = 0; index < left.length; index += 1) {
if (left[index] != right[index]) {
return false;
}
}
return true;
}
List<String> _readHistory(SharedPreferences prefs) {
try {
return prefs.getStringList(_historyKey) ?? [];
} catch (_) {
return [];
}
}
void _restoreHistory(String text) {
inputController.text = text;