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.

131 lines
3.6 KiB

import 'package:get/get.dart';
import 'dart:async';
import 'dart:io';
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;
ConnectStatus get connectStatus => _connectStatus.value;
String get searchDots => _searchDots.value;
@override
void onInit() {
super.onInit();
_connectStatus.value = ConnectStatus.initial;
VoiceInteractionService.to.initialize();
}
@override
void onClose() {
_isDisposed = true;
stopSearchingAnimation();
super.onClose();
}
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),
);
}
}