This commit is contained in:
Developer
2026-05-20 01:40:09 +08:00
parent 6f5400ec4b
commit 27672343b8
78 changed files with 7109 additions and 9503 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -3,44 +3,90 @@
/// 创建时间: 2026-05-19
/// 更新时间: 2026-05-19
/// 作用: 定义所有协议/政策类型,供全局调用
/// 上次更新: 新增webUrl在线版地址
/// 上次更新: 新增多语言支持(titleEn/subtitleEn/titleFor/webUrlFor)
/// ============================================================
import 'package:flutter/cupertino.dart';
enum AgreementType {
privacyPolicy('privacy-policy', '隐私政策', CupertinoIcons.shield_lefthalf_fill),
privacyPolicy(
'privacy-policy',
'隐私政策',
'Privacy Policy',
'How we collect, use, store and protect your personal information',
CupertinoIcons.shield_lefthalf_fill,
),
userServiceAgreement(
'user-service-agreement',
'用户服务协议',
'User Service Agreement',
'Terms and rules for using Xianyan APP',
CupertinoIcons.doc_text_fill,
),
accountAgreement(
'account-agreement',
'账号使用协议',
'Account Agreement',
'Rules for account registration, security, and deletion',
CupertinoIcons.person_crop_circle_badge_checkmark,
),
memberBenefits('member-benefits', '会员权益说明', CupertinoIcons.star_circle_fill),
memberBenefits(
'member-benefits',
'会员权益说明',
'Member Benefits',
'Membership levels, benefits and usage instructions',
CupertinoIcons.star_circle_fill,
),
disclaimer(
'disclaimer',
'免责声明及内容版权归属',
'Disclaimer & Copyright',
'Disclaimers, content copyright and intellectual property notices',
CupertinoIcons.exclamationmark_shield_fill,
),
childrenPrivacy(
'children-privacy',
'儿童隐私政策',
'Children\'s Privacy Policy',
'Rules for protecting children\'s personal information',
CupertinoIcons.person_crop_circle_fill,
),
permissionUsage(
'permission-usage',
'软件权限使用说明',
'Permission Usage',
'App permissions and their purposes',
CupertinoIcons.lock_shield_fill,
),
appIntroduction('app-introduction', '软件介绍', CupertinoIcons.info_circle_fill),
beginnerGuide('beginner-guide', '新手指引', CupertinoIcons.lightbulb_fill),
devTeam('dev-team', '开发团队', CupertinoIcons.group_solid);
appIntroduction(
'app-introduction',
'软件介绍',
'About Xianyan',
'Xianyan APP features and platform support',
CupertinoIcons.info_circle_fill,
),
beginnerGuide(
'beginner-guide',
'新手指引',
'Beginner\'s Guide',
'Feature tour and operation guide',
CupertinoIcons.lightbulb_fill,
),
devTeam(
'dev-team',
'开发团队',
'Development Team',
'Team information and contact details',
CupertinoIcons.group_solid,
);
const AgreementType(this.route, this.title, this.icon);
const AgreementType(
this.route,
this.title,
this.titleEn,
this.subtitleEn,
this.icon,
);
static const String _webBase = 'https://tools.wktyl.com/agreements';
@@ -48,8 +94,43 @@ enum AgreementType {
final String title;
final String titleEn;
final String subtitleEn;
final IconData icon;
/// 根据语言ID获取标题
String titleFor(String? languageId) {
final isEn = languageId == 'en';
return isEn ? titleEn : title;
}
/// 根据语言ID获取副标题
String subtitleFor(String? languageId) {
final isEn = languageId == 'en';
return isEn ? subtitleEn : _subtitleZh;
}
String get _subtitleZh => switch (this) {
privacyPolicy => '我们如何收集、使用、存储和保护您的个人信息',
userServiceAgreement => '使用闲言APP的服务条款与规则',
accountAgreement => '账号注册、安全、注销等相关规定',
memberBenefits => '会员等级、权益与使用说明',
disclaimer => '免责条款、内容版权与知识产权声明',
childrenPrivacy => '儿童及未成年人个人信息保护规则',
permissionUsage => '软件所需权限及使用目的说明',
appIntroduction => '闲言APP功能介绍与平台支持',
beginnerGuide => '功能导览与操作指引',
devTeam => '开发团队信息与联系方式',
};
/// 根据语言ID获取在线URL
String webUrlFor(String? languageId) {
final base = '$_webBase/$route.html';
return languageId == 'en' ? '$base?lang=en' : base;
}
String get webUrl => '$_webBase/$route.html';
static const String webIndexUrl = '$_webBase/';

View File

@@ -3,34 +3,39 @@
/// 创建时间: 2026-05-19
/// 更新时间: 2026-05-19
/// 作用: 展示所有协议/政策入口列表,点击跳转对应协议详情
/// 上次更新: 初始创建,支持动态主
/// 上次更新: 支持多语言(中文+英文),根据当前语言显示对应标题和副标
/// ============================================================
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart' show Divider;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_typography.dart';
import '../../../core/theme/app_radius.dart';
import '../../../l10n/app_locale.dart';
import '../../../core/router/app_nav_extension.dart';
import '../../../shared/widgets/glass_container.dart';
import '../data/agreement_types.dart';
import '../data/agreement_data.dart';
class AgreementListPage extends StatelessWidget {
class AgreementListPage extends ConsumerWidget {
const AgreementListPage({super.key});
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
final ext = AppTheme.ext(context);
final languageId = ref.watch(appLocaleProvider).toLanguageTag().startsWith('en')
? 'en'
: null;
return CupertinoPageScaffold(
backgroundColor: ext.bgPrimary,
navigationBar: CupertinoNavigationBar(
middle: Text(
'软件协议',
languageId == 'en' ? 'Agreements' : '软件协议',
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
@@ -48,17 +53,17 @@ class AgreementListPage extends StatelessWidget {
),
child: Column(
children: [
_HeaderCard(ext: ext),
_HeaderCard(ext: ext, languageId: languageId),
const SizedBox(height: AppSpacing.md),
_PrivacySection(ext: ext),
_PrivacySection(ext: ext, languageId: languageId),
const SizedBox(height: AppSpacing.md),
_ServiceSection(ext: ext),
_ServiceSection(ext: ext, languageId: languageId),
const SizedBox(height: AppSpacing.md),
_ContentSection(ext: ext),
_ContentSection(ext: ext, languageId: languageId),
const SizedBox(height: AppSpacing.md),
_GuideSection(ext: ext),
_GuideSection(ext: ext, languageId: languageId),
const SizedBox(height: AppSpacing.xl),
_Footer(ext: ext),
_Footer(ext: ext, languageId: languageId),
const SizedBox(height: AppSpacing.xxl),
],
),
@@ -69,12 +74,14 @@ class AgreementListPage extends StatelessWidget {
}
class _HeaderCard extends StatelessWidget {
const _HeaderCard({required this.ext});
const _HeaderCard({required this.ext, required this.languageId});
final AppThemeExtension ext;
final String? languageId;
@override
Widget build(BuildContext context) {
final isEn = languageId == 'en';
return GlassContainer(
depth: GlassDepth.elevated,
padding: const EdgeInsets.all(AppSpacing.lg),
@@ -106,7 +113,7 @@ class _HeaderCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'软件协议与政策',
isEn ? 'Agreements & Policies' : '软件协议与政策',
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w700,
@@ -114,7 +121,9 @@ class _HeaderCard extends StatelessWidget {
),
const SizedBox(height: AppSpacing.xs),
Text(
'请仔细阅读以下协议与政策,了解您的权利与义务',
isEn
? 'Please read the following agreements and policies carefully'
: '请仔细阅读以下协议与政策,了解您的权利与义务',
style: AppTypography.caption1.copyWith(
color: ext.textSecondary,
),
@@ -129,16 +138,19 @@ class _HeaderCard extends StatelessWidget {
}
class _PrivacySection extends StatelessWidget {
const _PrivacySection({required this.ext});
const _PrivacySection({required this.ext, required this.languageId});
final AppThemeExtension ext;
final String? languageId;
@override
Widget build(BuildContext context) {
final isEn = languageId == 'en';
return _SectionGroup(
ext: ext,
title: '隐私与安全',
title: isEn ? 'Privacy & Security' : '隐私与安全',
icon: CupertinoIcons.shield_lefthalf_fill,
languageId: languageId,
items: const [
AgreementType.privacyPolicy,
AgreementType.childrenPrivacy,
@@ -149,16 +161,19 @@ class _PrivacySection extends StatelessWidget {
}
class _ServiceSection extends StatelessWidget {
const _ServiceSection({required this.ext});
const _ServiceSection({required this.ext, required this.languageId});
final AppThemeExtension ext;
final String? languageId;
@override
Widget build(BuildContext context) {
final isEn = languageId == 'en';
return _SectionGroup(
ext: ext,
title: '服务条款',
title: isEn ? 'Service Terms' : '服务条款',
icon: CupertinoIcons.doc_text_fill,
languageId: languageId,
items: const [
AgreementType.userServiceAgreement,
AgreementType.accountAgreement,
@@ -169,32 +184,38 @@ class _ServiceSection extends StatelessWidget {
}
class _ContentSection extends StatelessWidget {
const _ContentSection({required this.ext});
const _ContentSection({required this.ext, required this.languageId});
final AppThemeExtension ext;
final String? languageId;
@override
Widget build(BuildContext context) {
final isEn = languageId == 'en';
return _SectionGroup(
ext: ext,
title: '内容与版权',
title: isEn ? 'Content & Copyright' : '内容与版权',
icon: CupertinoIcons.doc_on_doc_fill,
languageId: languageId,
items: const [AgreementType.disclaimer],
);
}
}
class _GuideSection extends StatelessWidget {
const _GuideSection({required this.ext});
const _GuideSection({required this.ext, required this.languageId});
final AppThemeExtension ext;
final String? languageId;
@override
Widget build(BuildContext context) {
final isEn = languageId == 'en';
return _SectionGroup(
ext: ext,
title: '了解闲言',
title: isEn ? 'About Xianyan' : '了解闲言',
icon: CupertinoIcons.info_circle_fill,
languageId: languageId,
items: const [
AgreementType.appIntroduction,
AgreementType.beginnerGuide,
@@ -209,12 +230,14 @@ class _SectionGroup extends StatelessWidget {
required this.ext,
required this.title,
required this.icon,
required this.languageId,
required this.items,
});
final AppThemeExtension ext;
final String title;
final IconData icon;
final String? languageId;
final List<AgreementType> items;
@override
@@ -258,17 +281,22 @@ class _SectionGroup extends StatelessWidget {
if (i > 0) {
widgets.add(_SectionDivider(ext: ext));
}
widgets.add(_AgreementTile(ext: ext, type: items[i]));
widgets.add(_AgreementTile(ext: ext, type: items[i], languageId: languageId));
}
return widgets;
}
}
class _AgreementTile extends StatelessWidget {
const _AgreementTile({required this.ext, required this.type});
const _AgreementTile({
required this.ext,
required this.type,
required this.languageId,
});
final AppThemeExtension ext;
final AgreementType type;
final String? languageId;
@override
Widget build(BuildContext context) {
@@ -297,7 +325,7 @@ class _AgreementTile extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
type.title,
type.titleFor(languageId),
style: AppTypography.body.copyWith(
fontWeight: FontWeight.w500,
color: ext.textPrimary,
@@ -305,7 +333,7 @@ class _AgreementTile extends StatelessWidget {
),
const SizedBox(height: 2),
Text(
AgreementData.getSubtitle(type),
AgreementData.getSubtitle(type, languageId: languageId),
style: AppTypography.caption1.copyWith(
color: ext.textSecondary,
),
@@ -342,9 +370,12 @@ class _SectionDivider extends StatelessWidget {
}
class _Footer extends StatelessWidget {
const _Footer({required this.ext});
const _Footer({required this.ext, required this.languageId});
final AppThemeExtension ext;
final String? languageId;
bool get _isEn => languageId == 'en';
@override
Widget build(BuildContext context) {
@@ -374,7 +405,7 @@ class _Footer extends StatelessWidget {
Icon(CupertinoIcons.globe, size: 14, color: ext.accent),
const SizedBox(width: AppSpacing.xs),
Text(
'在线版协议',
_isEn ? 'Online Version' : '在线版协议',
style: AppTypography.caption1.copyWith(
color: ext.accent,
fontWeight: FontWeight.w500,
@@ -393,13 +424,17 @@ class _Footer extends StatelessWidget {
),
const SizedBox(height: AppSpacing.md),
Text(
'使用闲言APP即表示您同意上述协议与政策',
_isEn
? 'By using Xianyan APP, you agree to the above agreements and policies'
: '使用闲言APP即表示您同意上述协议与政策',
style: AppTypography.caption1.copyWith(color: ext.textHint),
textAlign: TextAlign.center,
),
const SizedBox(height: AppSpacing.xs),
Text(
'如有疑问请联系 21981550@qq.com',
_isEn
? 'If you have questions, please contact 21981550@qq.com'
: '如有疑问请联系 21981550@qq.com',
style: AppTypography.caption1.copyWith(color: ext.textHint),
textAlign: TextAlign.center,
),

View File

@@ -3,38 +3,47 @@
/// 创建时间: 2026-05-19
/// 更新时间: 2026-05-19
/// 作用: 通用协议/政策内容展示页面接收AgreementType参数
/// 上次更新: 支持重要字段高亮、动态主题与多语言预留
/// 上次更新: 支持多语言(中文+英文),根据当前语言显示对应协议内容
/// ============================================================
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart' show Divider;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_typography.dart';
import '../../../core/theme/app_radius.dart';
import '../../../l10n/app_locale.dart';
import '../../../shared/widgets/glass_container.dart';
import '../data/agreement_types.dart';
import '../data/agreement_data.dart';
class AgreementPage extends StatelessWidget {
class AgreementPage extends ConsumerWidget {
const AgreementPage({super.key, required this.type});
final AgreementType type;
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
final ext = AppTheme.ext(context);
final content = AgreementData.getContent(type);
final updateDate = AgreementData.getUpdateDate(type);
final languageId =
ref.watch(appLocaleProvider).toLanguageTag().startsWith('en')
? 'en'
: null;
final content = AgreementData.getContent(type, languageId: languageId);
final updateDate = AgreementData.getUpdateDate(
type,
languageId: languageId,
);
final sections = _parseSections(content);
return CupertinoPageScaffold(
backgroundColor: ext.bgPrimary,
navigationBar: CupertinoNavigationBar(
middle: Text(
type.title,
type.titleFor(languageId),
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
@@ -48,11 +57,16 @@ class AgreementPage extends StatelessWidget {
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(AppSpacing.md),
children: [
_AgreementHeader(ext: ext, type: type),
_AgreementHeader(ext: ext, type: type, languageId: languageId),
const SizedBox(height: AppSpacing.lg),
...sections.map((s) => _AgreementSection(ext: ext, section: s)),
const SizedBox(height: AppSpacing.xl),
_AgreementFooter(ext: ext, updateDate: updateDate, type: type),
_AgreementFooter(
ext: ext,
updateDate: updateDate,
type: type,
languageId: languageId,
),
const SizedBox(height: AppSpacing.xxl),
],
),
@@ -98,11 +112,16 @@ class AgreementPage extends StatelessWidget {
bool _isHeading(String line) {
final headingPatterns = [
RegExp(r'^[一二三四五六七八九十]+、'),
RegExp(r'^[一二三四五六七八九十]+、'),
RegExp(r'^\d+\.\d+'),
RegExp(r'^闲言APP'),
RegExp(r'^Xianyan APP'),
RegExp(r'^更新日期'),
RegExp(r'^Updated'),
RegExp(r'^生效日期'),
RegExp(r'^Effective'),
RegExp(r'^Zero\.'),
RegExp(r'^[IVX]+\.\s'),
];
for (final pattern in headingPatterns) {
if (pattern.hasMatch(line)) return true;
@@ -118,10 +137,15 @@ class _Section {
}
class _AgreementHeader extends StatelessWidget {
const _AgreementHeader({required this.ext, required this.type});
const _AgreementHeader({
required this.ext,
required this.type,
required this.languageId,
});
final AppThemeExtension ext;
final AgreementType type;
final String? languageId;
@override
Widget build(BuildContext context) {
@@ -145,7 +169,7 @@ class _AgreementHeader extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
type.title,
type.titleFor(languageId),
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w700,
@@ -153,7 +177,7 @@ class _AgreementHeader extends StatelessWidget {
),
const SizedBox(height: AppSpacing.xs),
Text(
AgreementData.getSubtitle(type),
AgreementData.getSubtitle(type, languageId: languageId),
style: AppTypography.caption1.copyWith(
color: ext.textSecondary,
),
@@ -213,7 +237,7 @@ class _RichBody extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: lines.where((l) => l.trim().isNotEmpty).map((line) {
final trimmed = line.trim();
final isBullet = trimmed.startsWith('');
final isBullet = trimmed.startsWith('') || trimmed.startsWith('-');
return Padding(
padding: EdgeInsets.only(
left: isBullet ? AppSpacing.sm : 0,
@@ -309,11 +333,15 @@ class _AgreementFooter extends StatelessWidget {
required this.ext,
required this.updateDate,
required this.type,
required this.languageId,
});
final AppThemeExtension ext;
final String updateDate;
final AgreementType type;
final String? languageId;
bool get _isEn => languageId == 'en';
@override
Widget build(BuildContext context) {
@@ -327,7 +355,7 @@ class _AgreementFooter extends StatelessWidget {
const SizedBox(height: AppSpacing.md),
GestureDetector(
onTap: () => launchUrl(
Uri.parse(type.webUrl),
Uri.parse(type.webUrlFor(languageId)),
mode: LaunchMode.externalApplication,
),
child: Container(
@@ -349,7 +377,7 @@ class _AgreementFooter extends StatelessWidget {
Icon(CupertinoIcons.globe, size: 14, color: ext.accent),
const SizedBox(width: AppSpacing.xs),
Text(
'在线版',
_isEn ? 'Online Version' : '在线版',
style: AppTypography.caption1.copyWith(
color: ext.accent,
fontWeight: FontWeight.w500,
@@ -358,7 +386,7 @@ class _AgreementFooter extends StatelessWidget {
const SizedBox(width: AppSpacing.xs),
Flexible(
child: Text(
type.webUrl,
type.webUrlFor(languageId),
style: AppTypography.caption2.copyWith(
color: ext.accent.withValues(alpha: 0.7),
),
@@ -371,13 +399,15 @@ class _AgreementFooter extends StatelessWidget {
),
const SizedBox(height: AppSpacing.md),
Text(
'最后更新日期:$updateDate',
_isEn ? 'Last updated: $updateDate' : '最后更新日期:$updateDate',
style: AppTypography.caption1.copyWith(color: ext.textHint),
textAlign: TextAlign.center,
),
const SizedBox(height: AppSpacing.xs),
Text(
'弥勒市朋普镇微风暴网络科技工作室',
_isEn
? 'Mile City Pengpu Town Weifengbao Network Technology Studio'
: '弥勒市朋普镇微风暴网络科技工作室',
style: AppTypography.caption1.copyWith(color: ext.textHint),
textAlign: TextAlign.center,
),

View File

@@ -21,7 +21,7 @@ import '../../models/transfer_device.dart';
class BluetoothPairingService {
BluetoothPairingService();
static const _bleChannel = MethodChannel('com.xianyan/ble');
static const _bleChannel = MethodChannel('apps.xy.xianyan/ble');
bool _isScanning = false;
bool get isScanning => _isScanning;

View File

@@ -46,7 +46,7 @@ class HotspotConfig {
class HotspotService {
HotspotService();
static const _hotspotChannel = MethodChannel('com.xianyan/hotspot');
static const _hotspotChannel = MethodChannel('apps.xy.xianyan/hotspot');
bool _isHotspotActive = false;
bool get isHotspotActive => _isHotspotActive;

View File

@@ -207,14 +207,6 @@ mixin HomeInteractionMixin on Notifier<HomeState> {
final feedId = extractFeedId(id);
if (feedId > 0) {
try {
await FeedService.action(
action: 'view',
feedType: feedType,
feedId: feedId,
);
} catch (_) {}
try {
await FeedService.fetchDetail(type: feedType, id: feedId);
} catch (_) {}

View File

@@ -109,20 +109,19 @@ class FeedService {
/// 互动操作
///
/// 支持: like/unlike/favorite/unfavorite/share/dislike/
/// readlater/unreadlater/rating/view
/// 需要登录view操作不强制登录
/// comment/readlater/unreadlater/rating/block/unblock/
/// report/comment_like/comment_unlike/readtime
/// 需要登录view操作由fetchDetail自动处理
static Future<bool> action({
required String action,
required String feedType,
required int feedId,
String? extra,
}) async {
if (action != 'view') {
final loggedIn = await SecureStorage.isLoggedIn;
if (!loggedIn) {
Log.i('Feed互动本地记录: 未登录, action=$action, 仅本地生效');
return true;
}
final loggedIn = await SecureStorage.isLoggedIn;
if (!loggedIn) {
Log.i('Feed互动本地记录: 未登录, action=$action, 仅本地生效');
return true;
}
try {
@@ -435,11 +434,15 @@ class FeedService {
'limit': limit,
};
if (seenIds != null && seenIds.isNotEmpty) {
final trimmedIds = seenIds.length > 30 ? seenIds.sublist(0, 30) : seenIds;
final trimmedIds = seenIds.length > 30
? seenIds.sublist(0, 30)
: seenIds;
params['seen_ids'] = trimmedIds.join(',');
}
if (seenHashes != null && seenHashes.isNotEmpty) {
final trimmedHashes = seenHashes.length > 30 ? seenHashes.sublist(0, 30) : seenHashes;
final trimmedHashes = seenHashes.length > 30
? seenHashes.sublist(0, 30)
: seenHashes;
params['seen_hashes'] = trimmedHashes.join(',');
}
@@ -488,10 +491,7 @@ class FeedService {
try {
final response = await _api.post<Map<String, dynamic>>(
'/api/feed/preferences',
data: {
'action': 'save',
'data': jsonEncode(preferences.toJson()),
},
data: {'action': 'save', 'data': jsonEncode(preferences.toJson())},
);
final data = response.data as Map<String, dynamic>;
return data['code'] == 1;

View File

@@ -373,7 +373,7 @@ class _FeedbackSection extends StatelessWidget {
Navigator.pop(ctx);
launchUrl(
Uri.parse(
'https://appgallery.huawei.com/app/detail?id=com.xianyan.app',
'https://appgallery.huawei.com/app/detail?id=apps.xy.xianyan',
),
mode: LaunchMode.externalApplication,
);

View File

@@ -3,7 +3,7 @@
/// 创建时间: 2026-05-19
/// 更新时间: 2026-05-19
/// 作用: 定义所有桌面小部件的类型、元数据和平台标识
/// 上次更新: 增加深度链接路由、数据键前缀、主题键
/// 上次更新: 新增qualifiedAndroidName属性修复Android端ClassNotFoundException
/// ============================================================
import 'package:flutter/cupertino.dart';
@@ -66,6 +66,9 @@ extension WidgetTypeX on WidgetType {
WidgetType.checkin => 'CheckinProvider',
};
String get qualifiedAndroidName =>
'apps.xy.xianyan.widget.$androidProviderName';
String get iosWidgetKind => switch (this) {
WidgetType.dailySentence => 'DailySentenceWidget',
WidgetType.readlater => 'ReadlaterWidget',
@@ -141,5 +144,6 @@ extension WidgetTypeX on WidgetType {
String get themeKey => '${dataKeyPrefix}_theme';
static List<WidgetType> get all =>
WidgetType.values..sort((a, b) => a.priority.compareTo(b.priority));
List<WidgetType>.from(WidgetType.values)
..sort((a, b) => a.priority.compareTo(b.priority));
}

View File

@@ -3,7 +3,7 @@
/// 创建时间: 2026-05-19
/// 更新时间: 2026-05-19
/// 作用: 管理小部件安装状态、数据推送和交互
/// 上次更新: 增加pushThemeToAllWidgets、addWidget支持全类型
/// 上次更新: requestPinWidget增加qualifiedAndroidName参数修复Android类名拼接错误
/// ============================================================
import 'dart:ui';
@@ -92,6 +92,7 @@ class WidgetNotifier extends Notifier<WidgetState> {
Future<void> requestPinWidget(WidgetType type) async {
try {
await HomeWidget.requestPinWidget(
qualifiedAndroidName: type.qualifiedAndroidName,
androidName: type.androidProviderName,
ohosName: type.ohosFormName,
);