Files
flutterApp/lib/features/auth/presentation/bloc/auth_cubit.dart

107 lines
3.9 KiB
Dart
Raw Normal View History

2026-01-11 19:42:22 +08:00
import 'dart:async';
import 'package:flutter/cupertino.dart';
2026-01-11 19:42:22 +08:00
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
2026-01-11 19:42:22 +08:00
import 'package:maibu_satabot_v2/core/consts/tcp_consts.dart';
import 'package:maibu_satabot_v2/core/domain/entities/user_entity.dart';
import 'package:maibu_satabot_v2/core/network/net_message_dispatcher.dart';
2026-01-18 20:21:14 +08:00
import '../../../../core/app/app_user_cubit.dart';
import '../../../../core/infrastructure/logging/sentry_logger_impl.dart';
import '../../../../core/logging/i_logger_service.dart';
2026-01-11 19:42:22 +08:00
import '../../../../core/network/tcp/tcp_client.dart';
import '../../../../core/storage/user_storage.dart';
import '../../../devices/domain/usecases/get_user_device_usecase.dart';
import '../../../devices/domain/usecases/switch_device_usecase.dart';
import '../../../devices/presentation/bloc/devices_cubit.dart';
import '../../data/datasources/auth_tcp_datasource.dart';
import '../../data/datasources/impl/auth_tcp_datasource_impl.dart';
2026-01-11 19:42:22 +08:00
import 'auth_state.dart';
/// emit做的事情:
/// 1.修改状态标志:通过改变类的类型(从 Initial 变成 Authenticated)
/// 2.携带数据:把 user 对象塞进了状态里,让外部能拿到
/// 3.发送通知:自动触发监听(如 GoRouter 的刷新)。
class AuthCubit extends Cubit<AuthState> {
final UserStorage storage;
final TcpClient tcp;
2026-01-18 20:21:14 +08:00
final AppUserCubit appCubit;
2026-01-11 19:42:22 +08:00
final NetMessageDispatcher dispatcher;
final AuthTcpDatasource _authTcpDatasource;
2026-01-11 19:42:22 +08:00
StreamSubscription? _kickOutSub; // 新增:用于管理监听生命周期
AuthCubit(this.storage, this.tcp, this.appCubit, this.dispatcher, this._authTcpDatasource) : super(AuthInitial()) {
2026-01-11 19:42:22 +08:00
// Cubit 一启动就开始监听 TCP 的“自动逻辑”
_listenToAuthResponse();
}
/// App 启动时检查本地缓存
Future<void> appStarted() async {
final logger = GetIt.I<ILoggerService>() as SentryLoggerImpl;
// print("App 启动时检查本地缓存");
2026-01-11 19:42:22 +08:00
final user = await storage.getUser();
logger.logWithLevel(
'启动时检查本地缓存',
level: 'INFO',
data: {'user': user, 'data': user}
);
2026-01-11 19:42:22 +08:00
if (user != null) {
tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT);
// await _authTcpDatasource.sendAuthPacket();//包括发送认证包和获取列表和切换函数
tcp.startHeartbeat(interval: const Duration(seconds: 4));
2026-01-11 19:42:22 +08:00
// 2. 同步全局 App 状态
appCubit.setAuth(user);
// 3. 进入已登录状态
emit(AuthAuthenticated(user));
} else {
// print("App 启动时检查本地缓存user=null) ");
2026-01-11 19:42:22 +08:00
emit(AuthUnauthenticated());
}
}
/// 当 HTTP 登录/注册成功后调用
Future<void> loginSuccess(UserEntity user) async {
await storage.saveUser(user);
//await tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT);
// await _authTcpDatasource.sendAuthPacket(); //包括发送认证包和获取列表和切换函数
//tcp.startHeartbeat(interval: const Duration(seconds: 4)); //启动心跳
appCubit.setAuth(user);
2026-01-11 19:42:22 +08:00
emit(AuthAuthenticated(user));
}
/// 退出登录 (主动或被动)
Future<void> logout() async {
print("退出登录");
2026-01-11 19:42:22 +08:00
await storage.deleteUser();
tcp.disconnect();
appCubit.clearAuth();
emit(AuthUnauthenticated());
}
/// TCP 指令监听
void _listenToAuthResponse() {
_kickOutSub?.cancel(); // 防止重复监听
// 假设 0x12 是踢下线或多设备登录提醒
_kickOutSub = dispatcher.onJsonMessage(0x12).listen((json) {
// 如果后端发来指令确认需要退出
// print('>>> [AUTH] 收到 0x12: $json'); //
// logout();
final respond = json['respond'] ?? '';
if (respond == 'have_logged_in') {
logout(); // ✅ 只有特定消息才退出
}
2026-01-11 19:42:22 +08:00
});
}
2026-01-11 19:42:22 +08:00
@override
Future<void> close() {
_kickOutSub?.cancel(); // 销毁 Cubit 时关闭监听
return super.close();
}
}