Files
pangolin/client/lib/services/token_store.dart
T
wangjia df72ad60f4
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
fix: DNS 用 sing-box 1.12+ 新格式 + 引导仅首次显示
- clientconfig/mockserver:客户端配置 DNS 从 legacy address 串格式改为
  type+server 新格式(sing-box 1.13 对 legacy DNS 直接 FATAL,导致连不上)
- 引导页只首次:TokenStore 加 markOnboarded/isOnboarded;main.dart 登录后
  若已引导过直接进主界面,不再每次都弹引导

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 21:20:11 +08:00

38 lines
1.4 KiB
Dart

// token_store.dart — JWT 令牌安全持久化(flutter_secure_storage 封装)
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class TokenStore {
const TokenStore({FlutterSecureStorage? storage})
: _storage = storage ?? const FlutterSecureStorage(
// macOS 用文件式 keychain,避免未签名 app 缺 keychain-access-groups
// entitlement 时 write 报 -34018。
mOptions: MacOsOptions(useDataProtectionKeyChain: false),
);
final FlutterSecureStorage _storage;
static const _kAccess = 'pangolin_access_token';
static const _kRefresh = 'pangolin_refresh_token';
static const _kOnboarded = 'pangolin_onboarded';
Future<void> saveTokens({
required String access,
required String refresh,
}) async {
await _storage.write(key: _kAccess, value: access);
await _storage.write(key: _kRefresh, value: refresh);
}
Future<String?> loadAccessToken() => _storage.read(key: _kAccess);
Future<String?> loadRefreshToken() => _storage.read(key: _kRefresh);
Future<void> clear() async {
await _storage.delete(key: _kAccess);
await _storage.delete(key: _kRefresh);
}
// 首次引导标记:引导页只在第一次看(看完置位,后续登录直接进主界面)。
Future<void> markOnboarded() => _storage.write(key: _kOnboarded, value: '1');
Future<bool> isOnboarded() async => (await _storage.read(key: _kOnboarded)) == '1';
}