@@ -10,13 +10,27 @@ import '../../../providers/learning_settings_provider.dart';
1010import '../domain/user_preferences_document.dart' ;
1111
1212/// 将当前仍使用的用户偏好映射到同步文档;设备/开发状态不在此白名单中。
13+ ///
14+ /// 一次性提示标记也在白名单内(放在 `learning` 域),让多设备只展示一次。
15+ /// 新手引导的已看与跳过状态只保存在本机,不同步。
16+ /// 设备级状态(权限、版本忽略、评分弹窗时间)也不同步。
1317class LocalUserPreferencesStore {
1418 LocalUserPreferencesStore (this ._preferences);
1519
1620 final SharedPreferences _preferences;
1721
1822 static const syncMetadataKey = 'user_preferences_sync_state_v1' ;
1923
24+ /// 一次性提示标记。写回时只做「未展示 → 已展示」,云端 false 或缺失都不清除
25+ /// 本地已展示状态,否则旧客户端或新设备首次同步会让提示再次弹出。
26+ static const _promptMarkerFieldNames = < String , String > {
27+ LearningSettingsKeys .retellAutoPlaybackPromptShown:
28+ 'retellAutoPlaybackPromptShown' ,
29+ LearningSettingsKeys .pdfExportReminderShown: 'pdfExportReminderShown' ,
30+ LearningSettingsKeys .unclearAutoSaveReminderShown:
31+ 'unclearAutoSaveReminderShown' ,
32+ };
33+
2034 static const _practiceKeys = < String , String > {
2135 'intensiveListen' : 'intensive_listen_prefs_v2' ,
2236 'blindListen' : 'blind_listen_prefs_v1' ,
@@ -48,6 +62,8 @@ class LocalUserPreferencesStore {
4862 for (final entry in _learningDefaults.entries)
4963 _learningFieldName (entry.key):
5064 _preferences.getBool (entry.key) ?? entry.value,
65+ for (final entry in _promptMarkerFieldNames.entries)
66+ entry.value: _preferences.getBool (entry.key) ?? false ,
5167 };
5268 final storedThreshold = _preferences.getInt ('silence_threshold_seconds' );
5369 final playback = < String , Object ? > {
@@ -121,6 +137,9 @@ class LocalUserPreferencesStore {
121137 entry.value,
122138 );
123139 }
140+ for (final entry in _promptMarkerFieldNames.entries) {
141+ await _markShownIfTrue (entry.key, learning[entry.value]);
142+ }
124143
125144 final playback = _group (groups, 'playback' );
126145 await _writeBool (
@@ -227,6 +246,12 @@ class LocalUserPreferencesStore {
227246 return result;
228247 }
229248
249+ /// 一次性标记只能单向前进:云端 true 才落盘,false 与缺失都不清除本地 true。
250+ Future <void > _markShownIfTrue (String key, Object ? value) async {
251+ if (value != true ) return ;
252+ await _preferences.setBool (key, true );
253+ }
254+
230255 Future <void > _writeString (String key, Object ? value, String fallback) async {
231256 await _preferences.setString (key, value is String ? value : fallback);
232257 }
0 commit comments