user_account_storage.dart
5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// 账号级持久化存储。
///
/// 与 [UserPreferencesStorage] 的区别:
/// - [UserPreferencesStorage] 存储会话数据,退登时 clear() 会全部清除。
/// - [UserAccountStorage] 存储账号元数据,退登不清除,按 userId 隔离。
///
/// 适合存储:新手引导进度、账号历史记录等跨会话数据。
class UserAccountStorage {
UserAccountStorage(this._prefs);
final SharedPreferences _prefs;
// ─── Keys ──────────────────────────────────────────────────────────────────
/// Onboarding 阶段 key,按 userId 隔离
static String _onboardingKey(int userId) =>
'account_onboarding_stage_$userId';
/// Apple Health 上传时间记录 key,按 userId 隔离。
static String _appleHealthUploadRecordKey(int userId) =>
'apple_health_upload_local_records_$userId';
/// Apple Health 上传测试页上次同步时间 key,按 userId 隔离。
static String _appleHealthUploadTestLastSyncTimeKey(int userId) =>
'apple_health_upload_test_last_sync_time_$userId';
/// 是否显示实时压力,按 userId 隔离,避免会话数据刷新时覆盖该偏好。
static String _showRealtimeStressKey(int userId) =>
'account_show_realtime_stress_$userId';
/// 好友列表排序,按 userId 隔离。
static String _friendsOrderKey(int userId) => 'account_friends_order_$userId';
/// 在实时压力偏好更新后通知依赖它的页面刷新。
final realtimeStressSettingsVersion = 0.obs;
/// Onboarding 已全部完成的哨兵值
static const int _kOnboardingCompleted = -1;
// ─── Onboarding 阶段 ───────────────────────────────────────────────────────
//
// 存储规则:
// null(key 不存在) → 从未开始
// 0 ~ N(页码) → 进行中,记录上次停留的页码
// -1(kCompleted) → 已全部完成
//
// 状态机:
// null ──[进入引导]──▶ 0 ──[翻页]──▶ 1 ... N ──[完成]──▶ -1
// ↑ │
// └───────────────────[resetOnboarding]───────────────────┘
/// 是否已完成全部引导流程。
bool hasCompletedOnboarding(int userId) =>
_prefs.getInt(_onboardingKey(userId)) == _kOnboardingCompleted;
/// 是否已开始过引导(包括进行中和已完成)。
bool hasStartedOnboarding(int userId) =>
_prefs.getInt(_onboardingKey(userId)) != null;
/// 中途退出时上次停留的页码;null 表示从未开始或已完成。
int? onboardingResumeStage(int userId) {
final v = _prefs.getInt(_onboardingKey(userId));
if (v == null || v == _kOnboardingCompleted) return null;
return v;
}
/// 每次翻页时调用,保存当前页码进度。
Future<void> saveOnboardingStage(int userId, int pageIndex) =>
_prefs.setInt(_onboardingKey(userId), pageIndex);
/// 引导全部完成时调用。
Future<void> markOnboardingCompleted(int userId) =>
_prefs.setInt(_onboardingKey(userId), _kOnboardingCompleted);
/// 首页添加好友引导间隔
Future<void> saveLastAddFriendBannerShowTime(int userId) => _prefs.setInt(
'last_add_friend_banner_show_time_$userId',
DateTime.now().millisecondsSinceEpoch);
/// 首页添加好友引导间隔
int? getLastAddFriendBannerShowTime(int userId) =>
_prefs.getInt('last_add_friend_banner_show_time_$userId');
// ─── 实时压力展示偏好 ────────────────────────────────────────────────────
/// `null` 表示用户尚未设置,调用方应使用产品默认值。
bool? showRealtimeStress(int userId) =>
_prefs.getBool(_showRealtimeStressKey(userId));
Future<void> updateShowRealtimeStress(int userId, bool enabled) async {
await _prefs.setBool(_showRealtimeStressKey(userId), enabled);
realtimeStressSettingsVersion.value++;
}
// ─── 好友列表排序 ─────────────────────────────────────────────────────────
List<String>? friendOrder(int userId) =>
_prefs.getStringList(_friendsOrderKey(userId));
Future<void> saveFriendOrder(int userId, List<int> friendUserIds) =>
_prefs.setStringList(
_friendsOrderKey(userId),
friendUserIds.map((id) => id.toString()).toList(),
);
// ─── Apple Health 上传记录 ────────────────────────────────────────────────
String? appleHealthUploadLocalRecordJson(int userId) =>
_prefs.getString(_appleHealthUploadRecordKey(userId));
Future<void> saveAppleHealthUploadLocalRecordJson(
int userId,
String value,
) =>
_prefs.setString(_appleHealthUploadRecordKey(userId), value);
Future<void> clearAppleHealthUploadLocalRecord(int userId) =>
_prefs.remove(_appleHealthUploadRecordKey(userId));
int? appleHealthUploadTestLastSyncTime(int userId) =>
_prefs.getInt(_appleHealthUploadTestLastSyncTimeKey(userId));
Future<void> saveAppleHealthUploadTestLastSyncTime(
int userId,
int latestSyncTime,
) =>
_prefs.setInt(
_appleHealthUploadTestLastSyncTimeKey(userId),
latestSyncTime,
);
}