refactor: 完成项目架构重构,统一模块导入路径

- 清理大量废弃的 barrel 导出文件,移除冗余的中间导出层
- 修复所有相对路径导入错误,统一调整为扁平化模块引用
- 更新多平台 pubspec 版本号与依赖库版本
- 补充后端功能问题管理后台与脚本工具
- 调整部分页面的快捷方式文案适配新功能
- 更新部分翻译覆盖率与API文档
This commit is contained in:
Developer
2026-06-12 08:48:33 +08:00
parent 33e347dea7
commit f91be94e9c
560 changed files with 28489 additions and 14780 deletions

View File

@@ -20,12 +20,14 @@ 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 '../../../l10n/translation_resolver.dart';
import '../../../l10n/types/t.dart';
import '../../../shared/widgets/adaptive/adaptive_back_button.dart';
import '../../../shared/widgets/containers/glass_container.dart';
import '../../../shared/widgets/adaptive/responsive_layout.dart';
import '../../../shared/widgets/feedback/app_toast.dart';
import '../models/widget_type.dart';
import '../providers/widget_provider.dart' as wp;
import '../widget_type.dart';
import '../widget_provider.dart' as wp;
class WidgetManagementPage extends ConsumerStatefulWidget {
const WidgetManagementPage({super.key});
@@ -52,6 +54,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
void _showDevDialogIfNeeded() {
final dismissed = KvStorage.getBool('widget_dev_dismissed') ?? false;
if (dismissed) return;
final tw = ref.read(translationsProvider).widget;
showCupertinoDialog<void>(
context: context,
builder: (ctx) {
@@ -75,11 +78,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
'桌面小部件功能正在积极开发中,部分功能可能尚未完善或存在不稳定情况。\n\n'
'当前支持:基础小部件显示与数据推送\n'
'即将支持:更多小部件样式、交互操作、跨平台同步',
),
Text(tw.devDialogContent),
const SizedBox(height: 12),
GestureDetector(
onTap: () => setDialogState(() => dontRemind = !dontRemind),
@@ -96,7 +95,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
: CupertinoColors.systemGrey.resolveFrom(ctx),
),
const SizedBox(width: 8),
const Text('不再提醒', style: TextStyle(fontSize: 14)),
Text(tw.dontRemind, style: const TextStyle(fontSize: 14)),
],
),
),
@@ -105,7 +104,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
),
actions: [
CupertinoDialogAction(
child: const Text('查看实验功能'),
child: Text(tw.viewExperimentalFeatures),
onPressed: () {
Navigator.pop(ctx);
// 鸿蒙端暂不支持弹出toast提示
@@ -124,7 +123,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
}
Navigator.pop(ctx);
},
child: const Text('我知道了'),
child: Text(tw.iKnow),
),
],
),
@@ -136,11 +135,13 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
@override
Widget build(BuildContext context) {
final ext = AppTheme.ext(context);
final t = ref.watch(translationsProvider);
final tw = t.widget;
final wp.WidgetState widgetState = ref.watch(wp.widgetProvider);
final grouped = <int, List<WidgetType>>{};
for (final t in WidgetTypeX.all) {
grouped.putIfAbsent(t.priority, () => []).add(t);
for (final wt in WidgetTypeX.all) {
grouped.putIfAbsent(wt.priority, () => []).add(wt);
}
return CupertinoPageScaffold(
@@ -155,14 +156,14 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
CupertinoSliverNavigationBar(
leading: const AdaptiveBackButton(),
middle: Text(
'桌面小部件',
tw.title,
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
),
),
largeTitle: Text(
'桌面小部件',
tw.title,
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
@@ -179,7 +180,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
horizontal: AppSpacing.md,
vertical: AppSpacing.sm,
),
child: _PlatformCompatibilityCard(ext: ext),
child: _PlatformCompatibilityCard(ext: ext, tw: tw),
),
),
@@ -197,7 +198,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
_PriorityDot(priority: entry.key),
const SizedBox(width: 6),
Text(
_priorityLabel(entry.key),
_priorityLabel(entry.key, tw),
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
),
@@ -220,6 +221,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
),
child: _WidgetCard(
ext: ext,
tw: tw,
type: type,
isInstalled: isInstalled,
isAdding: _isAdding,
@@ -252,17 +254,17 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
);
}
String _priorityLabel(int p) => switch (p) {
0 => '核心小部件',
1 => '推荐小部件',
2 => '实用小部件',
_ => '趣味小部件',
String _priorityLabel(int p, TWidget tw) => switch (p) {
0 => tw.priorityCore,
1 => tw.priorityRecommended,
2 => tw.priorityPractical,
_ => tw.priorityFun,
};
void _handleAddWidget(WidgetType type) async {
// 鸿蒙端点击添加弹出toast提示
if (PlatformHelper.isHarmonyOS) {
AppToast.showInfo('敬请期待');
AppToast.showInfo(ref.read(translationsProvider).common.inDevelopment);
return;
}
if (_isAdding) return;
@@ -299,7 +301,8 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
.installedWidgets
.contains(type);
if (nowInstalled && !wasInstalled) {
AppToast.showInfo('${type.title} 已添加到桌面');
final tw = ref.read(translationsProvider).widget;
AppToast.showInfo(tw.addedToDesktop.replaceAll('{0}', type.localizedTitle(tw)));
} else if (!nowInstalled) {
_showManualAddGuide(type, isUnsupported: false);
}
@@ -347,30 +350,32 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
void _showManualAddGuide(WidgetType type, {required bool isUnsupported}) {
final ext = AppTheme.ext(context);
final tw = ref.read(translationsProvider).widget;
final typeTitle = type.localizedTitle(tw);
final steps = PlatformHelper.isHarmonyOS
? [
'1⃣ 长按桌面空白处',
'2⃣ 选择「服务卡片」',
'3⃣ 找到「闲言」',
'4⃣ 选择「${type.title}」并添加到桌面',
tw.harmonyStep1,
tw.harmonyStep2,
tw.harmonyStep3,
tw.harmonyStep4.replaceAll('{0}', typeTitle),
]
: PlatformHelper.isAndroid
? [
'1⃣ 长按桌面空白处',
'2⃣ 选择「小部件」',
'3⃣ 找到「闲言」',
'4⃣ 选择「${type.title}」拖动到桌面',
]
: [
'1⃣ 向右滑动到今日视图',
'2⃣ 滚动到底部点击「编辑」',
'3⃣ 找到「闲言」',
'4⃣ 选择「${type.title}」并添加',
];
? [
tw.androidStep1,
tw.androidStep2,
tw.androidStep3,
tw.androidStep4.replaceAll('{0}', typeTitle),
]
: [
tw.iosStep1,
tw.iosStep2,
tw.iosStep3,
tw.iosStep4.replaceAll('{0}', typeTitle),
];
final guideReason = isUnsupported
? '当前设备不支持快捷添加,请按以下步骤手动添加到桌面:'
: '快捷添加失败,请按以下步骤手动添加到桌面:';
? tw.unsupportedAddHint
: tw.failedAddHint;
showCupertinoDialog<void>(
context: context,
@@ -386,7 +391,7 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
color: ext.accent,
),
const SizedBox(width: AppSpacing.xs),
Text('添加「${type.title}'),
Text(tw.addWidgetTitle.replaceAll('{0}', typeTitle)),
],
),
),
@@ -411,16 +416,16 @@ class _WidgetManagementPageState extends ConsumerState<WidgetManagementPage> {
),
actions: [
CupertinoDialogAction(
child: const Text('推送数据'),
child: Text(tw.pushData),
onPressed: () {
Navigator.of(ctx).pop();
ref.read(wp.widgetProvider.notifier).pushDataToWidget(type);
AppToast.showInfo('已推送数据到${type.title}小部件');
AppToast.showInfo(tw.pushedDataToWidget.replaceAll('{0}', typeTitle));
},
),
CupertinoDialogAction(
isDefaultAction: true,
child: const Text('知道了'),
child: Text(tw.gotIt),
onPressed: () => Navigator.of(ctx).pop(),
),
],
@@ -435,10 +440,11 @@ class _ThemeToggle extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final tw = ref.watch(translationsProvider).widget;
return GestureDetector(
onTap: () {
ref.read(wp.widgetProvider.notifier).pushThemeToAllWidgets();
AppToast.showInfo('已推送当前主题到小部件');
AppToast.showInfo(tw.pushedThemeToWidget);
},
child: Container(
padding: const EdgeInsets.symmetric(
@@ -455,7 +461,7 @@ class _ThemeToggle extends ConsumerWidget {
Icon(CupertinoIcons.paintbrush_fill, size: 14, color: ext.accent),
const SizedBox(width: 4),
Text(
'同步主题',
tw.syncTheme,
style: AppTypography.caption1.copyWith(
color: ext.accent,
fontWeight: FontWeight.w600,
@@ -489,8 +495,9 @@ class _PriorityDot extends StatelessWidget {
}
class _PlatformCompatibilityCard extends StatefulWidget {
const _PlatformCompatibilityCard({required this.ext});
const _PlatformCompatibilityCard({required this.ext, required this.tw});
final AppThemeExtension ext;
final TWidget tw;
@override
State<_PlatformCompatibilityCard> createState() =>
@@ -504,6 +511,7 @@ class _PlatformCompatibilityCardState
@override
Widget build(BuildContext context) {
final ext = widget.ext;
final tw = widget.tw;
return GlassContainer(
depth: GlassDepth.elevated,
child: Column(
@@ -522,7 +530,7 @@ class _PlatformCompatibilityCardState
const SizedBox(width: AppSpacing.sm),
Expanded(
child: Text(
'平台兼容说明',
tw.platformCompatTitle,
style: AppTypography.subhead.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
@@ -554,21 +562,21 @@ class _PlatformCompatibilityCardState
ext: ext,
icon: '🤖',
name: 'Android',
desc: '功能不完整,原生侧存在通信问题',
desc: tw.androidCompatDesc,
),
const SizedBox(height: 4),
_PlatformRow(
ext: ext,
icon: '🍎',
name: 'iOS',
desc: 'WidgetKit + SwiftUI交互需 iOS 17+',
desc: tw.iosCompatDesc,
),
const SizedBox(height: 4),
_PlatformRow(
ext: ext,
icon: '🔴',
name: '鸿蒙',
desc: 'FormExtension + ArkUI能力受限系统限制刷新频率',
name: tw.badgeHarmony,
desc: tw.harmonyCompatDesc,
),
const SizedBox(height: AppSpacing.sm),
Container(
@@ -587,7 +595,7 @@ class _PlatformCompatibilityCardState
const SizedBox(width: AppSpacing.xs),
Expanded(
child: Text(
'点击「同步主题」可将当前深色/浅色模式推送到所有已安装小部件',
tw.syncThemeHint,
style: AppTypography.footnote.copyWith(
color: ext.textSecondary,
),
@@ -659,6 +667,7 @@ class _PlatformRow extends StatelessWidget {
class _WidgetCard extends StatelessWidget {
const _WidgetCard({
required this.ext,
required this.tw,
required this.type,
required this.isInstalled,
required this.isAdding,
@@ -666,6 +675,7 @@ class _WidgetCard extends StatelessWidget {
required this.onPin,
});
final AppThemeExtension ext;
final TWidget tw;
final WidgetType type;
final bool isInstalled;
final bool isAdding;
@@ -698,7 +708,7 @@ class _WidgetCard extends StatelessWidget {
Row(
children: [
Text(
type.title,
type.localizedTitle(tw),
style: AppTypography.subhead.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
@@ -710,7 +720,7 @@ class _WidgetCard extends StatelessWidget {
),
const SizedBox(height: 2),
Text(
type.subtitle,
type.localizedSubtitle(tw),
style: AppTypography.footnote.copyWith(
color: ext.textSecondary,
),
@@ -730,7 +740,7 @@ class _WidgetCard extends StatelessWidget {
borderRadius: AppRadius.pillBorder,
),
child: Text(
'已安装',
tw.installed,
style: AppTypography.caption2.copyWith(
color: CupertinoColors.systemGreen,
fontWeight: FontWeight.w600,
@@ -750,7 +760,7 @@ class _WidgetCard extends StatelessWidget {
child: isAdding
? const CupertinoActivityIndicator(radius: 8)
: Text(
'添加',
tw.add,
style: AppTypography.caption2.copyWith(
color: CupertinoColors.white,
fontWeight: FontWeight.w600,
@@ -762,13 +772,13 @@ class _WidgetCard extends StatelessWidget {
const SizedBox(height: AppSpacing.xs),
Row(
children: [
_PlatformBadges(ext: ext, type: type),
_PlatformBadges(ext: ext, tw: tw, type: type),
const Spacer(),
_DeepLinkBadge(ext: ext, route: type.deepLinkRoute),
],
),
const SizedBox(height: AppSpacing.sm),
_WidgetDataPreview(ext: ext, type: type),
_WidgetDataPreview(ext: ext, tw: tw, type: type),
],
),
);
@@ -812,8 +822,9 @@ class _PriorityBadge extends StatelessWidget {
}
class _PlatformBadges extends StatelessWidget {
const _PlatformBadges({required this.ext, required this.type});
const _PlatformBadges({required this.ext, required this.tw, required this.type});
final AppThemeExtension ext;
final TWidget tw;
final WidgetType type;
@override
@@ -824,7 +835,7 @@ class _PlatformBadges extends StatelessWidget {
const SizedBox(width: 4),
const _Badge(label: 'iOS', supported: true),
const SizedBox(width: 4),
_Badge(label: '鸿蒙', supported: type.supportsOhos),
_Badge(label: tw.badgeHarmony, supported: type.supportsOhos),
],
);
}
@@ -884,8 +895,9 @@ class _DeepLinkBadge extends StatelessWidget {
}
class _WidgetDataPreview extends ConsumerStatefulWidget {
const _WidgetDataPreview({required this.ext, required this.type});
const _WidgetDataPreview({required this.ext, required this.tw, required this.type});
final AppThemeExtension ext;
final TWidget tw;
final WidgetType type;
@override
@@ -957,23 +969,33 @@ class _WidgetDataPreviewState extends ConsumerState<_WidgetDataPreview> {
}
String _getPreviewText() {
final tw = widget.tw;
return switch (widget.type) {
WidgetType.dailySentence => '${_data['daily_sentence'] ?? '暂无数据'}',
WidgetType.readlater => '未读 ${_data['readlater_count'] ?? 0}',
WidgetType.dailyFortune => '${_data['fortune_text'] ?? '暂无数据'}',
WidgetType.countdown => '${_data['countdown_title'] ?? '暂无数据'}',
WidgetType.pomodoro => '剩余 ${_data['pomodoro_remaining'] ?? 0}s',
WidgetType.solarTerm => '${_data['solar_term_name'] ?? '暂无数据'}',
WidgetType.checkin => '连续 ${_data['checkin_days'] ?? 0}',
WidgetType.dailySentence =>
'${_data['daily_sentence'] ?? tw.previewNoData}',
WidgetType.readlater =>
tw.previewReadlaterCount.replaceAll('{0}', '${_data['readlater_count'] ?? 0}'),
WidgetType.dailyFortune =>
'${_data['fortune_text'] ?? tw.previewNoData}',
WidgetType.countdown =>
'${_data['countdown_title'] ?? tw.previewNoData}',
WidgetType.pomodoro =>
tw.previewPomodoroRemaining.replaceAll('{0}', '${_data['pomodoro_remaining'] ?? 0}'),
WidgetType.solarTerm =>
'${_data['solar_term_name'] ?? tw.previewNoData}',
WidgetType.checkin =>
tw.previewCheckinDays.replaceAll('{0}', '${_data['checkin_days'] ?? 0}'),
WidgetType.dailyWithCharacter =>
'${_data['daily_with_character_content'] ?? '暂无数据'}',
WidgetType.dailyCard => '日签卡片',
'${_data['daily_with_character_content'] ?? tw.previewNoData}',
WidgetType.dailyCard =>
tw.previewDailyCard,
};
}
@override
Widget build(BuildContext context) {
final ext = widget.ext;
final tw = widget.tw;
return Container(
padding: const EdgeInsets.all(AppSpacing.sm),
decoration: BoxDecoration(
@@ -988,7 +1010,7 @@ class _WidgetDataPreviewState extends ConsumerState<_WidgetDataPreview> {
Icon(CupertinoIcons.eye_fill, size: 12, color: ext.textSecondary),
const SizedBox(width: 4),
Text(
'数据预览',
tw.dataPreview,
style: AppTypography.caption2.copyWith(
color: ext.textSecondary,
fontWeight: FontWeight.w600,
@@ -1003,7 +1025,7 @@ class _WidgetDataPreviewState extends ConsumerState<_WidgetDataPreview> {
Icon(CupertinoIcons.refresh, size: 12, color: ext.accent),
const SizedBox(width: 2),
Text(
'刷新',
tw.refresh,
style: AppTypography.caption2.copyWith(
color: ext.accent,
fontWeight: FontWeight.w500,

View File

@@ -1,9 +1,9 @@
/// ============================================================
/// APP
/// : 2026-05-19
/// : 2026-06-05
/// : 2026-06-12
/// :
/// : PlatformCapabilities能力查询补充homeWidget判断
/// : providers/widget根目录
/// ============================================================
import 'dart:ui';
@@ -16,7 +16,7 @@ import 'package:xianyan/core/utils/platform/platform_capability.dart';
import '../../../core/services/data/home_widget_service.dart';
import '../../../core/utils/logger.dart';
import '../models/widget_type.dart';
import 'widget_type.dart';
enum PinWidgetResult { success, unsupported, failed }

View File

@@ -1,12 +1,13 @@
/// ============================================================
/// APP
/// : 2026-05-19
/// : 2026-05-20
/// : 2026-06-12
/// :
/// : dailyWithCharacter拾光角色小组件类型
/// : models/widget根目录
/// ============================================================
import 'package:flutter/cupertino.dart';
import '../../../l10n/types/t_widget.dart';
enum WidgetType {
dailySentence,
@@ -47,6 +48,32 @@ extension WidgetTypeX on WidgetType {
WidgetType.dailyWithCharacter => '拾光角色+每日推荐句子',
};
///
String localizedTitle(TWidget tw) => switch (this) {
WidgetType.dailySentence => tw.typeDailySentence,
WidgetType.readlater => tw.typeReadlater,
WidgetType.dailyCard => tw.typeDailyCard,
WidgetType.dailyFortune => tw.typeDailyFortune,
WidgetType.countdown => tw.typeCountdown,
WidgetType.pomodoro => tw.typePomodoro,
WidgetType.solarTerm => tw.typeSolarTerm,
WidgetType.checkin => tw.typeCheckin,
WidgetType.dailyWithCharacter => tw.typeDailyWithCharacter,
};
///
String localizedSubtitle(TWidget tw) => switch (this) {
WidgetType.dailySentence => tw.subtitleDailySentence,
WidgetType.readlater => tw.subtitleReadlater,
WidgetType.dailyCard => tw.subtitleDailyCard,
WidgetType.dailyFortune => tw.subtitleDailyFortune,
WidgetType.countdown => tw.subtitleCountdown,
WidgetType.pomodoro => tw.subtitlePomodoro,
WidgetType.solarTerm => tw.subtitleSolarTerm,
WidgetType.checkin => tw.subtitleCheckin,
WidgetType.dailyWithCharacter => tw.subtitleDailyWithCharacter,
};
IconData get icon => switch (this) {
WidgetType.dailySentence => CupertinoIcons.doc_text_fill,
WidgetType.readlater => CupertinoIcons.book_fill,
@@ -132,13 +159,13 @@ extension WidgetTypeX on WidgetType {
String get deepLinkRoute => switch (this) {
WidgetType.dailySentence => '/home',
WidgetType.readlater => '/home?tab=readlater',
WidgetType.dailyCard => '/home',
WidgetType.dailyFortune => '/inspiration',
WidgetType.countdown => '/widget-management',
WidgetType.pomodoro => '/widget-management',
WidgetType.solarTerm => '/inspiration',
WidgetType.checkin => '/signin',
WidgetType.readlater => '/readlater',
WidgetType.dailyCard => '/daily-card',
WidgetType.dailyFortune => '/daily-fortune',
WidgetType.countdown => '/countdown',
WidgetType.pomodoro => '/pomodoro',
WidgetType.solarTerm => '/solar-term',
WidgetType.checkin => '/achievement/checkin',
WidgetType.dailyWithCharacter => '/home',
};