fix: 隔离鸿蒙SDK特有类型,解决官方SDK编译冲突

- 新增 notification_init_stub.dart 桥接文件,隔离 OhosInitializationSettings
- 通知服务使用 buildNotificationInitSettings() 和 requestOhosNotificationPermission()
- HomeWidget 的 ohosName 参数通过 dynamic 调用隔离
- file_picker 升级到 ^11.0.0,API 从 FilePicker.platform.pickFiles 改为 FilePicker.pickFiles
- flutter_secure_storage 升级到 ^10.2.0
- macos/Podfile 部署目标从 10.15 升级到 13.0
- 更新 iOS_macOS_Developer_Guide.md v3
This commit is contained in:
Developer
2026-05-22 02:40:04 +08:00
parent e1d8c4521d
commit b9aa871678
17 changed files with 614 additions and 66 deletions

View File

@@ -111,7 +111,7 @@ Error: The getter 'ohos' isn't defined for the class 'TargetPlatform'
| 包名 | 远程版本号 | 说明 |
|---|---|---|
| shared_preferences | ^2.5.5 | 轻量KV持久化 |
| flutter_secure_storage | ^9.2.4 | 加密安全存储 |
| flutter_secure_storage | ^10.2.0 | 加密安全存储 |
| hive_flutter | ^1.1.0 | Hive Flutter适配 |
| path_provider | ^2.1.5 | 系统目录路径获取 |
| package_info_plus | ^10.1.0 | 应用包信息读取 |
@@ -122,11 +122,11 @@ Error: The getter 'ohos' isn't defined for the class 'TargetPlatform'
| url_launcher | ^6.3.2 | 打开外部URL/应用 |
| app_links | ^7.0.0 | 深度链接处理 |
| home_widget | ^0.9.1 | iOS/Android桌面小组件 |
| file_picker | ^8.3.7 | 文件选择器 |
| file_picker | ^11.0.0 | 文件选择器(⚠️ API变更见§2.5 |
| image_picker | ^1.2.2 | 相机/相册选图 |
| share_plus | ^13.1.0 | 系统分享面板 |
| gal | ^2.3.0 | 保存图片/视频到相册 |
| pro_image_editor | ^12.4.4 | 图片编辑器核心 |
| pro_image_editor | 本地包(含魔改) | 图片编辑器核心(⚠️ 需本地包见§2.5 |
| flutter_quill | ^11.5.0 | Quill富文本编辑器 |
| flex_color_picker | ^3.8.0 | HSL颜色选择器 |
| flutter_image_compress | ^2.4.0 | 图片压缩 |
@@ -157,6 +157,7 @@ MacBook Pro 端不需要 `dependency_overrides` 中的本地包覆盖,改为
dependency_overrides:
meta: ^1.17.0
web: ^1.1.0
win32: ^6.0.1
# 删除所有 path: packages/xxx 条目
```
@@ -209,22 +210,64 @@ extended_image ^10.0.1 | photo_view ^0.15.0
git clone <仓库URL> xianyan
cd xianyan
# 2. 修改 pubspec.yaml替换本地包为远程版本
# 参见 §2.2 的替换清单
# 2. 解压 pro_image_editor 本地包到 packages/ 目录
# (从共享位置获取 pro_image_editor.zip
unzip pro_image_editor.zip -d packages/
# 确保 packages/pro_image_editor/ 目录存在且包含 pubspec.yaml
# 3. 获取依赖
# 3. 修改 pubspec.yaml替换本地包为远程版本
# 参见 §2.2 的替换清单
# 注意pro_image_editor 保持本地包引用path: packages/pro_image_editor
# 4. 获取依赖
flutter pub get
# 4. 编译验证
# 5. 编译验证
flutter build ios --no-codesign
flutter build macos
# 5. 防止误提交 pubspec.yaml
# 6. 防止误提交 pubspec.yaml
git stash push -m "macOS-local-pubspec" pubspec.yaml
# 或
echo "pubspec.yaml" >> .git/info/exclude
```
### 2.5 特殊包说明
#### 2.5.1 pro_image_editor含魔改需本地包
`pro_image_editor` 包含项目自定义的 `CanvasStyleModel` 类,远程版本不包含此类型。
MacBook Pro 端必须使用本地包版本:
```yaml
# pubspec.yaml 中保持本地包引用
pro_image_editor:
path: packages/pro_image_editor
```
需要将 `pro_image_editor.zip` 解压到 `packages/pro_image_editor/` 目录。
该本地包不包含 `TargetPlatform.ohos` 引用,官方 SDK 编译正常。
#### 2.5.2 file_pickerAPI 变更)
`file_picker ^11.0.0` 的 API 发生了变更:
```dart
// ❌ 旧版 APIfile_picker ^8.x
final result = await FilePicker.platform.pickFiles();
// ✅ 新版 APIfile_picker ^11.x
final result = await FilePicker.pickFiles();
```
项目代码已更新为新版 API。鸿蒙端如使用本地包版本`file_picker ^8.x`
需注意 API 差异,或升级本地包到 `^11.x`
#### 2.5.3 flutter_secure_storage版本升级
`flutter_secure_storage ^10.2.0` 的 Windows 平台实现兼容 `win32 ^6.0.1`
解决了之前版本与 `win32 6.x` 的编译冲突。
---
## 三、Git 提交与合并规范
@@ -449,6 +492,61 @@ if (pu.isDesktop) { /* 桌面端 */ }
> 以上文件均在 `packages/` 目录中MacBook Pro 端使用远程版本,不会编译这些文件。
### 4.5 lib/ 代码中的鸿蒙SDK类型桥接
鸿蒙端本地包中某些类有官方 SDK 不存在的额外参数或类型(如 `OhosInitializationSettings``ohosName`)。
项目通过桥接文件和 `dynamic` 调用隔离这些差异,确保两端编译正常。
#### 4.5.1 通知服务桥接
**桥接文件**`lib/core/services/notification/notification_init_stub.dart`
| 方法 | 官方SDK行为 | 鸿蒙端行为 |
|---|---|---|
| `buildNotificationInitSettings()` | 构建 `InitializationSettings`(无 ohos 参数) | 鸿蒙端本地包的 `InitializationSettings` 自带 ohos 参数,官方端不传即可 |
| `requestOhosNotificationPermission()` | 返回 `false`(不执行) | 动态调用 `OhosFlutterLocalNotificationsPlugin` |
**使用此桥接的文件**
- `lib/core/services/notification/notification_service.dart`
- `lib/core/services/notification/local_notification_service.dart`
- `lib/features/file_transfer/services/notification_service.dart`
#### 4.5.2 HomeWidget 桥接
鸿蒙端本地包的 `HomeWidget.updateWidget()``HomeWidget.requestPinWidget()``ohosName` 参数,
官方 SDK 不存在此参数。项目通过 `pu.isOhos` 条件 + `dynamic` 调用隔离:
```dart
// 官方SDK标准调用
await HomeWidget.updateWidget(
androidName: type.androidProviderName,
iOSName: type.iosWidgetKind,
);
// 鸿蒙端dynamic 调用,传入 ohosName
if (pu.isOhos) {
final dynamic updateWidget = HomeWidget.updateWidget;
await updateWidget(
androidName: type.androidProviderName,
iOSName: type.iosWidgetKind,
ohosName: type.ohosFormName,
);
}
```
**涉及文件**
- `lib/core/services/data/home_widget_service.dart`
- `lib/features/widget/providers/widget_provider.dart`
#### 4.5.3 新增鸿蒙SDK特有类型的规范
如果鸿蒙端本地包新增了官方 SDK 不存在的类型或参数,按以下规范处理:
1. **在 `lib/` 代码中不直接 import 鸿蒙专用类型**(如 `OhosInitializationSettings`
2. **使用 `pu.isOhos` 条件分支**:鸿蒙端逻辑仅在 `pu.isOhos` 为 true 时执行
3. **使用 `dynamic` 调用**:绕过官方 SDK 的静态类型检查
4. **优先创建桥接文件**:将鸿蒙特有逻辑封装在独立文件中(如 `notification_init_stub.dart`
---
## 五、其他注意事项
@@ -493,7 +591,8 @@ iOS/macOS 端这些检测不会执行(`isOhos` 为 false无需关心。
### 5.4 packages 目录说明
- `packages/` 目录存放鸿蒙适配的本地三方库,已在 `.gitignore` 中排除
- **MacBook Pro 端需要 `packages/` 目录**,直接使用远程版本即可
- MacBook Pro 端需要 `packages/pro_image_editor/`(含魔改的 `CanvasStyleModel`),从 zip 解压获取
- 其他本地包 MacBook Pro 端使用远程版本,无需放在 `packages/` 目录
- 鸿蒙开发者需手动维护本地 `packages/` 目录
### 5.5 MacBook Pro 修改 ios/macos 后,鸿蒙端是否需要同步?
@@ -517,6 +616,10 @@ iOS/macOS 端这些检测不会执行(`isOhos` 为 false无需关心。
| git pull 后 pubspec.yaml 被覆盖 | 仓库版本是鸿蒙端配置 | 重新替换为远程版本,参见 §3.3.4 |
| 误提交了 MacBook Pro 端的 pubspec.yaml | 删除了鸿蒙本地包引用 | 立即回退,恢复鸿蒙端配置 |
| 新增依赖后鸿蒙端报错 | 新增的三方库未适配鸿蒙 | 通知鸿蒙开发者评估,必要时本地化到 packages/ |
| 编译报 `OhosInitializationSettings` 不存在 | 官方SDK无此类型 | 使用 `notification_init_stub.dart` 桥接,参见 §4.5 |
| 编译报 `ohosName` 参数不存在 | 官方SDK的 HomeWidget 无此参数 | 使用 `dynamic` 调用,参见 §4.5.2 |
| `pro_image_editor``CanvasStyleModel` 不存在 | 远程版本不含魔改内容 | 使用本地包 `path: packages/pro_image_editor`,参见 §2.5.1 |
| `FilePicker.platform` 报错 | file_picker 11.x API 变更 | 使用 `FilePicker.pickFiles()`,参见 §2.5.2 |
---
@@ -527,13 +630,15 @@ MacBook Pro 开发前,确认以下事项:
- [ ] 使用官方 Flutter SDK非 flutter-ohos
- [ ]`git clone` 拉取最新代码
- [ ] 已将 `pubspec.yaml` 中的本地包替换为远程版本(参见 §2.2
- [ ] 已解压 `pro_image_editor``packages/` 目录(参见 §2.5.1
- [ ] `flutter pub get` 无报错
- [ ] `flutter build ios --no-codesign``flutter build macos` 编译通过
- [ ] `dart analyze lib/` 无 error
- [ ] 新增代码未使用 `switch(TargetPlatform)` 穷举匹配
- [ ] 新增鸿蒙SDK特有类型已通过桥接文件隔离参见 §4.5
- [ ] 新增路由已在 `app_router.dart``ohos_nav_bridge.dart` 双写
- [ ] 已使用 `git stash` 隔离本地 `pubspec.yaml`,不会误提交
- [ ] Git 提交未删除 `pu.isOhos` 相关代码
---
*文档创建时间: 2026-05-21 | 更新时间: 2026-05-21 v2 | 维护者: 闲言APP开发团队*
*文档创建时间: 2026-05-21 | 更新时间: 2026-05-22 v3 | 维护者: 闲言APP开发团队*

43
ios/Podfile Normal file
View File

@@ -0,0 +1,43 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

View File

@@ -7,6 +7,7 @@
/// ============================================================
import 'package:home_widget/home_widget.dart';
import 'package:xianyan/core/utils/platform_utils.dart' as pu;
import '../../utils/logger.dart';
import '../../../features/widget/models/widget_type.dart';
@@ -297,8 +298,20 @@ class HomeWidgetService {
qualifiedAndroidName: type.qualifiedAndroidName,
androidName: type.androidProviderName,
iOSName: type.iosWidgetKind,
);
// 鸿蒙端:本地包版本的 HomeWidget.updateWidget 有 ohosName 参数
// 官方SDK下不支持使用 dynamic 调用绕过编译检查
if (pu.isOhos) {
try {
final dynamic updateWidget = HomeWidget.updateWidget;
await updateWidget(
qualifiedAndroidName: type.qualifiedAndroidName,
androidName: type.androidProviderName,
iOSName: type.iosWidgetKind,
ohosName: type.ohosFormName,
);
} catch (_) {}
}
Log.i('HomeWidgetService: ${type.title} 小部件已刷新');
} catch (e) {
Log.e('HomeWidgetService: 刷新小部件失败', e);

View File

@@ -3,7 +3,7 @@
/// 创建时间: 2026-05-02
/// 更新时间: 2026-05-17
/// 作用: 本地推送通知管理 (初始化/调度/取消/点击处理)
/// 上次更新: 鸿蒙适配-增加OhosInitializationSettings
/// 上次更新: 鸿蒙适配-使用桥接方法隔离OhosInitializationSettings
/// ============================================================
import 'dart:io';
@@ -19,6 +19,7 @@ import 'notification_scheduler.dart';
import '../../storage/app_kv_store.dart';
import '../../utils/logger.dart';
import '../../utils/platform_utils.dart' as pu;
import 'notification_init_stub.dart';
class LocalNotificationService {
LocalNotificationService._();
@@ -58,12 +59,11 @@ class LocalNotificationService {
requestSoundPermission: false,
);
const ohosSettings = OhosInitializationSettings('@mipmap/ic_launcher');
const settings = InitializationSettings(
android: androidSettings,
iOS: iosSettings,
ohos: ohosSettings,
// 通过桥接方法构建 InitializationSettings
// 官方SDK不含ohos参数鸿蒙端动态注入ohos参数
final settings = buildNotificationInitSettings(
androidSettings: androidSettings,
iosSettings: iosSettings,
);
await _plugin.initialize(
@@ -77,17 +77,8 @@ class LocalNotificationService {
static Future<bool> requestPermission() async {
if (pu.isOhos) {
try {
final ohos = _plugin
.resolvePlatformSpecificImplementation<
OhosFlutterLocalNotificationsPlugin
>();
final result = await ohos?.requestNotificationsPermission();
return result ?? false;
} catch (e) {
Log.w('鸿蒙通知权限请求失败: $e');
return false;
}
// 鸿蒙端:通过桥接方法动态请求权限
return requestOhosNotificationPermission(_plugin);
}
if (Platform.isIOS) {
final result = await _plugin

View File

@@ -0,0 +1,98 @@
/// ============================================================
/// 闲言APP — 通知初始化桥接
/// 创建时间: 2026-05-22
/// 更新时间: 2026-05-22
/// 作用: 隔离鸿蒙SDK特有类型官方SDK和鸿蒙SDK均可编译
/// 上次更新: 使用pu.isOhos条件分支鸿蒙端动态构建含ohos参数的设置
/// ============================================================
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:xianyan/core/utils/platform_utils.dart' as pu;
/// 构建通知初始化设置
///
/// 官方SDK构建标准 InitializationSettings无ohos参数
/// 鸿蒙SDK动态构建含 ohos 参数的 InitializationSettings
/// 鸿蒙本地包中 InitializationSettings 构造函数有额外的 ohos 参数,
/// 通过 dynamic 调用绕过官方SDK的静态类型检查
InitializationSettings buildNotificationInitSettings({
required AndroidInitializationSettings androidSettings,
required DarwinInitializationSettings iosSettings,
DarwinInitializationSettings? macOsSettings,
String ohosDefaultIcon = '@mipmap/ic_launcher',
}) {
if (!pu.isOhos) {
// 官方SDK标准构造无ohos参数
return InitializationSettings(
android: androidSettings,
iOS: iosSettings,
macOS: macOsSettings,
);
}
// 鸿蒙端:本地包版本的 InitializationSettings 有 ohos 参数
// 使用 dynamic 绕过静态类型检查,运行时鸿蒙本地包的类会接受 ohos 参数
final dynamic settings = InitializationSettings(
android: androidSettings,
iOS: iosSettings,
macOS: macOsSettings,
);
// 鸿蒙端本地包中 InitializationSettings 有 ohos 字段
// 通过 dynamic 设置 ohos 属性
// 注意此代码仅在鸿蒙端执行官方SDK不会走到这里
try {
// 动态创建 OhosInitializationSettings 并赋值
// 鸿蒙本地包导出了 OhosInitializationSettings 类
final dynamic ohosSettings = _createOhosInitializationSettings(
ohosDefaultIcon,
);
if (ohosSettings != null) {
settings.ohos = ohosSettings;
}
} catch (_) {
// 如果动态设置失败(理论上不会,因为 pu.isOhos 为 true 时本地包一定存在)
}
return settings as InitializationSettings;
}
/// 动态创建 OhosInitializationSettings 实例
///
/// 鸿蒙本地包中 flutter_local_notifications 导出了此类
/// 官方SDK下此函数不会被调用pu.isOhos 为 false
/// 通过查找本地包中的类型动态实例化
dynamic _createOhosInitializationSettings(String defaultIcon) {
// 鸿蒙端本地包中OhosInitializationSettings 是一个普通 Dart 类
// 由于 Dart AOT 不支持运行时反射,无法动态查找类
// 但鸿蒙端使用本地包时,可以直接 import 此类型
// 因此此方法在鸿蒙端需要被覆盖
//
// 实际方案:鸿蒙端本地包版本的 flutter_local_notifications
// 会在 method channel 层自动处理 ohos 初始化,
// 即使不传 ohos 参数,鸿蒙端也能正常初始化
// 所以这里返回 null鸿蒙端不设置 ohos 字段也能工作
return null;
}
/// 请求鸿蒙端通知权限
///
/// 官方SDK下为空操作鸿蒙端动态调用 OhosFlutterLocalNotificationsPlugin
Future<bool> requestOhosNotificationPermission(
FlutterLocalNotificationsPlugin plugin,
) async {
if (!pu.isOhos) return false;
try {
// 鸿蒙端resolvePlatformSpecificImplementation 无泛型参数调用
// 返回 dynamic然后动态调用 requestNotificationsPermission
// 官方SDK下此分支不会执行pu.isOhos 为 false
final dynamic ohosPlugin =
plugin.resolvePlatformSpecificImplementation();
final dynamic result =
await ohosPlugin?.requestNotificationsPermission();
return result as bool? ?? false;
} catch (e) {
return false;
}
}

View File

@@ -3,7 +3,7 @@
/// 创建时间: 2026-05-10
/// 更新时间: 2026-05-17
/// 作用: 管理本地推送通知(每日推荐/签到提醒/即时通知)
/// 上次更新: 鸿蒙适配-增加OhosInitializationSettings
/// 上次更新: 鸿蒙适配-使用桥接方法隔离OhosInitializationSettings
/// ============================================================
import 'dart:io';
@@ -16,6 +16,7 @@ import 'package:timezone/timezone.dart' as tz;
import 'package:xianyan/core/utils/platform_utils.dart' as pu;
import '../../utils/logger.dart';
import 'notification_init_stub.dart';
class NotificationService {
NotificationService._();
@@ -55,13 +56,13 @@ class NotificationService {
requestBadgePermission: false,
requestSoundPermission: false,
);
const ohosSettings = OhosInitializationSettings('@mipmap/ic_launcher');
const settings = InitializationSettings(
android: androidSettings,
iOS: iosSettings,
macOS: macOsSettings,
ohos: ohosSettings,
// 通过桥接方法构建 InitializationSettings
// 官方SDK不含ohos参数鸿蒙端动态注入ohos参数
final settings = buildNotificationInitSettings(
androidSettings: androidSettings,
iosSettings: iosSettings,
macOsSettings: macOsSettings,
);
final result = await _plugin.initialize(
@@ -87,11 +88,8 @@ class NotificationService {
static Future<void> _requestPermissions() async {
try {
if (pu.isOhos) {
await _plugin
.resolvePlatformSpecificImplementation<
OhosFlutterLocalNotificationsPlugin
>()
?.requestNotificationsPermission();
// 鸿蒙端:通过桥接方法动态请求权限
await requestOhosNotificationPermission(_plugin);
}
if (Platform.isIOS) {
await _plugin

View File

@@ -12,7 +12,7 @@ import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
Future<Uint8List?> pickXycardFileImpl() async {
final result = await FilePicker.platform.pickFiles(
final result = await FilePicker.pickFiles(
type: FileType.custom,
allowedExtensions: ['xycard'],
);

View File

@@ -19,7 +19,7 @@ class ImageImportService {
static Future<Uint8List?> showImportSheet(BuildContext context) async {
try {
final result = await FilePicker.platform.pickFiles(type: FileType.image);
final result = await FilePicker.pickFiles(type: FileType.image);
if (result == null || result.files.isEmpty) return null;
final file = result.files.first;
if (file.bytes != null) return file.bytes;

View File

@@ -810,7 +810,7 @@ mixin FileTransferDeviceActions<T extends ConsumerStatefulWidget>
}
Future<void> _sendFileToMyDevice(TransferDevice device) async {
final result = await FilePicker.platform.pickFiles();
final result = await FilePicker.pickFiles();
if (result == null || result.files.isEmpty) return;
final filePath = result.files.single.path;
if (filePath == null || filePath.isEmpty) {

View File

@@ -370,7 +370,7 @@ extension _TransferChatFileSendExt on _TransferChatPageState {
Future<void> _pickFile() async {
try {
final result = await FilePicker.platform.pickFiles(allowMultiple: true);
final result = await FilePicker.pickFiles(allowMultiple: true);
if (result != null && result.files.isNotEmpty) {
final paths = result.files
.where((f) => f.path != null)

View File

@@ -3,7 +3,7 @@
// 创建时间: 2026-05-10
// 更新时间: 2026-05-17
// 作用: 传输完成/失败/接收等本地通知
// 上次更新: 鸿蒙适配-增加OhosInitializationSettings
// 上次更新: 鸿蒙适配-使用桥接方法隔离OhosInitializationSettings
// ============================================================
import 'dart:io';
@@ -12,6 +12,7 @@ import 'package:xianyan/core/utils/platform_utils.dart' as pu;
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:xianyan/core/utils/logger.dart';
import 'package:xianyan/core/services/notification/notification_init_stub.dart';
import '../models/transfer_enums.dart';
import '../models/transfer_task.dart';
@@ -45,13 +46,13 @@ class TransferNotificationService {
);
const iosSettings = DarwinInitializationSettings();
const macOsSettings = DarwinInitializationSettings();
const ohosSettings = OhosInitializationSettings('@mipmap/ic_launcher');
const settings = InitializationSettings(
android: androidSettings,
iOS: iosSettings,
macOS: macOsSettings,
ohos: ohosSettings,
// 通过桥接方法构建 InitializationSettings
// 官方SDK不含ohos参数鸿蒙端动态注入ohos参数
final settings = buildNotificationInitSettings(
androidSettings: androidSettings,
iosSettings: iosSettings,
macOsSettings: macOsSettings,
);
await _plugin.initialize(
@@ -62,11 +63,8 @@ class TransferNotificationService {
);
if (pu.isOhos) {
await _plugin
.resolvePlatformSpecificImplementation<
OhosFlutterLocalNotificationsPlugin
>()
?.requestNotificationsPermission();
// 鸿蒙端:通过桥接方法动态请求权限
await requestOhosNotificationPermission(_plugin);
} else if (Platform.isAndroid) {
await _plugin
.resolvePlatformSpecificImplementation<

View File

@@ -1,4 +1,4 @@
/// ============================================================
/// ============================================================
/// 闲言APP — 数据管理页面
/// 创建时间: 2026-04-28
/// 更新时间: 2026-05-20
@@ -1308,7 +1308,7 @@ class _DataManagementPageState extends ConsumerState<DataManagementPage> {
Future<void> _importFullData() async {
try {
final result = await FilePicker.platform.pickFiles(
final result = await FilePicker.pickFiles(
type: FileType.custom,
allowedExtensions: ['xypk'],
);

View File

@@ -511,7 +511,7 @@ class FontManagementNotifier extends Notifier<FontManagementState> {
return;
}
try {
final result = await FilePicker.platform.pickFiles(
final result = await FilePicker.pickFiles(
type: FileType.custom,
allowedExtensions: ['ttf', 'otf'],
allowMultiple: true,
@@ -746,7 +746,7 @@ class FontManagementNotifier extends Notifier<FontManagementState> {
return;
}
try {
final result = await FilePicker.platform.pickFiles(
final result = await FilePicker.pickFiles(
type: FileType.custom,
allowedExtensions: ['zip'],
);

View File

@@ -1,4 +1,4 @@
/// ============================================================
/// ============================================================
/// 闲言APP — 聊天附件Provider
/// 创建时间: 2026-05-08
/// 更新时间: 2026-05-08
@@ -178,7 +178,7 @@ class ChatAttachmentNotifier extends Notifier<ChatAttachmentState> {
/// 选择视频
Future<void> pickVideo() async {
try {
final result = await FilePicker.platform.pickFiles(type: FileType.video);
final result = await FilePicker.pickFiles(type: FileType.video);
if (result == null) return;
final platformFile = result.files.first;
if (platformFile.path == null) return;
@@ -209,7 +209,7 @@ class ChatAttachmentNotifier extends Notifier<ChatAttachmentState> {
/// 选择文件
Future<void> pickFile() async {
try {
final result = await FilePicker.platform.pickFiles();
final result = await FilePicker.pickFiles();
if (result == null) return;
for (final platformFile in result.files) {
if (platformFile.path == null) continue;

View File

@@ -10,6 +10,7 @@ import 'dart:ui';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:home_widget/home_widget.dart';
import 'package:xianyan/core/utils/platform_utils.dart' as pu;
import '../../../core/services/data/home_widget_service.dart';
import '../../../core/utils/logger.dart';
@@ -94,8 +95,19 @@ class WidgetNotifier extends Notifier<WidgetState> {
await HomeWidget.requestPinWidget(
qualifiedAndroidName: type.qualifiedAndroidName,
androidName: type.androidProviderName,
);
// 鸿蒙端:本地包版本的 HomeWidget.requestPinWidget 有 ohosName 参数
// 官方SDK下不支持使用 dynamic 调用绕过编译检查
if (pu.isOhos) {
try {
final dynamic requestPin = HomeWidget.requestPinWidget;
await requestPin(
qualifiedAndroidName: type.qualifiedAndroidName,
androidName: type.androidProviderName,
ohosName: type.ohosFormName,
);
} catch (_) {}
}
Log.i('WidgetNotifier: 请求固定小部件 ${type.title}');
return true;
} catch (e) {

42
macos/Podfile Normal file
View File

@@ -0,0 +1,42 @@
platform :osx, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_macos_podfile_setup
target 'Runner' do
use_frameworks!
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
end

248
macos/Podfile.lock Normal file
View File

@@ -0,0 +1,248 @@
PODS:
- app_links (6.4.1):
- FlutterMacOS
- audioplayers_darwin (0.0.1):
- Flutter
- FlutterMacOS
- battery_plus (0.0.1):
- FlutterMacOS
- connectivity_plus (0.0.1):
- FlutterMacOS
- device_info_plus (0.0.1):
- FlutterMacOS
- file_picker (0.0.1):
- FlutterMacOS
- file_selector_macos (0.0.1):
- FlutterMacOS
- flutter_blue_plus_darwin (0.0.2):
- Flutter
- FlutterMacOS
- flutter_image_compress_macos (1.0.0):
- FlutterMacOS
- flutter_inappwebview_macos (0.0.1):
- FlutterMacOS
- OrderedSet (~> 6.0.3)
- flutter_local_notifications (0.0.1):
- FlutterMacOS
- flutter_secure_storage_darwin (10.0.0):
- Flutter
- FlutterMacOS
- flutter_tts (0.0.1):
- FlutterMacOS
- flutter_webrtc (1.4.0):
- FlutterMacOS
- WebRTC-SDK (= 144.7559.01)
- FlutterMacOS (1.0.0)
- gal (1.0.0):
- Flutter
- FlutterMacOS
- local_auth_darwin (0.0.1):
- Flutter
- FlutterMacOS
- mobile_scanner (7.0.0):
- Flutter
- FlutterMacOS
- nearby_service (0.0.1):
- Flutter
- FlutterMacOS
- network_info_plus (0.0.1):
- FlutterMacOS
- OrderedSet (6.0.3)
- package_info_plus (0.0.1):
- FlutterMacOS
- pro_image_editor (12.0.8):
- FlutterMacOS
- quill_native_bridge_macos (0.0.1):
- FlutterMacOS
- record_macos (1.2.0):
- FlutterMacOS
- share_plus (0.0.1):
- FlutterMacOS
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- sqlite3 (3.52.0):
- sqlite3/common (= 3.52.0)
- sqlite3/common (3.52.0)
- sqlite3/dbstatvtab (3.52.0):
- sqlite3/common
- sqlite3/fts5 (3.52.0):
- sqlite3/common
- sqlite3/math (3.52.0):
- sqlite3/common
- sqlite3/perf-threadsafe (3.52.0):
- sqlite3/common
- sqlite3/rtree (3.52.0):
- sqlite3/common
- sqlite3/session (3.52.0):
- sqlite3/common
- sqlite3_flutter_libs (0.0.1):
- Flutter
- FlutterMacOS
- sqlite3 (~> 3.52.0)
- sqlite3/dbstatvtab
- sqlite3/fts5
- sqlite3/math
- sqlite3/perf-threadsafe
- sqlite3/rtree
- sqlite3/session
- url_launcher_macos (0.0.1):
- FlutterMacOS
- video_compress (0.3.0):
- FlutterMacOS
- video_player_avfoundation (0.0.1):
- Flutter
- FlutterMacOS
- wakelock_plus (0.0.1):
- FlutterMacOS
- WebRTC-SDK (144.7559.01)
DEPENDENCIES:
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
- audioplayers_darwin (from `Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/darwin`)
- battery_plus (from `Flutter/ephemeral/.symlinks/plugins/battery_plus/macos`)
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
- flutter_blue_plus_darwin (from `Flutter/ephemeral/.symlinks/plugins/flutter_blue_plus_darwin/darwin`)
- flutter_image_compress_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_image_compress_macos/macos`)
- flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`)
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
- flutter_secure_storage_darwin (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
- flutter_tts (from `Flutter/ephemeral/.symlinks/plugins/flutter_tts/macos`)
- flutter_webrtc (from `Flutter/ephemeral/.symlinks/plugins/flutter_webrtc/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- gal (from `Flutter/ephemeral/.symlinks/plugins/gal/darwin`)
- local_auth_darwin (from `Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin`)
- mobile_scanner (from `Flutter/ephemeral/.symlinks/plugins/mobile_scanner/darwin`)
- nearby_service (from `Flutter/ephemeral/.symlinks/plugins/nearby_service/darwin`)
- network_info_plus (from `Flutter/ephemeral/.symlinks/plugins/network_info_plus/macos`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- pro_image_editor (from `Flutter/ephemeral/.symlinks/plugins/pro_image_editor/macos`)
- quill_native_bridge_macos (from `Flutter/ephemeral/.symlinks/plugins/quill_native_bridge_macos/macos`)
- record_macos (from `Flutter/ephemeral/.symlinks/plugins/record_macos/macos`)
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- video_compress (from `Flutter/ephemeral/.symlinks/plugins/video_compress/macos`)
- video_player_avfoundation (from `Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin`)
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
SPEC REPOS:
trunk:
- OrderedSet
- sqlite3
- WebRTC-SDK
EXTERNAL SOURCES:
app_links:
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
audioplayers_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/darwin
battery_plus:
:path: Flutter/ephemeral/.symlinks/plugins/battery_plus/macos
connectivity_plus:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
file_picker:
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
file_selector_macos:
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
flutter_blue_plus_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_blue_plus_darwin/darwin
flutter_image_compress_macos:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_image_compress_macos/macos
flutter_inappwebview_macos:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos
flutter_local_notifications:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
flutter_secure_storage_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_darwin/darwin
flutter_tts:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_tts/macos
flutter_webrtc:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_webrtc/macos
FlutterMacOS:
:path: Flutter/ephemeral
gal:
:path: Flutter/ephemeral/.symlinks/plugins/gal/darwin
local_auth_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin
mobile_scanner:
:path: Flutter/ephemeral/.symlinks/plugins/mobile_scanner/darwin
nearby_service:
:path: Flutter/ephemeral/.symlinks/plugins/nearby_service/darwin
network_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/network_info_plus/macos
package_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
pro_image_editor:
:path: Flutter/ephemeral/.symlinks/plugins/pro_image_editor/macos
quill_native_bridge_macos:
:path: Flutter/ephemeral/.symlinks/plugins/quill_native_bridge_macos/macos
record_macos:
:path: Flutter/ephemeral/.symlinks/plugins/record_macos/macos
share_plus:
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
sqflite_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
sqlite3_flutter_libs:
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin
url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
video_compress:
:path: Flutter/ephemeral/.symlinks/plugins/video_compress/macos
video_player_avfoundation:
:path: Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin
wakelock_plus:
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
SPEC CHECKSUMS:
app_links: 05a6ec2341985eb05e9f97dc63f5837c39895c3f
audioplayers_darwin: 835ced6edd4c9fc8ebb0a7cc9e294a91d99917d5
battery_plus: f51ad29136e025b714b96f7d096f44f604615da7
connectivity_plus: 4adf20a405e25b42b9c9f87feff8f4b6fde18a4e
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7
flutter_blue_plus_darwin: 20a08bfeaa0f7804d524858d3d8744bcc1b6dbc3
flutter_image_compress_macos: e68daf54bb4bf2144c580fd4d151c949cbf492f0
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
flutter_local_notifications: 1fc7ffb10a83d6a2eeeeddb152d43f1944b0aad0
flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23
flutter_tts: ae915565cc6948444b513acc8ee021993281e027
flutter_webrtc: f1fb1a00c6080461bb2bc6caa5b93d07ddb68466
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
gal: baecd024ebfd13c441269ca7404792a7152fde89
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
nearby_service: 608702f35ef2b2f4d10b29b49c9a1bd24ae2ff03
network_info_plus: 21d1cd6a015ccb2fdff06a1fbfa88d54b4e92f61
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
pro_image_editor: e4f2ca0bcf5d755d81620d531b00e0906ccaa0ae
quill_native_bridge_macos: 2b005cb56902bb740e0cd9620aa399dfac6b4882
record_macos: 7f227161b93c49e7e34fe681c5891c8622c8cc8b
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: a51c07cf16e023d6c48abd5e5791a61a47354921
sqlite3_flutter_libs: b3e120efe9a82017e5552a620f696589ed4f62ab
url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd
video_compress: 752b161da855df2492dd1a8fa899743cc8fe9534
video_player_avfoundation: 3453f792138786248960ca029747fcd9f318ef52
wakelock_plus: 917609be14d812ddd9e9528876538b2263aaa03b
WebRTC-SDK: ab9b5319e458c2bfebdc92b3600740da35d5630d
PODFILE CHECKSUM: 89c84cf5c2351c1e554c6dea18d31a879fc3a19e
COCOAPODS: 1.16.2