diff --git a/.gitignore b/.gitignore index 6a14bc9d..988349fd 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ app.*.map.json # Trae IDE .trae/ +docs/toolsapi/thinkphp diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b814260..e29a0af1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,45 @@ 所有重要变更均记录于此文件。格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/)。 -> 保留最近 10 个版本(v6.79.0 ~ v6.88.0)。更早版本已归档至软件特性功能文档。 +> 保留最近 10 个版本(v6.80.0 ~ v6.89.0)。更早版本已归档至软件特性功能文档。 + +*** + +## [v6.89.0] - 2026-06-17 + +### 🛠 评分弹窗商店名称多语言 + Beta问卷按钮隐藏跨平台修复 + +#### 1. "给个好评"弹窗商店名称由硬编码"Google Play"改为多语言"应用商店" +- **需求**: Android 端点击"给个好评"后,跳转确认弹窗显示硬编码英文"Google Play",未接入多语言系统,风格不统一 +- **实现**: + - `t_about.dart` 新增 `appStore` 翻译字段(构造函数 + 字段定义 + toMap + fromMap) + - 14 种语言文件全部补充 `appStore` 翻译: + - zh_cn: 应用商店 / zh_tw: 應用商店 / en: App Store / ru: Магазин приложений + - pt: Loja de aplicativos / ko: 앱 스토어 / ja: アプリストア / it: App Store + - hi: ऐप स्टोर / fr: App Store / es: Tienda de aplicaciones / de: App Store + - bn: অ্যাপ স্টোর / ar: متجر التطبيقات + - `app_store_service.dart` 的 `getStoreName` 方法:Android 分支由 `return 'Google Play'` 改为 `return t.about.appStore` +- **影响**: `profile_page.dart` 和 `about_page.dart` 的"给个好评"/"评价应用"入口弹窗文案自动跟随系统语言 + +#### 2. Beta 页面"填写问卷"按钮提交后隐藏逻辑跨平台生效 +- **问题**: 问卷提交后按钮只在 iOS 端隐藏,Android 等端不隐藏 +- **根因**: + 1. `_QuestionnaireSheet` 不符合条件关闭时调用 `_markQuestionnaireSubmitted()` 未 `await`,`Navigator.pop` 可能在 SharedPreferences 写入完成前执行 + 2. Sheet 关闭后仅依赖 `_loadQuestionnaireSubmitted()` 异步重读 SharedPreferences 更新 UI,跨平台存在时序差异(iOS NSUserDefaults 内存同步快,Android SharedPreferences.apply 异步落盘) +- **修复**: + - `_QuestionnaireSheet` 的两处关闭按钮改为 `Navigator.pop(context, true)` 返回已提交标记 + - `_showQuestionnaire` 接收 Sheet 返回值,`submitted == true` 时立即 `setState` 更新 `_questionnaireSubmitted`,不再依赖 SharedPreferences 时序 + - 不符合条件关闭分支改为 `async` + `await _markQuestionnaireSubmitted()`,并在 await 前获取 `Navigator.of(context)` 避免 `use_build_context_synchronously` + - 保留 `_loadQuestionnaireSubmitted()` 作为兜底,确保与持久化状态最终一致 +- **效果**: 所有平台(iOS/Android/Windows/macOS)问卷提交后按钮立即隐藏 + +#### 修改文件 +| 文件 | 变更 | +|---|---| +| `l10n/types/t_about.dart` | 新增 `appStore` 字段(构造/定义/toMap/fromMap) | +| `l10n/languages/*.dart` (14 个) | 补充 `appStore` 多语言翻译 | +| `core/services/app_store_service.dart` | Android 端商店名称改用 `t.about.appStore` | +| `features/settings/presentation/experimental_features_page.dart` | 问卷 Sheet 返回值即时更新 UI + await 修复时序 | *** @@ -312,49 +350,3 @@ | `l10n/languages/en.dart` | 新增英文翻译:Remember Account | | `features/auth/presentation/login_form_sections.dart` | `PasswordFormSection` 新增 `isRemembered`/`onToggleRemember` 参数,将忘记密码按钮改为 Row 布局(左:记住账户复选框,右:忘记密码) | | `features/auth/presentation/login_page.dart` | 新增 `_rememberAccount` 状态、`_saveRememberAccount()` 方法;`_loadLastLoginAccount()` 读取 `remember_account` 偏好;`_handlePasswordLogin()` 登录成功后保存/清除账户 | - -*** - -## [v6.79.0] - 2026-06-17 - -### 🔒 隐私合规 — 修复安卓端自启动问题(androidx.glance.appwidget) - -#### 问题描述 -1. 应用商店审核发现:`androidx.glance.appwidget` SDK 在应用退出后触发自启动(1次/秒),无隐私文本覆盖 -2. 审核依据:《个人信息保护法》要求 APP 未向用户明示且未经用户同意,不得存在频繁自启动行为 -3. 根因:`home_widget` 包引入了 `androidx.glance:glance-appwidget:1.1.1` 依赖,项目未使用 Glance Widget 但该库被打包进 APK,其内部 `GlanceAppWidgetReceiver`/`GlanceAppWidgetService` 被系统广播触发导致自启动 -4. 次要问题:8个桌面小部件 Provider 在系统定时 `APPWIDGET_UPDATE` 广播触发时,未检查隐私协议状态即执行数据读取 - -#### 修复内容 - -**1. 彻底移除 androidx.glance.appwidget 依赖** -| 文件 | 变更 | -|---|---| -| `packages/home_widget/android/build.gradle` | 移除 `implementation "androidx.glance:glance-appwidget:1.1.1"` 依赖 | -| `HomeWidgetGlanceWidgetReceiver.kt` | 删除未使用的 Glance Receiver 源文件 | -| `HomeWidgetGlanceState.kt` | 删除未使用的 Glance State 源文件 | - -**2. AndroidManifest 排除 Glance 组件合并** -| 文件 | 变更 | -|---|---| -| `AndroidManifest.xml` | 新增 `tools:node="remove"` 移除 `GlanceAppWidgetReceiver` 和 `GlanceAppWidgetService`,防止残留库通过 manifest merge 注入 | - -**3. 所有 Widget Provider 增加隐私协议守门** -| 文件 | 变更 | -|---|---| -| `PrivacyAwareHomeWidgetProvider.kt` | 新建基类,在 `onUpdate` 中检查 `agreement_accepted` 标志,未同意时显示占位视图不读取任何业务数据 | -| `widget_privacy_placeholder.xml` | 新建隐私占位布局,提示"请先同意隐私政策" | -| `DailySentenceProvider.kt` | 改为继承 `PrivacyAwareHomeWidgetProvider`,`onUpdate` → `onUpdateWithAgreement` | -| `ReadlaterProvider.kt` | 同上 | -| `DailyCardProvider.kt` | 同上 | -| `FortuneProvider.kt` | 同上 | -| `CountdownProvider.kt` | 同上 | -| `PomodoroProvider.kt` | 同上 | -| `SolarTermProvider.kt` | 同上 | -| `CheckinProvider.kt` | 同上 | -| `CtcLatestNoteProvider.kt` | 同上 | - -#### 合规影响 -- `androidx.glance.appwidget` 自启动行为彻底消除(依赖移除 + Manifest 排除 + 源文件删除三重防护) -- Widget Provider 在用户未同意隐私政策前不执行任何数据操作,仅显示占位提示 -- 与现有 `SplashActivity` 协议守门机制形成完整闭环 diff --git a/lib/core/services/app_store_service.dart b/lib/core/services/app_store_service.dart index 06547a9d..1ef44f23 100644 --- a/lib/core/services/app_store_service.dart +++ b/lib/core/services/app_store_service.dart @@ -3,7 +3,7 @@ /// 创建时间: 2026-06-17 /// 更新时间: 2026-06-17 /// 作用: 根据平台和语言地区生成正确的应用商店URL -/// 上次更新: 初始版本,支持iOS/Android/鸿蒙/Windows/macOS多平台多地区 +/// 上次更新: Android端商店名称由硬编码"Google Play"改为多语言"应用商店"(t.about.appStore) /// ============================================================ import 'package:flutter/widgets.dart'; @@ -78,14 +78,16 @@ class AppStoreService { /// [locale] 当前语言Locale,用于判断地区 static Uri getIOSAppStoreUrl(Locale locale) { final countryCode = locale.countryCode ?? ''; - final appId = _iosAppIdsByRegion[countryCode.toUpperCase()] ?? - _iosDefaultAppId; + 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)'); + Log.d( + 'AppStoreService: iOS URL = $url (region: $countryCode, appId: $appId)', + ); return Uri.parse(url); } @@ -167,9 +169,15 @@ class AppStoreService { } /// 获取应用商店显示名称 + /// + /// 根据当前平台返回对应应用商店的本地化名称。 + /// - iOS/macOS: App Store + /// - Android: 应用商店(多语言,使用 t.about.appStore) + /// - 鸿蒙: 华为应用市场(多语言) + /// - Windows: Microsoft Store static String getStoreName(T t) { if (pu.isIOS) return 'App Store'; - if (pu.isAndroid) return 'Google Play'; + if (pu.isAndroid) return t.about.appStore; if (pu.isOhos) return t.about.huaweiStore; if (pu.isWindows) return 'Microsoft Store'; if (pu.isMacOS) return 'App Store'; diff --git a/lib/features/settings/presentation/experimental_features_page.dart b/lib/features/settings/presentation/experimental_features_page.dart index 971e464d..ed580d45 100644 --- a/lib/features/settings/presentation/experimental_features_page.dart +++ b/lib/features/settings/presentation/experimental_features_page.dart @@ -3,7 +3,7 @@ /// 创建时间: 2026-05-30 /// 更新时间: 2026-06-17 /// 作用: 展示开发中/测试中/预览中的功能列表和问题列表,接入远程FeatureFlag服务 -/// 上次更新: 问卷进度实时保存(草稿持久化)、输入法遮挡修复、硬编码替换为多语言翻译键 +/// 上次更新: 修复问卷提交后按钮隐藏只在iOS端生效的问题——Sheet返回值即时更新UI + await修复时序 /// ============================================================ import 'package:flutter/cupertino.dart'; @@ -108,34 +108,41 @@ class _ExperimentalFeaturesPageState ), // 底部问卷按钮(提交后隐藏) if (!_questionnaireSubmitted) - Padding( - padding: const EdgeInsets.fromLTRB( - AppSpacing.md, AppSpacing.sm, AppSpacing.md, AppSpacing.md, - ), - child: SizedBox( - width: double.infinity, - child: CupertinoButton( - color: ext.accent, - borderRadius: BorderRadius.circular(10), - padding: const EdgeInsets.symmetric(vertical: 14), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(CupertinoIcons.question_circle_fill, size: 18, color: ext.textOnAccent), - const SizedBox(width: 6), - Text( - t.beta.questionnaireBtn, - style: AppTypography.subhead.copyWith( + Padding( + padding: const EdgeInsets.fromLTRB( + AppSpacing.md, + AppSpacing.sm, + AppSpacing.md, + AppSpacing.md, + ), + child: SizedBox( + width: double.infinity, + child: CupertinoButton( + color: ext.accent, + borderRadius: BorderRadius.circular(10), + padding: const EdgeInsets.symmetric(vertical: 14), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + CupertinoIcons.question_circle_fill, + size: 18, color: ext.textOnAccent, - fontWeight: FontWeight.w600, ), - ), - ], + const SizedBox(width: 6), + Text( + t.beta.questionnaireBtn, + style: AppTypography.subhead.copyWith( + color: ext.textOnAccent, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + onPressed: () => _showQuestionnaire(ext, t), ), - onPressed: () => _showQuestionnaire(ext, t), ), ), - ), ], ), ), @@ -145,15 +152,22 @@ class _ExperimentalFeaturesPageState // ---- 问卷 ---- /// 弹出问卷Sheet + /// + /// Sheet 关闭后返回是否已提交: + /// - 优先使用返回值立即更新 UI(避免 SharedPreferences 跨平台时序差异) + /// - 再异步读取 SharedPreferences 作为兜底,确保状态最终一致 Future _showQuestionnaire(AppThemeExtension ext, T t) async { - await showCupertinoModalPopup( + final submitted = await showCupertinoModalPopup( context: context, builder: (_) => _QuestionnaireSheet(ext: ext, t: t), ); - // Sheet关闭后刷新问卷提交状态 - if (mounted) { - _loadQuestionnaireSubmitted(); + if (!mounted) return; + // 立即根据 Sheet 返回值更新 UI(所有平台一致生效) + if (submitted == true && !_questionnaireSubmitted) { + setState(() => _questionnaireSubmitted = true); } + // 异步刷新作为兜底,确保与持久化状态一致 + _loadQuestionnaireSubmitted(); } // ---- 分段控制器 ---- @@ -234,7 +248,11 @@ class _ExperimentalFeaturesPageState ); } - Widget _buildFlagsList(AppThemeExtension ext, T t, List flags) { + Widget _buildFlagsList( + AppThemeExtension ext, + T t, + List flags, + ) { // 仅显示服务端启用的功能标志 final visibleFlags = flags.where((f) => f.enabled).toList(); @@ -262,7 +280,12 @@ class _ExperimentalFeaturesPageState ext: ext, t: t, onToggle: (key, enabled) { - _showToggleConfirmDialog(ext, t, visibleFlags[index], enabled); + _showToggleConfirmDialog( + ext, + t, + visibleFlags[index], + enabled, + ); }, ); }, @@ -674,7 +697,10 @@ class _RemoteFeatureCard extends StatelessWidget { Icon(CupertinoIcons.group_solid, size: 12, color: ext.textHint), const SizedBox(width: 4), Text( - t.beta.rolloutPercentage.replaceAll('{0}', '${(flag.rolloutPercentage * 100).toInt()}'), + t.beta.rolloutPercentage.replaceAll( + '{0}', + '${(flag.rolloutPercentage * 100).toInt()}', + ), style: AppTypography.caption2.copyWith(color: ext.textHint), ), if (flag.targetGroup != null) ...[ @@ -692,12 +718,15 @@ class _RemoteFeatureCard extends StatelessWidget { /// 显示关联问题数量 Widget _buildIssueCount() { - final pendingCount = - flag.issues.where((i) => i.status == IssueStatus.pending).length; - final fixingCount = - flag.issues.where((i) => i.status == IssueStatus.fixing).length; - final fixedCount = - flag.issues.where((i) => i.status == IssueStatus.fixed).length; + final pendingCount = flag.issues + .where((i) => i.status == IssueStatus.pending) + .length; + final fixingCount = flag.issues + .where((i) => i.status == IssueStatus.fixing) + .length; + final fixedCount = flag.issues + .where((i) => i.status == IssueStatus.fixed) + .length; return Row( children: [ @@ -917,16 +946,31 @@ class _QuestionnaireSheetState extends State<_QuestionnaireSheet> { void _answer(bool yes) { if (_step == 0) { // 问题1: 了解Google Play - if (!yes) { setState(() => _step = -1); _clearDraft(); return; } - setState(() => _step = 1); _saveDraft(); + if (!yes) { + setState(() => _step = -1); + _clearDraft(); + return; + } + setState(() => _step = 1); + _saveDraft(); } else if (_step == 1) { // 问题2: 有GMS设备 - if (!yes) { setState(() => _step = -1); _clearDraft(); return; } - setState(() => _step = 2); _saveDraft(); + if (!yes) { + setState(() => _step = -1); + _clearDraft(); + return; + } + setState(() => _step = 2); + _saveDraft(); } else if (_step == 2) { // 问题3: 愿意参与内测 - if (!yes) { setState(() => _step = -1); _clearDraft(); return; } - setState(() => _step = 3); _saveDraft(); + if (!yes) { + setState(() => _step = -1); + _clearDraft(); + return; + } + setState(() => _step = 3); + _saveDraft(); } } @@ -946,7 +990,10 @@ class _QuestionnaireSheetState extends State<_QuestionnaireSheet> { // 提交成功,保存标记并清除草稿 await _markQuestionnaireSubmitted(); _clearDraft(); - setState(() { _step = 4; _isSubmitting = false; }); + setState(() { + _step = 4; + _isSubmitting = false; + }); } else { AppToast.showError(widget.t.beta.qSubmitFailed); setState(() => _isSubmitting = false); @@ -982,7 +1029,8 @@ class _QuestionnaireSheetState extends State<_QuestionnaireSheet> { children: [ // 拖拽指示器 Container( - width: 36, height: 5, + width: 36, + height: 5, margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: ext.textHint.withValues(alpha: 0.3), @@ -991,7 +1039,10 @@ class _QuestionnaireSheetState extends State<_QuestionnaireSheet> { ), if (_step >= 0 && _step <= 3) ...[ // 进度 - Text('${_step + 1}/4', style: AppTypography.caption1.copyWith(color: ext.textHint)), + Text( + '${_step + 1}/4', + style: AppTypography.caption1.copyWith(color: ext.textHint), + ), const SizedBox(height: 12), // 问题 Text( @@ -1008,7 +1059,13 @@ class _QuestionnaireSheetState extends State<_QuestionnaireSheet> { child: CupertinoButton( color: ext.accent, borderRadius: BorderRadius.circular(10), - child: Text(t.beta.qYes, style: TextStyle(color: ext.textOnAccent, fontWeight: FontWeight.w600)), + child: Text( + t.beta.qYes, + style: TextStyle( + color: ext.textOnAccent, + fontWeight: FontWeight.w600, + ), + ), onPressed: () => _answer(true), ), ), @@ -1017,7 +1074,10 @@ class _QuestionnaireSheetState extends State<_QuestionnaireSheet> { child: CupertinoButton( color: ext.bgElevated, borderRadius: BorderRadius.circular(10), - child: Text(t.beta.qNo, style: TextStyle(color: ext.textSecondary)), + child: Text( + t.beta.qNo, + style: TextStyle(color: ext.textSecondary), + ), onPressed: () => _answer(false), ), ), @@ -1045,7 +1105,13 @@ class _QuestionnaireSheetState extends State<_QuestionnaireSheet> { borderRadius: BorderRadius.circular(10), child: _isSubmitting ? CupertinoActivityIndicator(color: ext.textOnAccent) - : Text(t.beta.qSubmit, style: TextStyle(color: ext.textOnAccent, fontWeight: FontWeight.w600)), + : Text( + t.beta.qSubmit, + style: TextStyle( + color: ext.textOnAccent, + fontWeight: FontWeight.w600, + ), + ), onPressed: _isSubmitting ? null : _submitEmail, ), ), @@ -1054,39 +1120,68 @@ class _QuestionnaireSheetState extends State<_QuestionnaireSheet> { // 不符合条件 Icon(CupertinoIcons.info_circle, size: 48, color: ext.textHint), const SizedBox(height: 12), - Text(t.beta.qEndThankYou, style: AppTypography.headline.copyWith(color: ext.textPrimary)), + Text( + t.beta.qEndThankYou, + style: AppTypography.headline.copyWith(color: ext.textPrimary), + ), const SizedBox(height: 8), - Text(t.beta.qEndNotQualified, style: AppTypography.subhead.copyWith(color: ext.textSecondary), textAlign: TextAlign.center), + Text( + t.beta.qEndNotQualified, + style: AppTypography.subhead.copyWith(color: ext.textSecondary), + textAlign: TextAlign.center, + ), const SizedBox(height: 20), SizedBox( width: double.infinity, child: CupertinoButton( color: ext.bgElevated, borderRadius: BorderRadius.circular(10), - child: Text(t.beta.close, style: TextStyle(color: ext.textSecondary)), - onPressed: () { + child: Text( + t.beta.close, + style: TextStyle(color: ext.textSecondary), + ), + onPressed: () async { // 不符合条件关闭时也保存标记并清除草稿 - _markQuestionnaireSubmitted(); + // 使用 await 确保写入完成后再关闭,避免跨平台时序问题 + final navigator = Navigator.of(context); + await _markQuestionnaireSubmitted(); _clearDraft(); - Navigator.pop(context); + if (mounted) navigator.pop(true); }, ), ), ] else ...[ // 完成 - Icon(CupertinoIcons.checkmark_circle_fill, size: 48, color: ext.successColor), + Icon( + CupertinoIcons.checkmark_circle_fill, + size: 48, + color: ext.successColor, + ), const SizedBox(height: 12), - Text(t.beta.qSubmitSuccess, style: AppTypography.headline.copyWith(color: ext.textPrimary)), + Text( + t.beta.qSubmitSuccess, + style: AppTypography.headline.copyWith(color: ext.textPrimary), + ), const SizedBox(height: 8), - Text(t.beta.qEndThanks, style: AppTypography.subhead.copyWith(color: ext.textSecondary), textAlign: TextAlign.center), + Text( + t.beta.qEndThanks, + style: AppTypography.subhead.copyWith(color: ext.textSecondary), + textAlign: TextAlign.center, + ), const SizedBox(height: 20), SizedBox( width: double.infinity, child: CupertinoButton( color: ext.accent, borderRadius: BorderRadius.circular(10), - child: Text(t.beta.gotIt, style: TextStyle(color: ext.textOnAccent, fontWeight: FontWeight.w600)), - onPressed: () => Navigator.pop(context), + child: Text( + t.beta.gotIt, + style: TextStyle( + color: ext.textOnAccent, + fontWeight: FontWeight.w600, + ), + ), + onPressed: () => Navigator.pop(context, true), ), ), ], diff --git a/lib/l10n/languages/ar.dart b/lib/l10n/languages/ar.dart index b4810499..54b050f4 100644 --- a/lib/l10n/languages/ar.dart +++ b/lib/l10n/languages/ar.dart @@ -1367,6 +1367,7 @@ const ar = T( rateDialogContent2: 'دعمكم هو حافزنا', laterButton: 'لاحقاً', huaweiStore: 'Huawei AppGallery', + appStore: 'متجر التطبيقات', goRate: 'تقييم', emailHint1: 'إذا لم يكن هناك رد خلال 24 ساعة، جرب بريداً آخر', emailHint2: 'أي بريد إلكتروني مناسب للتواصل', diff --git a/lib/l10n/languages/bn.dart b/lib/l10n/languages/bn.dart index 0170d10a..f139eab7 100644 --- a/lib/l10n/languages/bn.dart +++ b/lib/l10n/languages/bn.dart @@ -1376,6 +1376,7 @@ const bn = T( rateDialogContent2: 'আপনার সমর্থন আমাদের অনুপ্রেরণা', laterButton: 'পরে', huaweiStore: 'Huawei AppGallery', + appStore: 'অ্যাপ স্টোর', goRate: 'মূল্যায়ন', emailHint1: '২৪ ঘন্টায় কোনো উত্তর না পেলে অন্য ইমেইল চেষ্টা করুন', emailHint2: 'যেকোনো ইমেইল দিয়ে যোগাযোগ করুন', diff --git a/lib/l10n/languages/de.dart b/lib/l10n/languages/de.dart index 7cb8ad87..2509ffaa 100644 --- a/lib/l10n/languages/de.dart +++ b/lib/l10n/languages/de.dart @@ -1375,6 +1375,7 @@ const de = T( rateDialogContent2: 'Ihre Unterstützung ist unsere Motivation', laterButton: 'Später', huaweiStore: 'Huawei AppGallery', + appStore: 'App Store', goRate: 'Bewerten', emailHint1: 'Wenn innerhalb von 24h keine Antwort, andere E-Mail versuchen', emailHint2: 'Jede E-Mail ist für die Kontaktaufnahme geeignet', diff --git a/lib/l10n/languages/en.dart b/lib/l10n/languages/en.dart index 57df02c7..69304626 100644 --- a/lib/l10n/languages/en.dart +++ b/lib/l10n/languages/en.dart @@ -1386,6 +1386,7 @@ const en = T( rateDialogContent2: 'Your support is our motivation', laterButton: 'Later', huaweiStore: 'Huawei AppGallery', + appStore: 'App Store', goRate: 'Rate', emailHint1: 'If no reply within 24h, try another email', emailHint2: 'Any email is fine to contact', diff --git a/lib/l10n/languages/es.dart b/lib/l10n/languages/es.dart index 70b2b5c2..9a70795b 100644 --- a/lib/l10n/languages/es.dart +++ b/lib/l10n/languages/es.dart @@ -1385,6 +1385,7 @@ const es = T( rateDialogContent2: 'Tu apoyo es nuestra motivación', laterButton: 'Más tarde', huaweiStore: 'Huawei AppGallery', + appStore: 'Tienda de aplicaciones', goRate: 'Valorar', emailHint1: 'Sin respuesta en 24h, prueba otro correo', emailHint2: 'Cualquier correo es válido para contactar', diff --git a/lib/l10n/languages/fr.dart b/lib/l10n/languages/fr.dart index aed6148e..8ac0ca3b 100644 --- a/lib/l10n/languages/fr.dart +++ b/lib/l10n/languages/fr.dart @@ -1391,6 +1391,7 @@ const fr = T( rateDialogContent2: 'Votre soutien est notre motivation', laterButton: 'Plus tard', huaweiStore: 'Huawei AppGallery', + appStore: 'App Store', goRate: 'Évaluer', emailHint1: 'Sans réponse sous 24h, essayez un autre e-mail', emailHint2: 'Tout e-mail est valable pour nous contacter', diff --git a/lib/l10n/languages/hi.dart b/lib/l10n/languages/hi.dart index 371477cb..46e1db2a 100644 --- a/lib/l10n/languages/hi.dart +++ b/lib/l10n/languages/hi.dart @@ -1359,6 +1359,7 @@ const hi = T( rateDialogContent2: 'आपका समर्थन हमारी प्रेरणा है', laterButton: 'बाद में', huaweiStore: 'Huawei AppGallery', + appStore: 'ऐप स्टोर', goRate: 'रेट करें', emailHint1: '24 घंटे में कोई जवाब नहीं, दूसरा ईमेल आज़माएं', emailHint2: 'कोई भी ईमेल संपर्क के लिए ठीक है', diff --git a/lib/l10n/languages/it.dart b/lib/l10n/languages/it.dart index db374c4c..3c9bc1da 100644 --- a/lib/l10n/languages/it.dart +++ b/lib/l10n/languages/it.dart @@ -1384,6 +1384,7 @@ const it = T( rateDialogContent2: 'Il tuo supporto è la nostra motivazione', laterButton: 'Più tardi', huaweiStore: 'Huawei AppGallery', + appStore: 'App Store', goRate: 'Valuta', emailHint1: 'Se nessuna risposta entro 24h, prova un\'altra email', emailHint2: 'Qualsiasi email va bene per contattarci', diff --git a/lib/l10n/languages/ja.dart b/lib/l10n/languages/ja.dart index f498762a..f90943f5 100644 --- a/lib/l10n/languages/ja.dart +++ b/lib/l10n/languages/ja.dart @@ -1337,6 +1337,7 @@ const ja = T( rateDialogContent2: 'あなたのサポートが私たちの原動力です', laterButton: '後で', huaweiStore: 'Huawei AppGallery', + appStore: 'アプリストア', goRate: '評価する', emailHint1: '24時間以内に返信がない場合は別のメールをお試しください', emailHint2: 'どのメールでもご連絡いただけます', diff --git a/lib/l10n/languages/ko.dart b/lib/l10n/languages/ko.dart index dcc9fcd9..1c562fca 100644 --- a/lib/l10n/languages/ko.dart +++ b/lib/l10n/languages/ko.dart @@ -1339,6 +1339,7 @@ const ko = T( rateDialogContent2: '여러분의 지원이 우리의 원동력입니다', laterButton: '나중에', huaweiStore: 'Huawei AppGallery', + appStore: '앱 스토어', goRate: '평가하기', emailHint1: '24시간 내 답장이 없으면 다른 이메일을 시도하세요', emailHint2: '어떤 이메일로든 연락 가능합니다', diff --git a/lib/l10n/languages/pt.dart b/lib/l10n/languages/pt.dart index f6f342ba..ce4c187d 100644 --- a/lib/l10n/languages/pt.dart +++ b/lib/l10n/languages/pt.dart @@ -1382,6 +1382,7 @@ const pt = T( rateDialogContent2: 'Seu apoio é nossa motivação', laterButton: 'Mais tarde', huaweiStore: 'Huawei AppGallery', + appStore: 'Loja de aplicativos', goRate: 'Avaliar', emailHint1: 'Sem resposta em 24h, tente outro e-mail', emailHint2: 'Qualquer e-mail serve para contato', diff --git a/lib/l10n/languages/ru.dart b/lib/l10n/languages/ru.dart index 43d8a0ef..7897207e 100644 --- a/lib/l10n/languages/ru.dart +++ b/lib/l10n/languages/ru.dart @@ -1378,6 +1378,7 @@ const ru = T( rateDialogContent2: 'Ваша поддержка — наша мотивация', laterButton: 'Позже', huaweiStore: 'Huawei AppGallery', + appStore: 'Магазин приложений', goRate: 'Оценить', emailHint1: 'Если нет ответа 24ч, попробуйте другой email', emailHint2: 'Любой email подходит для связи', diff --git a/lib/l10n/languages/zh_cn.dart b/lib/l10n/languages/zh_cn.dart index 3030e05b..84eb2a61 100644 --- a/lib/l10n/languages/zh_cn.dart +++ b/lib/l10n/languages/zh_cn.dart @@ -1318,6 +1318,7 @@ const zhCN = T( rateDialogContent2: '您的支持是我们前进的动力', laterButton: '下次再说', huaweiStore: '华为应用市场', + appStore: '应用商店', goRate: '去评价', emailHint1: '若超24小时无回复可更换其他邮箱', emailHint2: '任意邮箱均可联系', diff --git a/lib/l10n/languages/zh_tw.dart b/lib/l10n/languages/zh_tw.dart index a9585f79..c0aa083c 100644 --- a/lib/l10n/languages/zh_tw.dart +++ b/lib/l10n/languages/zh_tw.dart @@ -1317,6 +1317,7 @@ const zhTW = T( rateDialogContent2: '您的支持是我們前進的動力', laterButton: '下次再說', huaweiStore: '華為應用市場', + appStore: '應用商店', goRate: '去評價', emailHint1: '若超24小時無回覆可更換其他信箱', emailHint2: '任意信箱均可聯繫', diff --git a/lib/l10n/types/t_about.dart b/lib/l10n/types/t_about.dart index 5be1fb92..c2674c62 100644 --- a/lib/l10n/types/t_about.dart +++ b/lib/l10n/types/t_about.dart @@ -124,6 +124,7 @@ class TAbout { required this.rateDialogContent2, required this.laterButton, required this.huaweiStore, + required this.appStore, required this.goRate, required this.emailHint1, required this.emailHint2, @@ -526,6 +527,9 @@ class TAbout { /// 华为应用市场 final String huaweiStore; + /// 应用商店(通用名称,用于Android端评分跳转弹窗) + final String appStore; + /// 去评价 final String goRate; @@ -717,6 +721,7 @@ class TAbout { 'rateDialogContent2': rateDialogContent2, 'laterButton': laterButton, 'huaweiStore': huaweiStore, + 'appStore': appStore, 'goRate': goRate, 'emailHint1': emailHint1, 'emailHint2': emailHint2, @@ -1090,6 +1095,9 @@ class TAbout { huaweiStore: map['huaweiStore']?.isNotEmpty == true ? map['huaweiStore']! : (fallback?.huaweiStore ?? ''), + appStore: map['appStore']?.isNotEmpty == true + ? map['appStore']! + : (fallback?.appStore ?? ''), goRate: map['goRate']?.isNotEmpty == true ? map['goRate']! : (fallback?.goRate ?? ''), diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index a73737b9..157145dd 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -17,7 +17,7 @@ import flutter_app_group_directory import flutter_image_compress_macos import flutter_inappwebview_macos import flutter_local_notifications -import flutter_secure_storage_darwin +import flutter_secure_storage_macos import flutter_tts import flutter_webrtc import gal @@ -54,7 +54,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterImageCompressMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterImageCompressMacosPlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) - FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin")) + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin")) FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin")) GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin"))