chore: 汇总批量提交的功能优化与bug修复

本次提交包含多项迭代优化和问题修复:
1. 新增缩略图图片组件、数字格式化工具类,补充多语言翻译类型与本地化支持
2. 优化底部导航栏主题色统一使用动态accent色值
3. 修复多处图表动画、路由跳转、API请求相关问题
4. 简化服务器公告文案,调整默认分屏状态为关闭
5. 新增安卓/iOS桌面快捷方式配置
6. 重构多处状态管理类使用SafeNotifierInit统一异常保护
7. 替换硬编码蓝色为主题色,更新版本号获取方式为动态读取
8. 优化缓存预加载逻辑,移除无用代码
9. 调整默认设置项,优化用户体验细节
This commit is contained in:
Developer
2026-05-31 12:24:05 +08:00
parent 0da8906f5d
commit 9ea8d3d606
298 changed files with 48547 additions and 21836 deletions

View File

@@ -1,9 +1,9 @@
/// ============================================================
/// 闲言APP — 语音输入Provider
/// 创建时间: 2026-05-25
/// 更新时间: 2026-05-25
/// 更新时间: 2026-05-30
/// 作用: 语音服务状态管理 + 识别结果Provider
/// 上次更新: 初始创建
/// 上次更新: 修复隐私问题 — build()不再自动初始化语音服务,改为用户主动触发时才初始化
/// ============================================================
import 'dart:async';
@@ -22,6 +22,7 @@ class SpeechState {
this.lastResult = '',
this.locale = 'zh_CN',
this.errorMessage,
this.isInitialized = false,
});
final bool isAvailable;
@@ -31,6 +32,9 @@ class SpeechState {
final String locale;
final String? errorMessage;
/// 是否已初始化仅用户主动触发后才为true
final bool isInitialized;
SpeechState copyWith({
bool? isAvailable,
bool? isListening,
@@ -38,6 +42,7 @@ class SpeechState {
String? lastResult,
String? locale,
String? errorMessage,
bool? isInitialized,
}) {
return SpeechState(
isAvailable: isAvailable ?? this.isAvailable,
@@ -46,11 +51,15 @@ class SpeechState {
lastResult: lastResult ?? this.lastResult,
locale: locale ?? this.locale,
errorMessage: errorMessage,
isInitialized: isInitialized ?? this.isInitialized,
);
}
}
/// 语音服务Notifier
///
/// 安全设计build()不自动初始化语音服务,避免在页面加载时
/// 触发麦克风权限申请。仅在用户主动点击语音按钮时调用init()。
class SpeechNotifier extends Notifier<SpeechState> {
StreamSubscription<SpeechServiceState>? _stateSub;
StreamSubscription<SpeechResult>? _resultSub;
@@ -59,15 +68,16 @@ class SpeechNotifier extends Notifier<SpeechState> {
@override
SpeechState build() {
ref.onDispose(_onDispose);
_initAndSubscribe();
return const SpeechState();
}
Future<void> _initAndSubscribe() async {
final service = SpeechService.instance;
/// 用户主动触发初始化 — 仅此时才请求麦克风权限
Future<bool> init() async {
if (state.isInitialized) return state.isAvailable;
final service = SpeechService.instance;
final available = await service.init();
state = state.copyWith(isAvailable: available);
state = state.copyWith(isAvailable: available, isInitialized: true);
_stateSub = service.onStateChanged.listen((s) {
state = state.copyWith(
@@ -91,6 +101,8 @@ class SpeechNotifier extends Notifier<SpeechState> {
state = state.copyWith(errorMessage: error);
Log.w('SpeechProvider: 错误 $error');
});
return available;
}
/// 开始语音识别