chore: 完成v1.2版本迭代优化与兼容修复

1. 基础适配升级:将iOS最低版本提升至15.5,更新Podfile与Xcode配置
2. 导航栈优化:使用push替代go保留路由栈,重构路由重定向逻辑
3. 多场景崩溃防护:
   - 新增目录获取降级逻辑,适配异常环境
   - 增加上下文挂载检查,防止PostFrame回调崩溃
   - 完善Hive初始化与Box访问的异常处理,实现空操作降级
4. 体验优化:
   - 修复摇一摇权限开关逻辑,更新个人中心文案
   - 新增请求超时保护与异常提示
   - 优化分享/保存相册的模拟器兼容处理
   - 重构引导页与初始化流程,修复数据丢失问题
5. 代码清理:移除重复路由注册,优化Widget预览页面生命周期
6. 细节优化:更新微信联系方式展示样式,完善日签与备份服务逻辑
This commit is contained in:
Developer
2026-06-04 10:26:42 +08:00
parent 67f26ff166
commit 33f59046b3
58 changed files with 872 additions and 3014 deletions

View File

@@ -1,9 +1,9 @@
/// ============================================================
/// 闲言APP — 桌面小部件管理页面
/// 创建时间: 2026-05-19
/// 更新时间: 2026-05-27
/// 更新时间: 2026-06-04
/// 作用: 管理桌面小部件的安装、数据推送、主题和平台兼容说明
/// 上次更新: 增加开发中弹窗提示,支持不再提醒
/// 上次更新: 修复_WidgetDataPreview生命周期问题(framework断言错误)增加disposed保护和超时机制
/// ============================================================
import 'dart:async';
@@ -18,6 +18,7 @@ import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_typography.dart';
import '../../../core/theme/app_radius.dart';
import '../../../core/services/data/home_widget_service.dart';
import '../../../core/utils/logger.dart';
import '../../../core/utils/platform/platform_helper.dart';
import '../../../shared/widgets/adaptive/adaptive_back_button.dart';
import '../../../shared/widgets/containers/glass_container.dart';
@@ -41,6 +42,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
ref.read(wp.widgetProvider.notifier).loadInstalledWidgets();
_showDevDialogIfNeeded();
});
@@ -154,6 +156,13 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
fontWeight: FontWeight.w600,
),
),
largeTitle: Text(
'桌面小部件',
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
),
),
trailing: _ThemeToggle(ext: ext),
backgroundColor: ext.bgPrimary.withValues(alpha: 0.85),
border: null,
@@ -199,6 +208,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
type,
);
return Padding(
key: ValueKey(type),
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.md,
vertical: AppSpacing.xs,
@@ -398,18 +408,15 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
}
}
class _ThemeToggle extends StatelessWidget {
class _ThemeToggle extends ConsumerWidget {
const _ThemeToggle({required this.ext});
final AppThemeExtension ext;
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
return GestureDetector(
onTap: () {
final notifier = ProviderScope.containerOf(
context,
).read(wp.widgetProvider.notifier);
notifier.pushThemeToAllWidgets();
ref.read(wp.widgetProvider.notifier).pushThemeToAllWidgets();
AppToast.showInfo('已推送当前主题到小部件');
},
child: Container(
@@ -515,8 +522,9 @@ class _PlatformCompatibilityCardState
),
),
AnimatedCrossFade(
firstChild: const SizedBox.shrink(),
firstChild: const SizedBox.shrink(key: ValueKey('collapsed')),
secondChild: Padding(
key: const ValueKey('expanded'),
padding: const EdgeInsets.only(top: AppSpacing.sm),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -866,34 +874,64 @@ class _WidgetDataPreview extends ConsumerStatefulWidget {
class _WidgetDataPreviewState extends ConsumerState<_WidgetDataPreview> {
Map<String, dynamic> _data = {};
bool _loading = true;
bool _disposed = false;
@override
void initState() {
super.initState();
_loadPreview();
// 使用addPostFrameCallback确保element完全挂载后再访问ref
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted || _disposed) return;
_loadPreview();
});
}
@override
void dispose() {
_disposed = true;
super.dispose();
}
Future<void> _loadPreview() async {
if (_disposed || !mounted) return;
try {
final data = await ref.read(homeWidgetServiceProvider).debugGetAllData();
if (mounted) {
setState(() {
_data = data;
_loading = false;
});
}
} catch (_) {
if (mounted) setState(() => _loading = false);
final service = ref.read(homeWidgetServiceProvider);
final data = await service.debugGetAllData().timeout(
const Duration(seconds: 5),
);
if (_disposed || !mounted) return;
setState(() {
_data = data;
_loading = false;
});
} on TimeoutException {
if (_disposed || !mounted) return;
setState(() => _loading = false);
Log.w('WidgetDataPreview: 加载预览数据超时');
} catch (e) {
if (_disposed || !mounted) return;
setState(() => _loading = false);
Log.e('WidgetDataPreview: 加载预览数据失败', e);
}
}
Future<void> _refreshData() async {
if (_disposed || !mounted) return;
setState(() => _loading = true);
try {
await ref.read(homeWidgetServiceProvider).updateWidget(widget.type);
final service = ref.read(homeWidgetServiceProvider);
await service.updateWidget(widget.type).timeout(
const Duration(seconds: 5),
);
await _loadPreview();
} catch (_) {
if (mounted) setState(() => _loading = false);
} on TimeoutException {
if (_disposed || !mounted) return;
setState(() => _loading = false);
Log.w('WidgetDataPreview: 刷新数据超时');
} catch (e) {
if (_disposed || !mounted) return;
setState(() => _loading = false);
Log.e('WidgetDataPreview: 刷新数据失败', e);
}
}