1. 新增工作台三栏布局模式,适配宽屏设备 2. 添加跨平台系统托盘支持,新增托盘图标资源 3. 修复工作台模式下导航返回异常问题 4. 统一JSON类型安全解析,替换硬类型转换 5. 增加macOS深度链接支持,统一渠道分发信息 6. 优化部分页面生命周期和状态加载逻辑 7. 移除废弃的nearby_connections依赖
162 lines
5.5 KiB
Dart
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,
|
|
);
|