远程遥控界面视频实现
This commit is contained in:
@@ -23,14 +23,12 @@ class RemoteControlPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
String _videoStreamUrl = "";
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 1. 锁定横屏
|
||||
SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.landscapeLeft,
|
||||
DeviceOrientation.landscapeRight,
|
||||
]);
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
|
||||
// 2. 隐藏状态栏和虚拟按键
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
|
||||
|
||||
@@ -53,10 +51,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
final deviceState = context.watch<DevicesCubit>().state;
|
||||
final currentDevice = deviceState.selectedDevice;
|
||||
|
||||
context.read<RemoteControlCubit>().requestControlPermissionS(
|
||||
currentDevice!.deviceName,
|
||||
"app",
|
||||
);
|
||||
context.read<RemoteControlCubit>().requestControlPermissionS(currentDevice!.deviceName, "app");
|
||||
|
||||
if (currentDevice == null) {
|
||||
return _buildOfflineScaffold();
|
||||
@@ -70,15 +65,19 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
Positioned.fill(
|
||||
child: BlocBuilder<RemoteControlCubit, RemoteControlState>(
|
||||
// 只有当显示隐藏状态改变时才重构,内部的拖拽由组件自身 State 处理,不影响这里
|
||||
buildWhen: (p, c) =>
|
||||
p.showLeftPip != c.showLeftPip ||
|
||||
p.showRightPip != c.showRightPip,
|
||||
buildWhen: (p, c) => p.showLeftPip != c.showLeftPip || p.showRightPip != c.showRightPip,
|
||||
|
||||
builder: (context, state) {
|
||||
final deviceId = context.watch<DevicesCubit>().state.selectedDevice?.deviceName;
|
||||
if (deviceId != null && userState.user != null && userState.user!.token != null) {
|
||||
_videoStreamUrl = "webrtc://${TCPConsts.TCP_IP}/live/livestream/$deviceId?token=${userState.user!.token}";
|
||||
} else {
|
||||
_videoStreamUrl = '';
|
||||
}
|
||||
return WebRTCLocalPlayer(
|
||||
// 这里的 URL 拼接根据你的后端规则
|
||||
// streamUrl: "webrtc://${TCPConsts.TCP_IP}/live/livestream/${currentDevice.deviceName}?token=${userState.user!.token}",
|
||||
streamUrl:
|
||||
"webrtc://${TCPConsts.TCP_IP}/live/livestream/111?token=${userState.user!.token}",
|
||||
streamUrl: _videoStreamUrl,
|
||||
showLeftPip: state.showLeftPip, // 从 Cubit 状态中读取
|
||||
showRightPip: state.showRightPip, // 从 Cubit 状态中读取
|
||||
);
|
||||
@@ -89,9 +88,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
BlocBuilder<RemoteControlCubit, RemoteControlState>(
|
||||
buildWhen: (p, c) => p.isEmergency != c.isEmergency,
|
||||
builder: (context, state) {
|
||||
return state.isEmergency
|
||||
? const Positioned.fill(child: EmergencyOverlay())
|
||||
: const SizedBox.shrink();
|
||||
return state.isEmergency ? const Positioned.fill(child: EmergencyOverlay()) : const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
|
||||
@@ -106,10 +103,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
final double centerAreaWidth = constraints.maxWidth * 0.5;
|
||||
|
||||
// 关键:使用 BlocBuilder 局部刷新摇杆,不要 watch 整个 Page
|
||||
return BlocBuilder<
|
||||
RemoteControlCubit,
|
||||
RemoteControlState
|
||||
>(
|
||||
return BlocBuilder<RemoteControlCubit, RemoteControlState>(
|
||||
// 只有 isLocked 改变时才重构摇杆区域,摇杆坐标改变由内部处理
|
||||
buildWhen: (p, c) => p.isLocked != c.isLocked,
|
||||
builder: (context, remoteState) {
|
||||
@@ -124,10 +118,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
width: sideAreaWidth,
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: LeftJoystickArea(
|
||||
isLocked: remoteState.isLocked,
|
||||
width: sideAreaWidth * 0.5 * 0.7,
|
||||
),
|
||||
child: LeftJoystickArea(isLocked: remoteState.isLocked, width: sideAreaWidth * 0.5 * 0.7),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -136,9 +127,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
width: centerAreaWidth,
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: CenterControlArea(
|
||||
totalWidth: centerAreaWidth,
|
||||
),
|
||||
child: CenterControlArea(totalWidth: centerAreaWidth),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -147,10 +136,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
width: sideAreaWidth,
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: RightJoystickArea(
|
||||
isLocked: remoteState.isLocked,
|
||||
width: sideAreaWidth * 0.5 * 0.7,
|
||||
),
|
||||
child: RightJoystickArea(isLocked: remoteState.isLocked, width: sideAreaWidth * 0.5 * 0.7),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -167,8 +153,7 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
|
||||
// 权限弹窗
|
||||
BlocBuilder<RemoteControlCubit, RemoteControlState>(
|
||||
buildWhen: (p, c) =>
|
||||
p.showPermissionRequestDialog != c.showPermissionRequestDialog,
|
||||
buildWhen: (p, c) => p.showPermissionRequestDialog != c.showPermissionRequestDialog,
|
||||
builder: (context, state) {
|
||||
if (state.showPermissionRequestDialog) {
|
||||
return _buildPermissionDialog(context, state);
|
||||
@@ -190,41 +175,24 @@ class _RemoteControlPageState extends State<RemoteControlPage> {
|
||||
children: [
|
||||
const Icon(Icons.signal_wifi_off, color: Colors.white, size: 60),
|
||||
const SizedBox(height: 20),
|
||||
const Text(
|
||||
"设备已断开连接",
|
||||
style: TextStyle(color: Colors.white, fontSize: 18),
|
||||
),
|
||||
const Text("设备已断开连接", style: TextStyle(color: Colors.white, fontSize: 18)),
|
||||
const SizedBox(height: 20),
|
||||
ElevatedButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: const Text("返回"),
|
||||
),
|
||||
ElevatedButton(onPressed: () => context.pop(), child: const Text("返回")),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPermissionDialog(
|
||||
BuildContext context,
|
||||
RemoteControlState state,
|
||||
) {
|
||||
Widget _buildPermissionDialog(BuildContext context, RemoteControlState state) {
|
||||
return Container(
|
||||
color: Colors.black54,
|
||||
child: AlertDialog(
|
||||
title: const Text("权限变更"),
|
||||
content: Text("${state.permissionPlatform}端正请求控制权,同意释放吗?"),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () =>
|
||||
context.read<RemoteControlCubit>().respondPermission(false),
|
||||
child: const Text("拒绝"),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () =>
|
||||
context.read<RemoteControlCubit>().respondPermission(true),
|
||||
child: const Text("同意"),
|
||||
),
|
||||
TextButton(onPressed: () => context.read<RemoteControlCubit>().respondPermission(false), child: const Text("拒绝")),
|
||||
TextButton(onPressed: () => context.read<RemoteControlCubit>().respondPermission(true), child: const Text("同意")),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -219,7 +219,7 @@ class _WebRTCLocalPlayerState extends State<WebRTCLocalPlayer> {
|
||||
),
|
||||
Positioned.fill(
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 45, sigmaY: 45),
|
||||
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
|
||||
child: Container(color: Colors.black.withOpacity(0.55)),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user