chore: 完成v2.4.7版本迭代更新
本次更新包含多项功能优化与兼容性修复: 1. iOS/鸿蒙端添加加密出口合规配置,跳过App Store审核问卷 2. 新增学习计划设置页路由与国际化支持 3. 修复鸿蒙端剪贴板粘贴不工作问题,安装标准剪贴板拦截器 4. 优化收藏功能:兼容复合ID、添加状态同步与触觉反馈 5. 修复鸿蒙端相册保存兼容性,统一使用系统分享降级方案 6. 优化搜索快捷方式跳转逻辑,避免白屏问题 7. 更新本地化资源,新增闲情逸致、学习计划等模块翻译 8. 修复节气日期表排序与跨年边界问题 9. 优化设备信息页面显示,新增系统版本号展示 10. 重构文件传输二维码逻辑,使用纯URL提升兼容性 11. 优化设置项布局,避免文本溢出问题 12. 修复登录页记住账户功能,新增隐私协议守卫 13. 更新macOS依赖库,替换flutter_secure_storage为darwin版本
This commit is contained in:
178
lib/core/services/app_store_service.dart
Normal file
178
lib/core/services/app_store_service.dart
Normal file
@@ -0,0 +1,178 @@
|
||||
/// ============================================================
|
||||
/// 闲言APP — 应用商店跳转服务
|
||||
/// 创建时间: 2026-06-17
|
||||
/// 更新时间: 2026-06-17
|
||||
/// 作用: 根据平台和语言地区生成正确的应用商店URL
|
||||
/// 上次更新: 初始版本,支持iOS/Android/鸿蒙/Windows/macOS多平台多地区
|
||||
/// ============================================================
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../l10n/app_locale.dart';
|
||||
import '../../l10n/types/t_root.dart';
|
||||
import '../utils/logger.dart';
|
||||
import '../utils/platform/platform_utils.dart' as pu;
|
||||
|
||||
/// 应用商店服务
|
||||
///
|
||||
/// 根据当前平台和语言地区,生成对应的应用商店URL。
|
||||
/// 不同地区的App Store可能使用不同的应用ID,
|
||||
/// 此服务统一管理这些ID和URL。
|
||||
class AppStoreService {
|
||||
AppStoreService._();
|
||||
|
||||
// ============================================================
|
||||
// 应用ID配置 — 按地区区分
|
||||
// ============================================================
|
||||
|
||||
/// iOS App Store 应用ID(按地区)
|
||||
///
|
||||
/// 不同地区的App Store可能有不同的应用ID,
|
||||
/// 如果应用在所有地区使用同一ID,则都填同一个。
|
||||
/// 当前配置:
|
||||
/// - 中国大陆 (cn): 6771828376
|
||||
/// - 其他地区: 6771828376
|
||||
static const Map<String, String> _iosAppIdsByRegion = {
|
||||
'CN': '6771828376',
|
||||
'TW': '6771828376',
|
||||
'HK': '6771828376',
|
||||
'MO': '6771828376',
|
||||
'US': '6771828376',
|
||||
'JP': '6771828376',
|
||||
'KR': '6771828376',
|
||||
'GB': '6771828376',
|
||||
'FR': '6771828376',
|
||||
'DE': '6771828376',
|
||||
'ES': '6771828376',
|
||||
'IT': '6771828376',
|
||||
'PT': '6771828376',
|
||||
'RU': '6771828376',
|
||||
'IN': '6771828376',
|
||||
'BR': '6771828376',
|
||||
'AR': '6771828376', // 阿拉伯语地区
|
||||
'BN': '6771828376', // 孟加拉语地区
|
||||
'HI': '6771828376', // 印地语地区
|
||||
};
|
||||
|
||||
/// 默认iOS应用ID(当地区未在映射中时使用)
|
||||
static const String _iosDefaultAppId = '6771828376';
|
||||
|
||||
/// Android 包名
|
||||
static const String _androidPackageName = 'apps.xy.xianyan';
|
||||
|
||||
/// 鸿蒙应用包名
|
||||
static const String _ohosPackageName = 'apps.xy.xianyan';
|
||||
|
||||
/// Windows 应用商店 Product ID
|
||||
/// 注意:用户提供两个URL,第二个看起来是错误的(少了个5)
|
||||
/// 正确的 Product ID: 9nqcv5gz10wnb
|
||||
static const String _windowsProductId = '9nqcv5gz10wnb';
|
||||
|
||||
// ============================================================
|
||||
// URL生成方法
|
||||
// ============================================================
|
||||
|
||||
/// 根据当前语言地区获取iOS App Store URL
|
||||
///
|
||||
/// [locale] 当前语言Locale,用于判断地区
|
||||
static Uri getIOSAppStoreUrl(Locale locale) {
|
||||
final countryCode = locale.countryCode ?? '';
|
||||
final appId = _iosAppIdsByRegion[countryCode.toUpperCase()] ??
|
||||
_iosDefaultAppId;
|
||||
|
||||
// App Store URL格式: https://apps.apple.com/{region}/app/id{appId}
|
||||
// 如果有地区代码,加入地区路径以正确跳转
|
||||
final region = countryCode.isNotEmpty ? '$countryCode/' : '';
|
||||
final url = 'https://apps.apple.com/${region}app/id$appId';
|
||||
Log.d('AppStoreService: iOS URL = $url (region: $countryCode, appId: $appId)');
|
||||
return Uri.parse(url);
|
||||
}
|
||||
|
||||
/// 获取Android Google Play URL
|
||||
static Uri getAndroidPlayStoreUrl({bool webFallback = false}) {
|
||||
if (webFallback) {
|
||||
return Uri.parse(
|
||||
'https://play.google.com/store/apps/details?id=$_androidPackageName',
|
||||
);
|
||||
}
|
||||
return Uri.parse('market://details?id=$_androidPackageName');
|
||||
}
|
||||
|
||||
/// 获取鸿蒙应用市场URL
|
||||
static Uri getOhosAppGalleryUrl() {
|
||||
return Uri.parse(
|
||||
'https://appgallery.huawei.com/app/detail?id=$_ohosPackageName',
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取Windows应用商店URL
|
||||
///
|
||||
/// [locale] 当前语言Locale,用于设置hl参数
|
||||
static Uri getWindowsStoreUrl(Locale locale) {
|
||||
final langCode = locale.languageCode;
|
||||
final countryCode = locale.countryCode ?? '';
|
||||
// 根据语言构造hl参数,如 zh-CN, en-GB
|
||||
String hl;
|
||||
if (countryCode.isNotEmpty) {
|
||||
hl = '${langCode.toLowerCase()}-${countryCode.toUpperCase()}';
|
||||
} else {
|
||||
// 默认中文
|
||||
hl = langCode == 'zh' ? 'zh-CN' : 'en-US';
|
||||
}
|
||||
return Uri.parse(
|
||||
'https://apps.microsoft.com/detail/$_windowsProductId?hl=$hl',
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取macOS App Store URL
|
||||
///
|
||||
/// macOS使用与iOS相同的应用ID(如果应用同时支持macOS)
|
||||
static Uri getMacOSAppStoreUrl(Locale locale) {
|
||||
// macOS版可能使用不同的应用ID,这里暂时使用与iOS相同的逻辑
|
||||
return getIOSAppStoreUrl(locale);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 统一入口方法
|
||||
// ============================================================
|
||||
|
||||
/// 获取当前平台的应用商店URL
|
||||
///
|
||||
/// 自动根据平台和语言地区返回正确的URL。
|
||||
/// 返回null表示当前平台不支持跳转应用商店。
|
||||
static Uri? getStoreUrl(BuildContext context, WidgetRef ref) {
|
||||
final locale = ref.read(appLocaleProvider);
|
||||
return getStoreUrlByLocale(locale);
|
||||
}
|
||||
|
||||
/// 根据Locale获取当前平台的应用商店URL
|
||||
static Uri? getStoreUrlByLocale(Locale locale) {
|
||||
if (pu.isIOS) {
|
||||
return getIOSAppStoreUrl(locale);
|
||||
}
|
||||
if (pu.isAndroid) {
|
||||
return getAndroidPlayStoreUrl();
|
||||
}
|
||||
if (pu.isOhos) {
|
||||
return getOhosAppGalleryUrl();
|
||||
}
|
||||
if (pu.isWindows) {
|
||||
return getWindowsStoreUrl(locale);
|
||||
}
|
||||
if (pu.isMacOS) {
|
||||
return getMacOSAppStoreUrl(locale);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// 获取应用商店显示名称
|
||||
static String getStoreName(T t) {
|
||||
if (pu.isIOS) return 'App Store';
|
||||
if (pu.isAndroid) return 'Google Play';
|
||||
if (pu.isOhos) return t.about.huaweiStore;
|
||||
if (pu.isWindows) return 'Microsoft Store';
|
||||
if (pu.isMacOS) return 'App Store';
|
||||
return t.about.huaweiStore;
|
||||
}
|
||||
}
|
||||
168
lib/core/services/auth/token_refresh_watcher.dart
Normal file
168
lib/core/services/auth/token_refresh_watcher.dart
Normal file
@@ -0,0 +1,168 @@
|
||||
/// ============================================================
|
||||
/// 闲言APP — Token过期智能续期监听器
|
||||
/// 创建时间: 2026-06-17
|
||||
/// 更新时间: 2026-06-17
|
||||
/// 作用: 监听网络恢复事件,自动尝试Token续期,失败则弹窗引导重新登录
|
||||
/// 上次更新: 初始创建
|
||||
/// ============================================================
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import '../network/connectivity_service.dart';
|
||||
import 'token_service.dart';
|
||||
import '../../storage/kv_storage.dart';
|
||||
import '../../utils/logger.dart';
|
||||
import '../../router/app_router.dart' show rootNavigatorKey;
|
||||
import '../../router/app_routes.dart';
|
||||
|
||||
class TokenRefreshWatcher {
|
||||
TokenRefreshWatcher._();
|
||||
|
||||
// ============================================================
|
||||
// 私有状态
|
||||
// ============================================================
|
||||
|
||||
static StreamSubscription<NetworkType>? _networkSub;
|
||||
static bool _isWatching = false;
|
||||
static bool _wasOffline = false;
|
||||
static bool _dialogShowing = false;
|
||||
static const String _dialogFlagKey = '_relogin_dialog_showing';
|
||||
|
||||
// ============================================================
|
||||
// 公开接口
|
||||
// ============================================================
|
||||
|
||||
/// 启动监听(在 ConnectivityService 初始化之后调用)
|
||||
static void startWatching() {
|
||||
if (_isWatching) return;
|
||||
_isWatching = true;
|
||||
|
||||
// 记录初始网络状态
|
||||
_wasOffline = ConnectivityService.isOffline;
|
||||
|
||||
_networkSub = ConnectivityService.onTypeChange.listen(_onNetworkChanged);
|
||||
Log.i('TokenRefreshWatcher: 开始监听网络变化');
|
||||
}
|
||||
|
||||
/// 停止监听
|
||||
static void stopWatching() {
|
||||
_networkSub?.cancel();
|
||||
_networkSub = null;
|
||||
_isWatching = false;
|
||||
Log.i('TokenRefreshWatcher: 停止监听');
|
||||
}
|
||||
|
||||
/// 当前是否正在监听
|
||||
static bool get isWatching => _isWatching;
|
||||
|
||||
// ============================================================
|
||||
// 网络变化回调
|
||||
// ============================================================
|
||||
|
||||
/// 网络类型变化时触发
|
||||
static void _onNetworkChanged(NetworkType type) {
|
||||
final isOffline = type == NetworkType.none;
|
||||
|
||||
// 从离线恢复到在线时,尝试续期
|
||||
if (_wasOffline && !isOffline) {
|
||||
Log.i('TokenRefreshWatcher: 检测到网络恢复,尝试Token续期');
|
||||
_tryRefreshToken();
|
||||
}
|
||||
|
||||
_wasOffline = isOffline;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Token续期逻辑
|
||||
// ============================================================
|
||||
|
||||
/// 尝试续期Token
|
||||
static Future<void> _tryRefreshToken() async {
|
||||
try {
|
||||
// 先检查Token是否有效
|
||||
final result = await TokenService.checkToken();
|
||||
if (result.valid) {
|
||||
Log.i('TokenRefreshWatcher: Token有效,无需续期');
|
||||
return;
|
||||
}
|
||||
|
||||
// Token无效,尝试续期
|
||||
Log.i('TokenRefreshWatcher: Token无效(${result.reason}),尝试续期...');
|
||||
final refreshed = await TokenService.refreshToken();
|
||||
if (refreshed) {
|
||||
Log.i('TokenRefreshWatcher: Token续期成功 ✓');
|
||||
} else {
|
||||
Log.w('TokenRefreshWatcher: Token续期失败,引导重新登录');
|
||||
_showReLoginDialog();
|
||||
}
|
||||
} catch (e) {
|
||||
Log.e('TokenRefreshWatcher: 续期异常', e);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 重新登录引导弹窗
|
||||
// ============================================================
|
||||
|
||||
/// 弹出重新登录引导弹窗(Cupertino风格)
|
||||
static void _showReLoginDialog() {
|
||||
final context = rootNavigatorKey.currentContext;
|
||||
if (context == null) {
|
||||
Log.w('TokenRefreshWatcher: context不可用,无法弹窗');
|
||||
return;
|
||||
}
|
||||
|
||||
// 避免重复弹窗
|
||||
if (_dialogShowing) return;
|
||||
if (KvStorage.getBool(_dialogFlagKey) == true) return;
|
||||
|
||||
_dialogShowing = true;
|
||||
KvStorage.setBool(_dialogFlagKey, true);
|
||||
|
||||
showCupertinoDialog<void>(
|
||||
context: context,
|
||||
builder: (ctx) => CupertinoAlertDialog(
|
||||
title: const Text('🔑 登录已过期'),
|
||||
content: const Text('您的登录凭证已失效,请重新登录以继续使用完整功能。'),
|
||||
actions: [
|
||||
CupertinoDialogAction(
|
||||
onPressed: () {
|
||||
_dismissDialog(ctx);
|
||||
},
|
||||
child: const Text('稍后'),
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
isDefaultAction: true,
|
||||
onPressed: () {
|
||||
_dismissDialog(ctx);
|
||||
_navigateToLogin();
|
||||
},
|
||||
child: const Text('重新登录'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 关闭弹窗并重置标记
|
||||
static void _dismissDialog(BuildContext ctx) {
|
||||
_dialogShowing = false;
|
||||
KvStorage.setBool(_dialogFlagKey, false);
|
||||
Navigator.pop(ctx);
|
||||
}
|
||||
|
||||
/// 导航到登录页
|
||||
static void _navigateToLogin() {
|
||||
try {
|
||||
final nav = rootNavigatorKey.currentState;
|
||||
if (nav != null) {
|
||||
nav.pushNamed(AppRoutes.login);
|
||||
Log.i('TokenRefreshWatcher: 已导航到登录页');
|
||||
}
|
||||
} catch (e) {
|
||||
Log.e('TokenRefreshWatcher: 导航到登录页失败', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
/// ============================================================
|
||||
/// 闲言APP — 桌面小组件数据管理服务
|
||||
/// 创建时间: 2026-05-15
|
||||
/// 更新时间: 2026-06-16
|
||||
/// 更新时间: 2026-06-17
|
||||
/// 作用: 基于home_widget库管理桌面小组件数据推送与交互
|
||||
/// 上次更新: 添加平台检测,Windows/Linux桌面端跳过HomeWidget调用防止MissingPluginException
|
||||
/// 上次更新: 统一使用PlatformCapabilities.supports(CapabilityKey.homeWidget)判断平台支持,移除_isPlatformSupported双轨逻辑
|
||||
/// ============================================================
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
@@ -69,8 +69,13 @@ class HomeWidgetService {
|
||||
|
||||
bool get isInitialized => _initialized;
|
||||
|
||||
/// 当前平台是否支持桌面小组件(仅 iOS/Android/macOS 支持,Windows/Linux 跳过)
|
||||
bool get _isPlatformSupported => !pu.isDesktop || pu.isMacOS;
|
||||
/// 当前平台是否支持桌面小组件
|
||||
///
|
||||
/// 统一通过 [PlatformCapabilities] 查询 [CapabilityKey.homeWidget] 能力,
|
||||
/// 避免与平台判断逻辑(pu.isDesktop 等)产生双轨不一致问题。
|
||||
/// 支持平台: iOS / Android / 鸿蒙;macOS/Windows/Linux/Web 不支持。
|
||||
bool get _isPlatformSupported =>
|
||||
PlatformCapabilities.supports(CapabilityKey.homeWidget);
|
||||
|
||||
// ============================================================
|
||||
// 初始化
|
||||
@@ -542,12 +547,6 @@ class HomeWidgetService {
|
||||
try {
|
||||
await _ensureInit();
|
||||
|
||||
// [PlatformCapabilities] 统一能力查询: homeWidget
|
||||
if (!PlatformCapabilities.supports(CapabilityKey.homeWidget)) {
|
||||
Log.w('HomeWidgetService: 当前平台不支持桌面小组件,跳过刷新');
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == WidgetType.dailyWithCharacter) {
|
||||
if (!pu.isOhos) {
|
||||
Log.i('HomeWidgetService: ${type.title} 原生端尚未实现,跳过刷新');
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// ============================================================
|
||||
// 闲言APP — 设备信息服务
|
||||
// 创建时间: 2026-05-10
|
||||
// 更新时间: 2026-06-05
|
||||
// 更新时间: 2026-06-17
|
||||
// 作用: 采集设备信息并自动注册到服务端
|
||||
// 上次更新: 鸿蒙端增加设备信息回退逻辑;Web端精确识别浏览器标识
|
||||
// 上次更新: 新增 getSystemVersion() 方法获取系统版本号
|
||||
// ============================================================
|
||||
|
||||
import 'dart:io' show Platform;
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
@@ -638,6 +639,73 @@ class DeviceInfoService {
|
||||
return browserCn;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 获取系统版本号
|
||||
// ============================================================
|
||||
|
||||
static Future<String> getSystemVersion() async {
|
||||
if (kIsWeb) return '';
|
||||
try {
|
||||
if (pu.isOhos) {
|
||||
// 鸿蒙:从 Platform.operatingSystemVersion 获取
|
||||
try {
|
||||
final ver = Platform.operatingSystemVersion;
|
||||
if (ver.isNotEmpty) return _extractOhosVersion(ver);
|
||||
} catch (_) {}
|
||||
// 回退:使用 Android 信息
|
||||
final android = await _deviceInfoPlugin.androidInfo;
|
||||
return 'Android ${android.version.release}';
|
||||
} else if (pu.isAndroid) {
|
||||
final android = await _deviceInfoPlugin.androidInfo;
|
||||
return 'Android ${android.version.release}';
|
||||
} else if (pu.isIOS) {
|
||||
final ios = await _deviceInfoPlugin.iosInfo;
|
||||
return 'iOS ${ios.systemVersion}';
|
||||
} else if (pu.isMacOS) {
|
||||
final mac = await _deviceInfoPlugin.macOsInfo;
|
||||
return 'macOS ${mac.majorVersion}.${mac.minorVersion}.${mac.patchVersion}';
|
||||
} else if (pu.isWindows) {
|
||||
final windows = await _deviceInfoPlugin.windowsInfo;
|
||||
final major = windows.majorVersion;
|
||||
final display = windows.displayVersion;
|
||||
if (display.isNotEmpty) return 'Windows $major ($display)';
|
||||
return 'Windows $major';
|
||||
} else if (pu.isLinux) {
|
||||
try {
|
||||
final linux = await _deviceInfoPlugin.linuxInfo;
|
||||
if (linux.version != null && linux.version!.isNotEmpty) {
|
||||
return 'Linux ${linux.version}';
|
||||
}
|
||||
} catch (_) {}
|
||||
// 回退:从 Platform.operatingSystemVersion 提取
|
||||
try {
|
||||
final ver = Platform.operatingSystemVersion;
|
||||
if (ver.isNotEmpty) return 'Linux ${_extractKernelVersion(ver)}';
|
||||
} catch (_) {}
|
||||
return 'Linux';
|
||||
}
|
||||
} catch (e) {
|
||||
Log.w('获取系统版本失败: $e', null, null, LogCategory.device);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/// 从鸿蒙 operatingSystemVersion 提取版本号
|
||||
/// 例如 "HarmonyOS 5.0.0" → "鸿蒙 5.0"
|
||||
static String _extractOhosVersion(String ver) {
|
||||
final match = RegExp(r'(\d+\.\d+)').firstMatch(ver);
|
||||
if (match != null) return '鸿蒙 ${match.group(1)}';
|
||||
return '鸿蒙';
|
||||
}
|
||||
|
||||
/// 从 Linux operatingSystemVersion 提取内核版本
|
||||
/// 例如 "6.1.0-generic" → "6.1"
|
||||
static String _extractKernelVersion(String ver) {
|
||||
final match = RegExp(r'(\d+\.\d+)').firstMatch(ver);
|
||||
if (match != null) return match.group(1)!;
|
||||
return ver;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 获取平台标识
|
||||
// ============================================================
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// ============================================================
|
||||
// 闲言APP — 快捷操作服务
|
||||
// 创建时间: 2026-05-31
|
||||
/// 更新时间: 2026-06-16
|
||||
/// 更新时间: 2026-06-17
|
||||
/// 作用: 管理主屏幕快捷操作(Quick Actions / App Shortcuts)
|
||||
/// 上次更新: 使用ShortcutManager API创建快捷方式,修复图标和跳转问题
|
||||
/// 上次更新: 修复搜索快捷方式白屏问题,改用 action:search 标记由回调方直接弹搜索浮层
|
||||
// 跨平台: iOS(UIApplicationShortcutItems) + Android(ShortcutManager)
|
||||
// + 鸿蒙(module.json5 shortcuts + MethodChannel)
|
||||
// ============================================================
|
||||
@@ -176,13 +176,22 @@ class QuickActionsService {
|
||||
});
|
||||
}
|
||||
|
||||
/// 解析快捷方式为路由字符串
|
||||
///
|
||||
/// 搜索快捷方式使用特殊标记 `action:search`,由回调方(app.dart)负责:
|
||||
/// 1. 切换到 profile Tab(goBranch)而非 push 新页面
|
||||
/// 2. 直接在当前 context 弹出 SpotlightSearchOverlay
|
||||
///
|
||||
/// 这样可避免以下问题:
|
||||
/// - push `/profile` 会在 shell 之外创建新页面,导致白屏只显示底栏
|
||||
/// - ProfilePage 已构建过时 initState 不会再触发,pendingSearch 永不消费
|
||||
static String? _resolveRoute(String shortcutType) {
|
||||
switch (shortcutType) {
|
||||
case 'action_theme':
|
||||
return AppRoutes.themeSettings;
|
||||
case 'action_search':
|
||||
// 带参数路由,通知ProfilePage自动弹出搜索框
|
||||
return '${AppRoutes.profile}?action=search';
|
||||
// 特殊标记:搜索动作,由回调方直接弹出搜索浮层
|
||||
return 'action:search';
|
||||
case 'action_general_settings':
|
||||
return AppRoutes.generalSettings;
|
||||
default:
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../storage/kv_storage.dart';
|
||||
import '../utils/logger.dart';
|
||||
import '../utils/platform/platform_utils.dart' as pu;
|
||||
import '../router/app_router.dart' show rootNavigatorKey;
|
||||
import 'auth/token_refresh_watcher.dart';
|
||||
import 'auth/permission_service.dart';
|
||||
import 'device/haptic_service.dart';
|
||||
import 'network/connectivity_service.dart';
|
||||
@@ -140,6 +141,14 @@ class PostAgreementInitializer {
|
||||
}
|
||||
}
|
||||
|
||||
// Token续期监听器(依赖ConnectivityService,必须在其之后启动)
|
||||
try {
|
||||
TokenRefreshWatcher.startWatching();
|
||||
Log.i('Token续期监听器启动完成');
|
||||
} catch (e, st) {
|
||||
Log.e('Token续期监听器启动失败', e, st);
|
||||
}
|
||||
|
||||
if (!pu.isWeb) {
|
||||
try {
|
||||
await BackgroundTaskService.instance.init();
|
||||
|
||||
Reference in New Issue
Block a user