chore: 汇总2026-05-30全量更新

### 详细变更:
1.  **文档与配置**:更新AGENTS.md添加命令超时约束,升级Rive依赖至0.14.7并替换平台插件引用
2.  **UI优化**:重构AppInfo页面布局、移除图表冗余配置、锁定部分系统设置项
3.  **功能增强**:
    - 新增工具面板拖拽状态管理与介绍弹窗
    - 新增进度页面编辑/重排/清空用户进度功能
    - 新增摇一摇路由作用域拦截逻辑
4.  **体验优化**:
    - 统一外部链接跳转弹窗,添加文件打开确认逻辑
    - 修复设备卡片IP溢出、Android权限声明问题
    - 后台任务初始化增加协议校验
5.  **代码重构**:拆分工具面板配置、拖拽逻辑与动画参数,优化状态管理代码
6.  **工具脚本**:新增协议文件上传脚本
This commit is contained in:
Developer
2026-05-30 05:29:50 +08:00
parent ca68fe29c7
commit adfa0af825
123 changed files with 17747 additions and 4641 deletions

View File

@@ -3,7 +3,7 @@
/// 创建时间: 2026-05-29
/// 更新时间: 2026-05-29
/// 作用: 使用Rive动画替代TabIconSprite实现更丰富的角色动画
/// 上次更新: 初始创建
/// 上次更新: 迁移至 Rive 0.14.x API
/// ============================================================
import 'package:flutter/cupertino.dart';
@@ -41,8 +41,9 @@ class RiveTabIcon extends StatefulWidget {
}
class _RiveTabIconState extends State<RiveTabIcon> {
SMIInput<bool>? _selectedInput;
Artboard? _artboard;
RiveWidgetController? _controller;
File? _file;
bool _isLoading = true;
@override
void initState() {
@@ -50,39 +51,49 @@ class _RiveTabIconState extends State<RiveTabIcon> {
_loadRive();
}
/// 加载 Rive 文件并初始化 StateMachine
@override
void dispose() {
_controller?.dispose();
_file?.dispose();
super.dispose();
}
Future<void> _loadRive() async {
try {
final data = await RiveFile.asset(widget.assetPath);
final artboard = data.mainArtboard;
final controller = StateMachineController.fromArtboard(
artboard,
widget.stateMachineName,
final file = await File.asset(
widget.assetPath,
riveFactory: Factory.rive,
);
if (controller != null) {
artboard.addController(controller);
_selectedInput = controller.findInput<bool>('isSelected');
_selectedInput?.value = widget.isSelected;
}
if (mounted) {
setState(() => _artboard = artboard);
}
if (!mounted) return;
_file = file;
_controller = RiveWidgetController(
file!,
stateMachineSelector: StateMachineSelector.byName(
widget.stateMachineName,
),
);
_syncSelection();
setState(() => _isLoading = false);
} catch (e) {
// Rive文件加载失败时静默处理不影响其他功能
if (mounted) setState(() => _isLoading = false);
}
}
void _syncSelection() {
_controller?.stateMachine.boolean('isSelected')?.value = widget.isSelected;
}
@override
void didUpdateWidget(RiveTabIcon oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.isSelected != widget.isSelected) {
_selectedInput?.value = widget.isSelected;
_syncSelection();
}
}
@override
Widget build(BuildContext context) {
if (_artboard == null) {
if (_isLoading || _controller == null) {
return SizedBox(
width: widget.size,
height: widget.size,
@@ -92,7 +103,7 @@ class _RiveTabIconState extends State<RiveTabIcon> {
return SizedBox(
width: widget.size,
height: widget.size,
child: Rive(artboard: _artboard!),
child: RiveWidget(controller: _controller!),
);
}
}

View File

@@ -97,7 +97,7 @@ class SplitViewNotifier extends Notifier<SplitViewState> {
@override
SplitViewState build() {
final savedIndex = KvStorage.getInt(_kNavBarPosition) ?? 0;
final positions = NavBarPosition.values;
const positions = NavBarPosition.values;
return SplitViewState(
splitRatio: KvStorage.getDouble(_kSplitRatio) ?? 0.4,
navBarPosition: (savedIndex >= 0 && savedIndex < positions.length)

View File

@@ -1,9 +1,9 @@
// ============================================================
// 闲言APP — 路由配置(主入口)
// 创建时间: 2026-04-20
// 更新时间: 2026-05-28
// 更新时间: 2026-05-30
// 作用: go_router 路由表组装 + ShellRoute 布局壳 + iOS 风格转场 + 深链接重定向
// 上次更新: 对调inspiration/discover路由discover为Tab主页面
// 上次更新: 新增ShakeScopeObserver监听路由变化自动更新摇一摇作用域
// ============================================================
import 'package:bot_toast/bot_toast.dart';
@@ -20,6 +20,7 @@ import '../../features/mine/profile/presentation/profile_page.dart';
import '../layout/app_shell.dart';
import '../storage/kv_storage.dart';
import '../utils/ui/page_transitions.dart';
import '../services/device/shake_detector.dart';
import 'app_routes.dart';
import 'settings_routes.dart';
@@ -43,9 +44,7 @@ final GoRouter appRouter = GoRouter(
navigatorKey: rootNavigatorKey,
initialLocation: _resolveInitialLocation(),
debugLogDiagnostics: true,
observers: pu.isOhos
? [_OhosRouteObserver()]
: [BotToastNavigatorObserver()],
observers: pu.isOhos ? [_OhosRouteObserver()] : [BotToastNavigatorObserver()],
redirect: _handleDeepLinkRedirect,
routes: [
GoRoute(
@@ -106,6 +105,12 @@ final GoRouter appRouter = GoRouter(
errorBuilder: (context, state) => const NotFoundPage(),
);
/// 摇一摇路由作用域观察者
/// 监听路由变化,自动更新 ShakeDetector 的作用域
/// 仅当当前路由为 /home 时允许摇一摇触发3/4级页面自动拦截
// ignore: unused_element
final _shakeScopeObserver = ShakeScopeObserver(appRouter);
String? _handleDeepLinkRedirect(BuildContext context, GoRouterState state) {
final uri = state.uri;
final resolved = AppRouter.resolveDeepLinkUri(uri);
@@ -348,3 +353,17 @@ class _OhosRouteObserver extends NavigatorObserver {
Log.i('🟢 [OHOS] Route didStartUserGesture: ${route.settings.name}');
}
}
/// 摇一摇路由作用域观察者
/// 监听 GoRouter 路由变化,自动更新 ShakeDetector 的作用域
/// 仅当当前路由为 /home 时允许摇一摇触发
class ShakeScopeObserver {
ShakeScopeObserver(GoRouter router) {
router.routerDelegate.addListener(() {
final location =
router.routerDelegate.currentConfiguration.last.matchedLocation;
final scope = location == AppRoutes.home ? AppRoutes.home : '';
ShakeDetector.instance.setScope(scope);
});
}
}

View File

@@ -1,9 +1,9 @@
// ============================================================
// 闲言APP — 路由路径常量 + 路由辅助组件
// 创建时间: 2026-04-20
// 更新时间: 2026-05-28
// 更新时间: 2026-05-30
// 作用: 集中管理所有路由路径字符串,供各路由模块和页面统一引用
// 上次更新: 对调inspiration/discover路由路径inspiration为子页面discover为Tab主页面
// 上次更新: 新增imageCache路由
// ============================================================
import 'package:flutter/cupertino.dart';
@@ -27,6 +27,7 @@ class AppRoutes {
static const String passwordSettings = '/settings/password';
static const String securityQuestion = '/settings/security-question';
static const String dataManagement = '/settings/data';
static const String imageCache = '/settings/image-cache';
static const String accountDeletion = '/settings/account/deletion';
static const String fontManagement = '/settings/fonts';
static const String favorites = '/favorites';
@@ -94,6 +95,7 @@ class AppRoutes {
static const String ttsPlugin = '/settings/plugin/tts';
static const String permissionManagement = '/permission-management';
static const String privacyPolicy = '/privacy-policy';
static const String dataCollectionInfo = '/data-collection-info';
static const String logViewer = '/log-viewer';
static const String crashLog = '/crash-log';
static const String knowledgeGraph = '/knowledge-graph';
@@ -120,7 +122,9 @@ class AppRoutes {
static const String translateSettings = '/translate-settings';
static const String leisure = '/leisure';
static const String leisureSettings = '/leisure/settings';
static const String toolCenterSettings = '/tool-center/settings';
static const String onboarding = '/onboarding';
static const String experimentalFeatures = '/settings/experimental-features';
// ---- Deep Link 路由 ----
static const String deepFortune = '/fortune';

View File

@@ -1,9 +1,9 @@
// ============================================================
// 闲言APP — 设置模块路由
// 创建时间: 2026-05-22
// 更新时间: 2026-05-24
// 更新时间: 2026-05-30
// 作用: 设置相关页面的 GoRoute 定义
// 上次更新: 新增插件系统路由(plugin/translatePlugin/ttsPlugin)
// 上次更新: 新增imageCache路由
// ============================================================
import 'package:flutter/cupertino.dart';
@@ -24,12 +24,14 @@ import '../../features/mine/settings/presentation/more_settings_page.dart';
import '../../features/mine/settings/presentation/other_settings_page.dart';
import '../../features/mine/settings/presentation/privacy/permission_management_page.dart';
import '../../features/mine/settings/presentation/privacy/privacy_policy_page.dart';
import '../../features/mine/settings/presentation/privacy/data_collection_info_page.dart';
import '../../features/mine/settings/presentation/privacy/log_viewer_page.dart';
import '../../features/mine/settings/presentation/privacy/crash_log_page.dart';
import '../../features/mine/settings/presentation/lock/app_lock_settings_page.dart';
import '../../features/mine/settings/presentation/plugin/plugin_page.dart';
import '../../features/mine/settings/presentation/plugin/translate_plugin_page.dart';
import '../../features/mine/settings/presentation/plugin/tts_plugin_page.dart';
import '../../features/mine/settings/presentation/experimental_features_page.dart';
import '../utils/ui/page_transitions.dart';
import 'app_routes.dart';
@@ -145,6 +147,15 @@ List<GoRoute> buildSettingsRoutes(
pageBuilder: (context, state) =>
iosSlideTransition(state: state, child: const PrivacyPolicyPage()),
),
GoRoute(
path: AppRoutes.dataCollectionInfo,
name: 'data-collection-info',
parentNavigatorKey: rootNavigatorKey,
pageBuilder: (context, state) => iosSlideTransition(
state: state,
child: const DataCollectionInfoPage(),
),
),
GoRoute(
path: AppRoutes.logViewer,
name: 'log-viewer',
@@ -187,4 +198,13 @@ List<GoRoute> buildSettingsRoutes(
pageBuilder: (context, state) =>
iosSlideTransition(state: state, child: const TtsPluginPage()),
),
GoRoute(
path: AppRoutes.experimentalFeatures,
name: 'experimental-features',
parentNavigatorKey: rootNavigatorKey,
pageBuilder: (context, state) => iosSlideTransition(
state: state,
child: const ExperimentalFeaturesPage(),
),
),
];

View File

@@ -1,9 +1,9 @@
// ============================================================
// 闲言APP — 工具中心路由
// 创建时间: 2026-05-22
// 更新时间: 2026-05-28
// 更新时间: 2026-05-30
// 作用: 工具中心、AI聊天、翻译、文件传输、协作相关 GoRoute 定义
// 上次更新: 更新import路径 tool_center/inspiration → discover
// 上次更新: 新增工具中心设置页路由
// ============================================================
import 'package:flutter/cupertino.dart';
@@ -15,6 +15,7 @@ import '../../features/discover/presentation/pages/tool/china_colors_page.dart';
import '../../features/discover/presentation/pages/tool_list_page.dart';
import '../../features/discover/presentation/pages/tool/ocr_tool_page.dart';
import '../../features/discover/presentation/pages/tool/pinyin_tool_page.dart';
import '../../features/discover/presentation/pages/tool_center_settings_page.dart';
import '../../features/discover/presentation/pages/chat/chat_flow_page.dart';
import '../../features/discover/models/chat_session.dart';
import '../../features/discover/presentation/pages/chat/chat_settings_page.dart';
@@ -258,4 +259,11 @@ List<GoRoute> buildToolRoutes(GlobalKey<NavigatorState> rootNavigatorKey) => [
);
},
),
GoRoute(
path: AppRoutes.toolCenterSettings,
name: 'tool-center-settings',
parentNavigatorKey: rootNavigatorKey,
pageBuilder: (context, state) =>
iosSlideTransition(state: state, child: const ToolCenterSettingsPage()),
),
];

View File

@@ -1,9 +1,9 @@
/// ============================================================
/// 闲言APP — 权限管理服务
/// 创建时间: 2026-04-23
/// 更新时间: 2026-05-26
/// 更新时间: 2026-05-30
/// 作用: 统一管理应用权限请求,支持相机/相册/通知/位置/蓝牙/附近设备/麦克风/存储/网络/剪贴板/分享权限
/// 上次更新: 新增权限使用统计功能(recordUsage/getUsageStats)
/// 上次更新: 更新存储权限描述(区分READ/WRITE的API级别必要性)
/// ============================================================
import 'dart:io';
@@ -12,6 +12,7 @@ import 'package:flutter/cupertino.dart';
import 'package:permission_handler/permission_handler.dart';
import '../../storage/kv_storage.dart';
import '../device/shake_detector.dart';
/// 权限状态枚举
enum AppPermissionStatus {
@@ -117,9 +118,14 @@ enum AppPermission {
'存储空间',
Permission.storage,
CupertinoIcons.folder_fill,
'用于保存编辑的卡片、壁纸到本地,导出字体文件和数据。Android 12及以下版本需要此权限',
'用于保存编辑的卡片、壁纸到本地,导出字体文件和数据。仅Android 9及以下(API≤29)需要写入权限Android 10+使用分区存储Android 12及以下(API≤32)需要读取权限Android 13+由相册权限替代',
Color(0xFFFF9500),
usageScenes: ['保存卡片 — 导出到本地', '字体管理 — 下载字体文件', '数据导出 — 导出用户数据'],
usageScenes: [
'保存卡片 — 导出到本地',
'壁纸设置 — 保存壁纸',
'字体管理 — 下载字体文件',
'数据导出 — 导出用户数据',
],
),
network(
'网络连接',
@@ -151,6 +157,15 @@ enum AppPermission {
isVirtual: true,
group: PermissionGroup.system,
usageScenes: ['句子分享 — 分享到微信/QQ', '卡片分享 — 分享到社交平台', '日志导出 — 分享日志文件'],
),
shake(
'摇一摇',
Permission.notification,
CupertinoIcons.arrow_counterclockwise,
'摇晃手机触发特定功能,如换句、刷新等',
Color(0xFF5856D6),
isVirtual: true,
usageScenes: ['切换每日推荐句子', '刷新内容', '互动彩蛋'],
);
const AppPermission(
@@ -204,6 +219,24 @@ class PermissionService {
static const _usageStatsKey = 'permission_usage_stats';
static const _shakeEnabledKey = 'shake_enabled';
static bool get isShakeEnabled =>
KvStorage.getBool(_shakeEnabledKey, box: HiveBoxNames.userPrefs) ?? true;
static Future<void> setShakeEnabled(bool enabled) async {
await KvStorage.setBool(
_shakeEnabledKey,
enabled,
box: HiveBoxNames.userPrefs,
);
if (!enabled) {
try {
ShakeDetector.instance.stop();
} catch (_) {}
}
}
/// 记录权限使用
static void recordUsage(AppPermission permission) {
try {
@@ -283,7 +316,9 @@ class PermissionService {
final buffer = StringBuffer();
stats.forEach((key, value) {
if (buffer.isNotEmpty) buffer.write(';');
buffer.write('$key=${value['count']},${value['lastUsed']},${value['firstUsed'] ?? ''}');
buffer.write(
'$key=${value['count']},${value['lastUsed']},${value['firstUsed'] ?? ''}',
);
});
return buffer.toString();
}
@@ -332,6 +367,10 @@ class PermissionService {
return AppPermissionStatus.granted;
case AppPermission.share:
return AppPermissionStatus.granted;
case AppPermission.shake:
return isShakeEnabled
? AppPermissionStatus.granted
: AppPermissionStatus.denied;
default:
return AppPermissionStatus.granted;
}

View File

@@ -1,13 +1,14 @@
/// ============================================================
/// 闲言APP — 后台任务服务
/// 创建时间: 2026-05-25
/// 更新时间: 2026-05-25
/// 更新时间: 2026-05-30
/// 作用: 基于workmanager实现后台定时任务
/// 上次更新: 修复OHOS端原生通道未注册导致PlatformException
/// 上次更新: 增加用户协议同意检查,未同意则跳过后台任务初始化
/// ============================================================
import 'package:workmanager/workmanager.dart';
import '../../storage/kv_storage.dart';
import '../../utils/logger.dart';
import '../../utils/platform/platform_utils.dart' as pu;
import 'background_callback.dart';
@@ -27,6 +28,11 @@ class BackgroundTaskService {
Future<void> init() async {
if (_initialized) return;
if (!KvStorage.isOnboardingCompleted) {
Log.i('BackgroundTaskService: 用户未同意协议,跳过初始化');
return;
}
if (pu.isWeb) {
Log.i('BackgroundTaskService: Web平台跳过后台任务初始化');
_initialized = true;

View File

@@ -1,9 +1,9 @@
// ============================================================
// 闲言APP — 摇一摇检测器
// 创建时间: 2026-05-20
// 更新时间: 2026-05-29
// 更新时间: 2026-05-30
// 作用: 监听加速度传感器,检测摇一摇手势
// 上次更新: 改用处理器栈模式,仅当前可见页面的回调生效
// 上次更新: 新增路由作用域检查仅当前路由在home分支时才响应摇一摇
//
// 摇一摇生命周期管理(处理器栈模式):
//
@@ -15,6 +15,12 @@
// - 页面 deactivate 时: ShakeDetector.instance.popHandler('/route')
// - 仅栈顶 handler 生效,确保只有当前可见页面响应摇一摇
//
// 路由作用域:
// - setScope(scope) 由路由观察者调用,标识当前所在路由分支
// - 仅当 _activeScope 匹配栈顶 handler 路由前缀时才触发回调
// - 例如: _activeScope='/home' 且栈顶 handler route='/home' → 允许触发
// - 例如: _activeScope='/settings' 且栈顶 handler route='/home' → 禁止触发
//
// 错误用法(已废弃):
// - setHomePageActive(true/false) — 在 IndexedStack 中永远为 true
// - 在 dispose 中 stop() — 永远不会被调用
@@ -48,9 +54,24 @@ class ShakeDetector {
final List<_ShakeHandlerEntry> _handlerStack = [];
String? _activeScope;
bool get isEnabled => _isEnabled;
bool get hasActiveHandler => _handlerStack.isNotEmpty;
void setScope(String? scope) {
_activeScope = scope;
Log.i('ShakeDetector: setScope scope=$scope');
}
bool _isScopeAllowed() {
if (_activeScope == null) return true;
if (_activeScope!.isEmpty) return false;
if (_handlerStack.isEmpty) return false;
final topRoute = _handlerStack.last.route;
return topRoute == _activeScope || topRoute.startsWith('$_activeScope/');
}
void pushHandler(String route, ShakeCallback callback) {
_handlerStack.removeWhere((e) => e.route == route);
_handlerStack.add(_ShakeHandlerEntry(route, callback));
@@ -90,6 +111,12 @@ class ShakeDetector {
now.difference(_lastShakeTime!) > _minInterval) {
_lastShakeTime = now;
_consecutiveCount = 0;
if (!_isScopeAllowed()) {
Log.i(
'ShakeDetector: 摇一摇被作用域拦截 (scope=$_activeScope, topRoute=${_handlerStack.last.route})',
);
return;
}
Log.i('ShakeDetector: 检测到摇一摇 (acceleration=$acceleration)');
_handlerStack.last.callback.call();
HapticService.medium();

View File

@@ -0,0 +1,132 @@
// ============================================================
// 闲言APP — 协议同意后初始化器
// 创建时间: 2026-05-30
// 更新时间: 2026-05-30
// 作用: 将权限敏感的服务初始化延迟到用户同意协议后执行
// 上次更新: 首次创建从main.dart拆分权限敏感初始化
// ============================================================
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 'network/connectivity_service.dart';
import 'clipboard_monitor_service.dart';
import 'background/background_task_service.dart';
import 'notification/local_notification_service.dart';
import 'device/screen_wake_service.dart';
import 'device/battery_optimization_service.dart';
import 'notification/readlater_reminder_service.dart';
import 'data/home_widget_service.dart';
import 'readlater/sharing_receiver_service.dart';
import '../../features/discover/services/chat_migration_service.dart';
class PostAgreementInitializer {
PostAgreementInitializer._();
static bool _initialized = false;
static bool get isInitialized => _initialized;
static Future<void> init() async {
if (_initialized) return;
Log.i('PostAgreementInitializer: 开始初始化权限敏感服务...');
if (!pu.isWeb) {
try {
SharingReceiverService().init();
SharingReceiverService().setNavigatorKey(rootNavigatorKey);
Log.i('分享接收服务初始化完成');
} catch (e, st) {
Log.e('分享接收服务初始化失败', e, st);
}
}
if (!pu.isWeb) {
try {
await LocalNotificationService.init();
Log.i('本地通知服务初始化完成');
} catch (e, st) {
Log.e('本地通知服务初始化失败', e, st);
}
}
if (!pu.isWeb) {
try {
await ScreenWakeService.init();
Log.i('屏幕常亮服务初始化完成');
} catch (e, st) {
Log.e('屏幕常亮服务初始化失败', e, st);
}
}
if (!pu.isWeb) {
try {
await BatteryOptimizationService.init();
Log.i('电池优化服务初始化完成');
} catch (e, st) {
Log.e('电池优化服务初始化失败', e, st);
}
}
if (!pu.isWeb) {
try {
await ReadlaterReminderService.startMonitoring();
Log.i('稍后读提醒服务初始化完成');
} catch (e, st) {
Log.e('稍后读提醒服务初始化失败', e, st);
}
}
try {
await ChatMigrationService.migrateIfNeeded();
Log.i('聊天数据迁移检查完成');
} catch (e, st) {
Log.e('聊天数据迁移检查失败', e, st);
}
if (!pu.isWeb) {
try {
await HomeWidgetService.instance.init();
Log.i('桌面小组件服务初始化完成');
} catch (e, st) {
Log.e('桌面小组件服务初始化失败', e, st);
}
}
if (!pu.isWeb) {
try {
await ClipboardMonitorService.instance.initFromStore();
Log.i('剪贴板监控服务初始化完成');
} catch (e, st) {
Log.e('剪贴板监控服务初始化失败', e, st);
}
}
if (!pu.isWeb) {
try {
await ConnectivityService.init();
Log.i('网络状态检测服务初始化完成');
} catch (e, st) {
Log.e('网络状态检测服务初始化失败', e, st);
}
}
if (!pu.isWeb) {
try {
await BackgroundTaskService.instance.init();
Log.i('后台任务服务初始化完成');
} catch (e, st) {
Log.e('后台任务服务初始化失败', e, st);
}
}
_initialized = true;
Log.i('PostAgreementInitializer: 所有权限敏感服务初始化完成 ✓');
}
static bool shouldInit() {
return KvStorage.isOnboardingCompleted && !_initialized;
}
}

View File

@@ -1,19 +1,18 @@
//// 闲言APP 统一分享接收服务
// 创建时间: 2026-05-15
/// 更新时间: 2026-05-26
/// 更新时间: 2026-05-30
/// 作用: 接收其他App通过系统分享面板发送的内容写入稍后读会话
/// 上次更新: 使用SafeSharingReceiver中间件防止SharedMediaFile空指针崩溃
/// 上次更新: 添加确认弹窗,修复图片视频空白问题
/// ============================================================
import 'dart:async';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
import 'package:xianyan/core/utils/data/pattern_utils.dart';
import 'package:xianyan/core/utils/platform/platform_utils.dart' as pu;
import 'package:xianyan/core/router/app_nav_extension.dart';
import '../../../core/utils/logger.dart';
import '../../../core/router/app_router.dart';
@@ -170,8 +169,7 @@ class SharingReceiverService {
sourceApp: '分享',
);
Log.i('分享链接已写入稍后读: $text');
AppToast.showSuccess('🔗 链接已保存到稍后读');
_navigateToReadlater();
_showConfirmDialog('🔗 链接已保存到稍后读');
} else {
await ChatMessageService.sendText(
conversationId: _readLaterConvId,
@@ -181,8 +179,7 @@ class SharingReceiverService {
Log.i(
'分享文本已写入稍后读: ${text.length > 50 ? '${text.substring(0, 50)}...' : text}',
);
AppToast.showSuccess('📝 文本已保存到稍后读');
_navigateToReadlater();
_showConfirmDialog('📝 文本已保存到稍后读');
}
} catch (e) {
Log.e('分享文本处理失败', e);
@@ -211,8 +208,7 @@ class SharingReceiverService {
},
);
Log.i('分享图片已写入稍后读: $fileName');
AppToast.showSuccess('🖼️ 图片已保存到稍后读');
_navigateToReadlater();
_showConfirmDialog('🖼️ 图片已保存到稍后读');
} else if (mimeType.startsWith('video/')) {
await ChatMessageService.sendVideo(
conversationId: _readLaterConvId,
@@ -225,8 +221,7 @@ class SharingReceiverService {
},
);
Log.i('分享视频已写入稍后读: $fileName');
AppToast.showSuccess('🎬 视频已保存到稍后读');
_navigateToReadlater();
_showConfirmDialog('🎬 视频已保存到稍后读');
} else if (mimeType.startsWith('application/')) {
await ChatMessageService.sendDocument(
conversationId: _readLaterConvId,
@@ -237,8 +232,7 @@ class SharingReceiverService {
meta: {'mimeType': mimeType},
);
Log.i('分享文档已写入稍后读: $fileName');
AppToast.showSuccess('📄 文档已保存到稍后读');
_navigateToReadlater();
_showConfirmDialog('📄 文档已保存到稍后读');
} else {
await ChatMessageService.sendFile(
conversationId: _readLaterConvId,
@@ -246,8 +240,7 @@ class SharingReceiverService {
meta: {'mimeType': mimeType, 'fileName': fileName},
);
Log.i('分享文件已写入稍后读: $fileName');
AppToast.showSuccess('📁 文件已保存到稍后读');
_navigateToReadlater();
_showConfirmDialog('📁 文件已保存到稍后读');
}
} catch (e) {
Log.e('分享文件处理失败', e);
@@ -259,17 +252,30 @@ class SharingReceiverService {
// 工具方法
// ============================================================
void _navigateToReadlater() {
void _showConfirmDialog(String message) {
try {
final ctx = rootNavigatorKey.currentContext;
if (ctx != null && ctx.mounted) {
ctx.appGo(AppRoutes.readlaterChat);
Log.i('已自动导航到稍后读会话');
showCupertinoDialog<void>(
context: ctx,
builder: (_) => CupertinoAlertDialog(
title: const Text('已添加到稍后读'),
content: Text(message),
actions: [
CupertinoDialogAction(
isDefaultAction: true,
child: const Text('好的'),
onPressed: () => Navigator.pop(ctx),
),
],
),
);
} else {
Log.w('自动导航到稍后读失败: context不可用');
AppToast.showSuccess(message);
}
} catch (e) {
Log.w('自动导航到稍后读失败: $e');
Log.w('确认弹窗显示失败: $e');
AppToast.showSuccess(message);
}
}

View File

@@ -1,9 +1,9 @@
/// ============================================================
/// 闲言APP — 统一 KV 本地存储
/// 创建时间: 2026-04-20
/// 更新时间: 2026-05-27
/// 更新时间: 2026-05-30
/// 作用: 基于 Hive 的统一 KV 存储,合并原 KvStorage(SP) + AppKVStore(Hive)
/// 上次更新: 新增leisure box命名空间
/// 上次更新: 新增featureFlags box命名空间
/// ============================================================
import 'dart:convert';
@@ -31,6 +31,7 @@ class HiveBoxNames {
static const String wallpaperFavorites = 'wallpaper_favorites';
static const String translateHistory = 'translateHistory';
static const String leisure = 'leisure';
static const String imageCacheMeta = 'image_cache_meta';
static const List<String> all = [
app,
@@ -43,6 +44,7 @@ class HiveBoxNames {
chatMessages,
wallpaperFavorites,
leisure,
imageCacheMeta,
];
}