chore: 迁移依赖、移除sqlite3_flutter_libs并新增功能

1. 替换hive_flutter为hive_ce_flutter依赖
2. 从各平台插件列表移除sqlite3_flutter_libs
3. 重构API请求体格式,优化历史记录去重逻辑
4. 新增CTC笔记相关功能:桌面小部件、模板模型、本地存储
5. 新增表单收集服务和后台管理接口
6. 优化缓存配置、多语言文案和UI细节
7. 重构首页状态监听组件
This commit is contained in:
Developer
2026-06-15 10:04:52 +08:00
parent af14ed4121
commit ad00967c68
90 changed files with 4728 additions and 1028 deletions

View File

@@ -11,7 +11,7 @@ import 'dart:io';
import 'package:archive/archive.dart';
import 'package:crypto/crypto.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hive_ce_flutter/hive_flutter.dart';
import '../../storage/database/app_database.dart';
import '../../storage/kv_storage.dart';

View File

@@ -9,7 +9,7 @@
import 'dart:io';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hive_ce_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import '../../storage/kv_storage.dart';

View File

@@ -10,7 +10,7 @@ import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hive_ce_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';

View File

@@ -1,19 +1,18 @@
/// ============================================================
/// 闲言APP — 日历同步服务
/// 创建时间: 2026-05-29
/// 更新时间: 2026-06-06
/// 更新时间: 2026-06-15
/// 作用: 跨平台日历事件同步Android/iOS/HarmonyOS/macOS/Windows
/// 上次更新: 鸿蒙端MethodChannel添加超时保护+MissingPluginException捕获+平台判断早期返回
/// 上次更新: 迁移至 device_calendar_plus适配新 APIDeviceCalendar 单例、CalendarPermissionStatus、listCalendars/createEvent/deleteEvent 新签名)
/// ============================================================
import 'dart:io';
import 'dart:async';
import 'package:device_calendar/device_calendar.dart';
import 'package:device_calendar_plus/device_calendar_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:xianyan/core/utils/logger.dart';
import 'package:xianyan/core/utils/platform/platform_utils.dart' as pu;
@@ -43,7 +42,7 @@ class CalendarService {
CalendarService._();
static final CalendarService instance = CalendarService._();
final DeviceCalendarPlugin _plugin = DeviceCalendarPlugin();
final DeviceCalendar _plugin = DeviceCalendar.instance;
String? _calendarId;
bool _isAvailable = false;
@@ -79,11 +78,12 @@ class CalendarService {
Log.w('CalendarService: 当前平台不支持日历');
return false;
}
final hasPermissions = await _plugin.hasPermissions();
if (hasPermissions.isSuccess && !hasPermissions.data!) {
final status = await _plugin.hasPermissions();
if (status != CalendarPermissionStatus.granted) {
final result = await _plugin.requestPermissions();
if (!result.isSuccess || !result.data!) {
Log.w('CalendarService: 日历权限被拒绝');
if (result != CalendarPermissionStatus.granted &&
result != CalendarPermissionStatus.writeOnly) {
Log.w('CalendarService: 日历权限被拒绝 ($result)');
return false;
}
}
@@ -122,23 +122,18 @@ class CalendarService {
/// 确保闲言专属日历存在,不存在则创建
Future<void> _ensureCalendar() async {
final calendars = await _plugin.retrieveCalendars();
if (calendars.isSuccess && calendars.data != null) {
final existing = calendars.data!.where(
(c) => c.name == '闲言' || c.name == 'Xianyan',
final calendars = await _plugin.listCalendars();
final existing = calendars.where(
(c) => c.name == '闲言' || c.name == 'Xianyan',
);
if (existing.isNotEmpty) {
_calendarId = existing.first.id;
} else {
final calendarId = await _plugin.createCalendar(
name: '闲言',
colorHex: '#007AFF',
);
if (existing.isNotEmpty) {
_calendarId = existing.first.id;
} else {
final result = await _plugin.createCalendar(
'闲言',
calendarColor: const Color(0xFF007AFF),
localAccountName: '闲言APP',
);
if (result.isSuccess) {
_calendarId = result.data;
}
}
_calendarId = calendarId;
}
}
@@ -148,6 +143,7 @@ class CalendarService {
/// 添加日历事件
/// 鸿蒙端通过_addEventOhos()桥接通道未实现时返回false
/// 注意device_calendar_plus 暂不支持 ReminderreminderMinutesBefore 仅鸿蒙端生效
Future<bool> addEvent(CalendarEvent event) async {
// 鸿蒙端:直接走鸿蒙通道
if (_isOhos()) {
@@ -160,31 +156,26 @@ class CalendarService {
}
try {
final local = tz.local;
final calendarEvent = Event(
_calendarId,
// device_calendar_plus 使用 createEvent 方法,无需手动构造 Event 对象
await _plugin.createEvent(
calendarId: _calendarId!,
title: event.title,
startDate: event.start,
endDate: event.end,
description: event.description,
start: tz.TZDateTime.from(event.start, local),
end: tz.TZDateTime.from(event.end, local),
location: event.location,
);
// device_calendar_plus 暂不支持 Reminder记录提示
if (event.reminderMinutesBefore != null) {
calendarEvent.reminders = [
Reminder(minutes: event.reminderMinutesBefore!),
];
Log.w(
'CalendarService: device_calendar_plus 暂不支持 Reminder'
'reminderMinutesBefore=${event.reminderMinutesBefore} 已忽略',
);
}
final result = await _plugin.createOrUpdateEvent(calendarEvent);
if (result?.isSuccess == true) {
Log.i('CalendarService: 事件已添加 - ${event.title}');
return true;
}
Log.e(
'CalendarService: 添加事件失败 - ${result?.errors.map((e) => e.errorMessage)}',
);
return false;
Log.i('CalendarService: 事件已添加 - ${event.title}');
return true;
} catch (e) {
Log.e('CalendarService: 添加事件异常', e);
return false;
@@ -216,10 +207,9 @@ class CalendarService {
/// 删除日历事件
Future<bool> deleteEvent(String eventId) async {
if (_calendarId == null) return false;
try {
final result = await _plugin.deleteEvent(_calendarId!, eventId);
return result.isSuccess;
await _plugin.deleteEvent(eventId: eventId);
return true;
} catch (e) {
Log.e('CalendarService: 删除事件异常', e);
return false;

View File

@@ -11,7 +11,7 @@ import 'dart:isolate';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hive_ce_flutter/hive_flutter.dart';
import '../../utils/logger.dart';
import '../../utils/platform/platform_utils.dart' as pu;

View File

@@ -11,7 +11,7 @@ import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hive_ce_flutter/hive_flutter.dart';
import '../../network/api_client.dart';
import '../../storage/kv_storage.dart';

View File

@@ -0,0 +1,82 @@
/// ============================================================
/// 闲言APP — 表单收集服务
/// 创建时间: 2026-06-15
/// 更新时间: 2026-06-15
/// 作用: 调用 /api/form_collect/submit 提交表单信息(邮箱等)
/// 上次更新: v6.73.0 初始版本
/// ============================================================
import '../../network/api_client.dart';
import '../../utils/logger.dart';
/// 表单来源标识
enum FormCollectSource {
/// app.html Google Play内测
appGpBeta('app_gp_beta'),
/// 注册页面订阅闲言邮箱
registerSubscribe('register_subscribe'),
/// Beta页面问卷填写Gmail
betaQuestionnaire('beta_questionnaire');
const FormCollectSource(this.value);
final String value;
}
/// 表单收集服务
class FormCollectService {
FormCollectService._();
static final FormCollectService instance = FormCollectService._();
static const String _submitPath = '/api/form_collect/submit';
/// 提交表单
///
/// [email] 邮箱地址(必填)
/// [source] 来源标识(必填)
/// [uid] 用户ID可选
/// [extraJson] 扩展字段JSON字符串可选
/// [deviceId] 设备ID可选
///
/// 返回 true 提交成功false 提交失败
Future<bool> submit({
required String email,
required FormCollectSource source,
String? uid,
String? extraJson,
String? deviceId,
}) async {
try {
final data = <String, dynamic>{
'email': email,
'source': source.value,
};
if (uid != null && uid.isNotEmpty) data['uid'] = uid;
if (extraJson != null && extraJson.isNotEmpty) {
data['extra_json'] = extraJson;
}
if (deviceId != null && deviceId.isNotEmpty) {
data['device_id'] = deviceId;
}
final response = await ApiClient.instance.post<Map<String, dynamic>>(
_submitPath,
data: data,
);
final result = response.data;
final code = result?['code'];
if (code == 1) {
Log.d('FormCollect: 提交成功 source=${source.value} email=$email');
return true;
}
Log.w('FormCollect: 提交失败 code=$code msg=${result?['msg']}');
return false;
} catch (e) {
Log.e('FormCollect: 提交异常 $e');
return false;
}
}
}