Files
feature-next-arch/lib/features/home/presentation/pages/home_page.dart
Songzex 443ce601a0 1更新无人机的摄像头视频显示的条件为在离线情况下的自动刷新+下拉刷新的机制。
2更新优化去除原有路径规划的初始化阶段的获取设备的接口请求,改为使用新的 targetDevice。
3修改无人机机场的在线状态简化为在线和离线。去掉机场二字。
4.更新同一账号同时段登录,被强制下线的友好提示!
2026-06-17 13:46:30 +08:00

159 lines
6.0 KiB
Dart
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import 'package:maibu_satabot_v2/core/app/app_user_cubit.dart';
import 'package:maibu_satabot_v2/core/consts/tcp_consts.dart';
import 'package:maibu_satabot_v2/core/localization/app_localizations.dart';
import 'package:maibu_satabot_v2/core/network/tcp/tcp_client.dart';
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart';
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_state.dart'; // 👈 必须加
import 'package:maibu_satabot_v2/features/remote_control/domain/repositories/remote_control_repository.dart';
import 'package:maibu_satabot_v2/features/remote_control/presentation/bloc/remote_control_cubit.dart';
import '../../../devices/domain/entities/device_entity.dart';
import '../bloc/permission_request_bloc.dart';
import '../bloc/permission_request_state.dart';
import '../bloc/permission_request_event.dart';
import '../widgets/ImmersionHeader.dart';
import '../widgets/quick_actions_grid.dart';
import '../widgets/work_params_card.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isInitializing = false;
bool _isDevicesLoading = true; // 👈 新加:设备加载中状态
bool _hasLoadedDevices = false;
/// 🔥 修复:等待设备加载完成,再执行后续逻辑
Future<void> _initializePage() async {
if (_isInitializing) return;
_isInitializing = true;
try {
final username = context.read<AppUserCubit>().state.user?.username;
if (username == null || username.isEmpty) {
setState(() => _isDevicesLoading = false);
return;
}
final devicesCubit = context.read<DevicesCubit>();
// 🔥 修复:检查是否已有 targetDevice,如果有则不需要加载设备列表
final remoteControlState = context.read<RemoteControlCubit>().state;
if (remoteControlState.targetDevice != null) {
debugPrint('✅ [HomePage] 已有 targetDevice: ${remoteControlState.targetDevice!.deviceName},跳过设备列表加载');
setState(() {
_isDevicesLoading = false;
_hasLoadedDevices = true;
});
return;
}
// 🔥 关键:等待设备加载完成
await devicesCubit.fetchAllDevices(username);
// 🔥 加载完成!关闭 loading
setState(() {
_isDevicesLoading = false;
_hasLoadedDevices = true;
});
// 🔥 现在再拿设备列表 = 最新的,绝对不是旧的!
final deviceList = devicesCubit.state.devices ?? [];
if (deviceList.isNotEmpty) {
final firstDevice = deviceList.first;
// 🔥 自动选中第一个设备(保证是最新的)
devicesCubit.selectDevice(firstDevice);
// 🔥 关键修复:首页不再自动连接TCP,改为选择设备时才连接
// 连接 TCP
// final tcpClient = GetIt.instance<TcpClient>();
// if (!tcpClient.isConnected) {
// tcpClient.connectBySwitch(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT, deviceName: firstDevice.deviceName).then((_) {
// debugPrint('✅ [HomePage] TCP 连接成功');
// tcpClient.startHeartbeat(interval: const Duration(seconds: 4));
//
// // 🔥 关键:TCP 连接成功后,主动请求权限以激活服务器的推送机制
// final remoteRepo = GetIt.instance<RemoteControlRepository>();
// remoteRepo.requestControlPermission(firstDevice.deviceName, "app");
// debugPrint('✅ [HomePage] 已发送权限请求,激活服务器推送');
// });
// } else {
// // 🔥 TCP 已连接,也要发送权限请求
// final remoteRepo = GetIt.instance<RemoteControlRepository>();
// remoteRepo.requestControlPermission(firstDevice.deviceName, "app");
// debugPrint('✅ [HomePage] TCP 已连接,已发送权限请求');
// }
debugPrint('ℹ️ [HomePage] TCP 连接已移至选择设备时执行');
}
} catch (e) {
setState(() => _isDevicesLoading = false);
debugPrint('初始化异常:$e');
} finally {
_isInitializing = false;
}
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_initializePage();
});
}
@override
Widget build(BuildContext context) {
final userState = context.watch<AppUserCubit>().state;
final deviceState = context.watch<DevicesCubit>().state;
// 🔥 加载中 → 显示 Loading
if (_isDevicesLoading) {
return const Scaffold(body: Center(child: CircularProgressIndicator()));
}
// 🔥 现在取的设备 = 100% 最新加载完成的
final currentDevice = deviceState.selectedDevice;
final defaultDevice = DeviceEntity(
deviceName: AppLocalizations.of(context).translate('home.no_device_bound'),
productId: 00000,
productName: '',
tenantId: 00000,
tenantName: '',
);
// 🔥 移除 PermissionRequestBloc 监听,统一由 RemoteControlCubit 处理权限弹窗
return Scaffold(
backgroundColor: const Color(0xFFF7F7F7),
body: CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
SliverToBoxAdapter(child: ImmersionHeader(device: currentDevice ?? defaultDevice)),
const SliverToBoxAdapter(child: QuickActionsGrid()),
SliverToBoxAdapter(child: WorkParamsCard()),
const SliverToBoxAdapter(child: SizedBox(height: 120)),
],
),
);
}
// 🔥 移除首页的权限弹窗方法,统一由 RemoteControlCubit 处理
// Widget _buildPermissionDialog(BuildContext context, PermissionRequestDialogVisible state) {
// ...
// }
@override
void dispose() {
super.dispose();
}
}