- 更新设备屏幕尺寸配置从1920*1080调整为1024x600 - 添加完成页面的AppBar导航和返回功能 - 重构CompletePage布局,使用SafeArea和ConstrainedBox适配不同屏幕 - 添加国际化支持的完成按钮文本 - 优化完成页面视觉元素,包括图标大小和间距调整 - 实现串口连接状态的响应式管理,解决UI状态同步问题 - 优化串口运行器的状态更新逻辑,实现乐观更新机制 - 调整完成页面按钮布局,提供完成和重新运行选项
126 lines
4.1 KiB
Dart
126 lines
4.1 KiB
Dart
import 'dart:async';
|
||
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
|
||
import '../../../core/database/database_service.dart';
|
||
import '../models/serial_config.dart';
|
||
import '../services/auto_serial_connect.dart';
|
||
import '../services/device_message_service.dart';
|
||
import '../services/json_protocol.dart';
|
||
import '../services/runner_interface.dart';
|
||
import '../services/serial_port_service.dart';
|
||
import '../services/serial_runner.dart';
|
||
|
||
/// 串口服务单例
|
||
final serialPortServiceProvider = Provider<SerialPortService>((ref) {
|
||
final service = SerialPortService();
|
||
ref.onDispose(service.dispose);
|
||
return service;
|
||
});
|
||
|
||
/// 串口连接状态(响应式)
|
||
///
|
||
/// 直接 `ref.watch(serialPortServiceProvider).state` 不会触发 UI 重建,
|
||
/// 因为 [SerialPortService] 内部 `_state` 的变化不会冒泡到 Provider 层。
|
||
/// 这里把状态抽出为独立的 StateNotifierProvider,让状态栏等 UI 能即时
|
||
/// 反映连接/断开事件,避免出现"标题栏显示已连接、实际下发失败"的错觉。
|
||
class SerialConnectionStateNotifier
|
||
extends StateNotifier<SerialConnectionState> {
|
||
SerialConnectionStateNotifier(this._service) : super(_service.state) {
|
||
_sub = _service.connectionStateChanges.listen((s) => state = s);
|
||
}
|
||
|
||
final SerialPortService _service;
|
||
late final StreamSubscription<SerialConnectionState> _sub;
|
||
|
||
@override
|
||
void dispose() {
|
||
_sub.cancel();
|
||
super.dispose();
|
||
}
|
||
}
|
||
|
||
final serialConnectionStateProvider = StateNotifierProvider<
|
||
SerialConnectionStateNotifier, SerialConnectionState>((ref) {
|
||
final service = ref.watch(serialPortServiceProvider);
|
||
return SerialConnectionStateNotifier(service);
|
||
});
|
||
|
||
/// 启动自动连接服务
|
||
///
|
||
/// 通过 [main] 中的 ProviderContainer 在 runApp 之前触发一次,
|
||
/// 服务内部立即尝试连接第一个 USB 串口设备,失败时按 3s 间隔重试。
|
||
final autoSerialConnectProvider = Provider<AutoSerialConnect>((ref) {
|
||
final service = ref.watch(serialPortServiceProvider);
|
||
final auto = AutoSerialConnect(service);
|
||
auto.start();
|
||
ref.onDispose(auto.dispose);
|
||
return auto;
|
||
});
|
||
|
||
/// JSON 协议编解码器(可在调试/真机协议不一致时整体替换)
|
||
final jsonProtocolProvider = Provider<JsonProtocolService>((ref) {
|
||
return JsonProtocolService();
|
||
});
|
||
|
||
/// 设备消息分发服务
|
||
///
|
||
/// 集中处理 JSON 消息的发送与订阅;下游 Provider 各自订阅感兴趣的类型。
|
||
final deviceMessageServiceProvider =
|
||
Provider<DeviceMessageService>((ref) {
|
||
final serial = ref.watch(serialPortServiceProvider);
|
||
final protocol = ref.watch(jsonProtocolProvider);
|
||
final service = DeviceMessageService(serial: serial, protocol: protocol);
|
||
ref.onDispose(service.dispose);
|
||
return service;
|
||
});
|
||
|
||
/// 当前串口配置(设置页修改后通过 notifier 写入并持久化)
|
||
class SerialConfigNotifier extends StateNotifier<SerialConfig> {
|
||
final SettingsConfigRepository _repo;
|
||
|
||
SerialConfigNotifier(this._repo) : super(SerialConfig.defaults) {
|
||
_load();
|
||
}
|
||
|
||
Future<void> _load() async {
|
||
state = await _repo.read();
|
||
}
|
||
|
||
/// 修改并持久化
|
||
Future<void> update(SerialConfig Function(SerialConfig) mutator) async {
|
||
final next = mutator(state);
|
||
state = next;
|
||
await _repo.write(next);
|
||
}
|
||
|
||
/// 重置为默认值
|
||
Future<void> reset() => update((_) => SerialConfig.defaults);
|
||
}
|
||
|
||
/// 串口配置仓库:把 [SerialConfig] 以 JSON 形式存到 settings 表
|
||
class SettingsConfigRepository {
|
||
static const _key = 'serial_config';
|
||
final DatabaseService _db = DatabaseService.instance;
|
||
|
||
Future<SerialConfig> read() async {
|
||
final raw = await _db.readSetting(_key);
|
||
return SerialConfig.fromJsonString(raw);
|
||
}
|
||
|
||
Future<void> write(SerialConfig config) async {
|
||
await _db.writeSetting(_key, config.toJsonString());
|
||
}
|
||
}
|
||
|
||
final serialConfigProvider =
|
||
StateNotifierProvider<SerialConfigNotifier, SerialConfig>((ref) {
|
||
return SerialConfigNotifier(SettingsConfigRepository());
|
||
});
|
||
|
||
/// 运行器实例(基于 JSON 协议与设备消息服务)
|
||
final runnerProvider = Provider<Runner>((ref) {
|
||
final msgService = ref.watch(deviceMessageServiceProvider);
|
||
return JsonSerialRunner(messageService: msgService);
|
||
});
|