import 'package:shared_preferences/shared_preferences.dart'; /// 会话级本地偏好:免打扰、置顶、背景、本地清空记录。 class ChatPrefs { ChatPrefs._(); static SharedPreferences? _p; static Future ensure() async { _p ??= await SharedPreferences.getInstance(); // 旧版本曾在滑动过程中误写 hidden,导致会话读完后看似“自动删除”。 // 升级时清理一次旧标记,之后只有确认“不显示/删除”才会再次隐藏。 if (_p!.getBool('im.hidden.migration.v3') != true) { for (final key in _p!.getKeys().where((k) => k.startsWith('im.hidden.'))) { await _p!.remove(key); } await _p!.setBool('im.hidden.migration.v3', true); } } static bool muted(String id) => id.isEmpty ? false : (_p?.getBool('im.mute.$id') ?? false); static bool pinned(String id) => id.isEmpty ? false : (_p?.getBool('im.pin.$id') ?? false); static bool hidden(String id) => id.isEmpty ? false : (_p?.getBool('im.hidden.$id') ?? false); static int? bgColor(String id) => id.isEmpty ? null : _p?.getInt('im.bg.$id'); static DateTime? clearedAt(String id) { if (id.isEmpty) return null; final ms = _p?.getInt('im.cleared.$id'); if (ms == null || ms <= 0) return null; return DateTime.fromMillisecondsSinceEpoch(ms); } static Future setMuted(String id, bool v) async { await ensure(); await _p!.setBool('im.mute.$id', v); } static Future setPinned(String id, bool v) async { await ensure(); await _p!.setBool('im.pin.$id', v); } static Future setHidden(String id, bool v) async { await ensure(); await _p!.setBool('im.hidden.$id', v); } static Future setBg(String id, int color) async { await ensure(); await _p!.setInt('im.bg.$id', color); } static Future clearHistory(String id) async { await ensure(); await _p!.setInt('im.cleared.$id', DateTime.now().millisecondsSinceEpoch); } static int fakeUnread(String id) => id.isEmpty ? 0 : (_p?.getInt('im.fakeUnread.$id') ?? 0); static Future setFakeUnread(String id, int n) async { await ensure(); if (n <= 0) { await _p!.remove('im.fakeUnread.$id'); } else { await _p!.setInt('im.fakeUnread.$id', n); } } /// 语音转文字结果,按消息 id 或 fileId 缓存。 static String? voiceText(String key) { if (key.isEmpty) return null; final v = _p?.getString('im.voiceText.$key'); if (v == null || v.isEmpty) return null; return v; } static Future setVoiceText(String key, String text) async { if (key.isEmpty) return; await ensure(); final t = text.trim(); if (t.isEmpty) { await _p!.remove('im.voiceText.$key'); } else { await _p!.setString('im.voiceText.$key', t); } } }