You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
5.8 KiB

import 'package:get/get.dart';
import 'dart:async';
import 'package:flutter/material.dart';
import '../../../data/services/voice_interaction_service.dart';
enum ConnectStatus {
initial, // 初始状态,显示添加设备
searching, // 搜索中
connected, // 连接成功
failed // 连接失败
}
class HomeController extends GetxController {
static HomeController get to => Get.find();
final _connectStatus = ConnectStatus.initial.obs;
final _searchDots = ''.obs;
Timer? _animationTimer;
bool _isDisposed = false;
// 语音服务状态
final _voiceServiceRunning = false.obs;
bool get voiceServiceRunning => _voiceServiceRunning.value;
ConnectStatus get connectStatus => _connectStatus.value;
String get searchDots => _searchDots.value;
@override
void onInit() {
super.onInit();
_connectStatus.value = ConnectStatus.initial;
// 获取语音服务状态
_updateVoiceServiceStatus();
}
@override
void onClose() {
_isDisposed = true;
stopSearchingAnimation();
super.onClose();
}
/// 更新语音服务状态
Future<void> _updateVoiceServiceStatus() async {
if (Get.isRegistered<VoiceInteractionService>()) {
_voiceServiceRunning.value = VoiceInteractionService.to.isRunning;
} else {
_voiceServiceRunning.value = false;
}
}
/// 启动语音交互服务
Future<void> startVoiceService() async {
// 确保 ConfigService 已初始化
// 确保 VoiceInteractionService 已初始化
if (!Get.isRegistered<VoiceInteractionService>()) {
await Get.putAsync(() => VoiceInteractionService().init());
}
final result = await VoiceInteractionService.to.startService();
await _updateVoiceServiceStatus();
if (result) {
Get.snackbar(
'成功',
'语音交互服务已启动',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green.withOpacity(0.1),
colorText: Colors.green,
duration: const Duration(seconds: 2),
);
} else {
Get.snackbar(
'错误',
'启动语音交互服务失败',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.1),
colorText: Colors.red,
duration: const Duration(seconds: 2),
);
}
}
/// 停止语音交互服务
Future<void> stopVoiceService() async {
if (!Get.isRegistered<VoiceInteractionService>()) {
await Get.putAsync(() => VoiceInteractionService().init());
}
final result = await VoiceInteractionService.to.stopService();
await _updateVoiceServiceStatus();
if (result) {
Get.snackbar(
'成功',
'语音交互服务已停止',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.blue.withOpacity(0.1),
colorText: Colors.blue,
duration: const Duration(seconds: 2),
);
} else {
Get.snackbar(
'错误',
'停止语音交互服务失败',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.1),
colorText: Colors.red,
duration: const Duration(seconds: 2),
);
}
}
void startSearchingAnimation() {
stopSearchingAnimation(); // Clear any existing timer
if (_isDisposed) return;
int count = 0;
_animationTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) {
if (_isDisposed || _connectStatus.value != ConnectStatus.searching) {
timer.cancel();
return;
}
count = (count + 1) % 4;
_searchDots.value = '.' * count;
});
}
void stopSearchingAnimation() {
_animationTimer?.cancel();
_animationTimer = null;
if (!_isDisposed) {
_searchDots.value = '';
}
}
Future<void> connectDevice() async {
if (_connectStatus.value == ConnectStatus.searching) return;
_connectStatus.value = ConnectStatus.searching;
startSearchingAnimation();
try {
// 模拟搜索和连接过程
await Future.delayed(const Duration(seconds: 3));
if (_isDisposed) return; // Check if controller is disposed
// 模拟随机成功或失败
if (DateTime.now().millisecondsSinceEpoch % 2 == 0) {
_connectStatus.value = ConnectStatus.connected;
if (!_isDisposed) {
await Future.delayed(const Duration(seconds: 2)); // 显示成功状态2秒
Get.snackbar(
'Success',
'Device connected successfully',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green.withOpacity(0.1),
colorText: Colors.green,
duration: const Duration(seconds: 3),
);
}
} else {
_connectStatus.value = ConnectStatus.failed;
}
} catch (e) {
if (!_isDisposed) {
_connectStatus.value = ConnectStatus.failed;
Get.snackbar(
'Error',
'Failed to connect to device',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.1),
colorText: Colors.red,
duration: const Duration(seconds: 3),
);
}
} finally {
if (!_isDisposed && _connectStatus.value == ConnectStatus.searching) {
stopSearchingAnimation();
_connectStatus.value = ConnectStatus.failed;
}
}
}
void retryConnect() {
if (_isDisposed) return;
_connectStatus.value = ConnectStatus.initial;
connectDevice();
}
void disconnectDevice() {
if (_isDisposed) return;
_connectStatus.value = ConnectStatus.initial;
Get.snackbar(
'Disconnected',
'Device has been disconnected',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.blue.withOpacity(0.1),
colorText: Colors.blue,
duration: const Duration(seconds: 3),
);
}
}