Files
xianyan/lib/features/widget/widget_provider.dart
Developer 83720002e6 feat: 新增工作台模式、系统托盘,修复多平台兼容性问题
1. 新增工作台三栏布局模式,适配宽屏设备
2. 添加跨平台系统托盘支持,新增托盘图标资源
3. 修复工作台模式下导航返回异常问题
4. 统一JSON类型安全解析,替换硬类型转换
5. 增加macOS深度链接支持,统一渠道分发信息
6. 优化部分页面生命周期和状态加载逻辑
7. 移除废弃的nearby_connections依赖
2026-06-19 06:43:55 +08:00

162 lines
5.5 KiB
Dart

/// ============================================================
/// 闲言APP — 桌面小部件状态管理
/// 创建时间: 2026-05-19
/// 更新时间: 2026-06-12
/// 作用: 管理小部件安装状态、数据推送和交互
/// 上次更新: 从providers/子目录提升至widget根目录
/// ============================================================
import 'dart:ui';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:home_widget/home_widget.dart';
import 'package:xianyan/core/utils/platform/platform_utils.dart' as pu;
import 'package:xianyan/core/utils/platform/platform_capability.dart';
import '../../../core/services/data/home_widget_service.dart';
import '../../../core/utils/logger.dart';
import 'widget_type.dart';
enum PinWidgetResult { success, unsupported, failed }
class WidgetState {
final Set<WidgetType> installedWidgets;
final bool isLoading;
final String? error;
const WidgetState({
this.installedWidgets = const {},
this.isLoading = false,
this.error,
});
WidgetState copyWith({
Set<WidgetType>? installedWidgets,
bool? isLoading,
String? error,
}) => WidgetState(
installedWidgets: installedWidgets ?? this.installedWidgets,
isLoading: isLoading ?? this.isLoading,
error: error,
);
}
class WidgetNotifier extends Notifier<WidgetState> {
@override
WidgetState build() => const WidgetState();
Future<void> loadInstalledWidgets() async {
// [PlatformCapabilities] 统一能力查询: homeWidget
// macOS/Windows/Linux/Web 端 home_widget 插件无原生实现,调用会抛 MissingPluginException
if (pu.isOhos || !PlatformCapabilities.supports(CapabilityKey.homeWidget)) {
Log.w('WidgetNotifier: 当前平台不支持桌面小部件,跳过加载');
state = state.copyWith(isLoading: false);
return;
}
state = state.copyWith(isLoading: true);
try {
final widgets = await HomeWidget.getInstalledWidgets();
final installed = <WidgetType>{};
for (final w in widgets) {
final kind = w.iOSKind ?? w.androidClassName ?? '';
for (final type in WidgetType.values) {
if (kind.contains(type.androidProviderName) ||
kind.contains(type.iosWidgetKind) ||
kind.contains(type.ohosFormName)) {
installed.add(type);
}
}
}
state = state.copyWith(installedWidgets: installed, isLoading: false);
Log.i('WidgetNotifier: 已安装 ${installed.length} 个小部件');
} catch (e) {
Log.e('WidgetNotifier: 加载小部件失败', e);
state = state.copyWith(isLoading: false, error: e.toString());
}
}
Future<void> addWidget(WidgetType type) async {
try {
final service = ref.read(homeWidgetServiceProvider);
await service.init();
await service.updateWidget(type);
final isDark =
PlatformDispatcher.instance.platformBrightness == Brightness.dark;
await service.pushThemeMode(isDark);
final newInstalled = {...state.installedWidgets, type};
state = state.copyWith(installedWidgets: newInstalled);
Log.i('WidgetNotifier: 添加小部件 ${type.title}');
} catch (e) {
Log.e('WidgetNotifier: 添加小部件失败', e);
state = state.copyWith(error: e.toString());
}
}
Future<void> removeWidget(WidgetType type) async {
final newInstalled = {...state.installedWidgets}..remove(type);
state = state.copyWith(installedWidgets: newInstalled);
Log.i('WidgetNotifier: 移除小部件 ${type.title}');
}
Future<PinWidgetResult> requestPinWidget(WidgetType type) async {
// [PlatformCapabilities] 统一能力查询: homeWidget
if (pu.isOhos || !PlatformCapabilities.supports(CapabilityKey.homeWidget)) {
Log.w('WidgetNotifier: 鸿蒙端不支持快捷添加');
return PinWidgetResult.unsupported;
}
try {
await HomeWidget.requestPinWidget(
qualifiedAndroidName: type.qualifiedAndroidName,
androidName: type.androidProviderName,
);
Log.i('WidgetNotifier: 请求固定小部件 ${type.title}');
return PinWidgetResult.success;
} on PlatformException catch (e) {
Log.e('WidgetNotifier: 请求固定小部件 PlatformException', e);
if (e.code == 'not_supported' || e.code == 'ACTION_APPWIDGET_BIND') {
return PinWidgetResult.unsupported;
}
return PinWidgetResult.failed;
} catch (e) {
Log.e('WidgetNotifier: 请求固定小部件失败', e);
return PinWidgetResult.failed;
}
}
Future<void> pushDataToWidget(WidgetType type) async {
try {
final service = ref.read(homeWidgetServiceProvider);
await service.init();
await service.updateWidget(type);
Log.i('WidgetNotifier: 推送数据到小部件 ${type.title}');
} catch (e) {
Log.e('WidgetNotifier: 推送数据失败', e);
}
}
Future<void> pushThemeToAllWidgets() async {
try {
final service = ref.read(homeWidgetServiceProvider);
await service.init();
final isDark =
PlatformDispatcher.instance.platformBrightness == Brightness.dark;
await service.pushThemeMode(isDark);
for (final type in WidgetType.values) {
await service.updateWidget(type);
}
Log.i('WidgetNotifier: 已推送主题到所有小部件');
} catch (e) {
Log.e('WidgetNotifier: 推送主题失败', e);
}
}
}
final widgetProvider = NotifierProvider<WidgetNotifier, WidgetState>(
WidgetNotifier.new,
);