rustdesk/flutter/lib/desktop/pages/remote_tab_page.dart
2022-11-01 10:10:40 +08:00

208 lines
7.2 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/common/shared_state.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/desktop/pages/remote_page.dart';
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
import 'package:flutter_hbb/utils/multi_window_manager.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import '../../models/platform_model.dart';
class ConnectionTabPage extends StatefulWidget {
final Map<String, dynamic> params;
const ConnectionTabPage({Key? key, required this.params}) : super(key: key);
@override
State<ConnectionTabPage> createState() => _ConnectionTabPageState(params);
}
class _ConnectionTabPageState extends State<ConnectionTabPage> {
final tabController = Get.put(DesktopTabController(
tabType: DesktopTabType.remoteScreen,
onSelected: (_, id) => bind.setCurSessionId(id: id)));
static const IconData selectedIcon = Icons.desktop_windows_sharp;
static const IconData unselectedIcon = Icons.desktop_windows_outlined;
var connectionMap = RxList<Widget>.empty(growable: true);
_ConnectionTabPageState(Map<String, dynamic> params) {
RemoteCountState.init();
final RxBool fullscreen = Get.find(tag: 'fullscreen');
final peerId = params['id'];
if (peerId != null) {
ConnectionTypeState.init(peerId);
tabController.add(TabInfo(
key: peerId,
label: peerId,
selectedIcon: selectedIcon,
unselectedIcon: unselectedIcon,
onTabCloseButton: () => tabController.closeBy(peerId),
page: Obx(() => RemotePage(
key: ValueKey(peerId),
id: peerId,
windowId: windowId(),
tabBarHeight:
fullscreen.isTrue ? 0 : kDesktopRemoteTabBarHeight,
windowBorderWidth: fullscreen.isTrue ? 0 : kWindowBorderWidth,
))));
_update_remote_count();
}
}
@override
void initState() {
super.initState();
tabController.onRemoved = (_, id) => onRemoveId(id);
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
print(
"call ${call.method} with args ${call.arguments} from window $fromWindowId");
final RxBool fullscreen = Get.find(tag: 'fullscreen');
// for simplify, just replace connectionId
if (call.method == "new_remote_desktop") {
final args = jsonDecode(call.arguments);
final id = args['id'];
ConnectionTypeState.init(id);
window_on_top(windowId());
ConnectionTypeState.init(id);
tabController.add(TabInfo(
key: id,
label: id,
selectedIcon: selectedIcon,
unselectedIcon: unselectedIcon,
onTabCloseButton: () => tabController.closeBy(id),
page: ObxValue<RxBool>(
(fullscreen) => RemotePage(
id: id,
windowId: windowId(),
tabBarHeight:
fullscreen.isTrue ? 0 : kDesktopRemoteTabBarHeight,
windowBorderWidth: fullscreen.isTrue ? 0 : kWindowBorderWidth,
),
fullscreen,
key: ValueKey(id),
)));
} else if (call.method == "onDestroy") {
tabController.clear();
} else if (call.method == kWindowActionRebuild) {
reloadCurrentWindow();
}
_update_remote_count();
});
Future.delayed(Duration.zero, () {
restoreWindowPosition(WindowType.RemoteDesktop, windowId: windowId());
});
}
@override
Widget build(BuildContext context) {
final RxBool fullscreen = Get.find(tag: 'fullscreen');
final tabWidget = Container(
decoration: BoxDecoration(
border: Border.all(
color: MyTheme.color(context).border!,
width: kWindowBorderWidth)),
child: Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: Obx(() => DesktopTab(
controller: tabController,
showTabBar: fullscreen.isFalse,
onWindowCloseButton: handleWindowCloseButton,
tail: const AddButton().paddingOnly(left: 10),
pageViewBuilder: (pageView) {
WindowController.fromWindowId(windowId())
.setFullscreen(fullscreen.isTrue);
return pageView;
},
tabBuilder: (key, icon, label, themeConf) => Obx(() {
final connectionType = ConnectionTypeState.find(key);
if (!connectionType.isValid()) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
icon,
label,
],
);
} else {
final msgDirect = translate(
connectionType.direct.value == ConnectionType.strDirect
? 'Direct Connection'
: 'Relay Connection');
final msgSecure = translate(
connectionType.secure.value == ConnectionType.strSecure
? 'Secure Connection'
: 'Insecure Connection');
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
icon,
Tooltip(
message: '$msgDirect\n$msgSecure',
child: SvgPicture.asset(
'assets/${connectionType.secure.value}${connectionType.direct.value}.svg',
width: themeConf.iconSize,
height: themeConf.iconSize,
).paddingOnly(right: 5),
),
label,
],
);
}
}),
))),
);
return Platform.isMacOS
? tabWidget
: Obx(() => SubWindowDragToResizeArea(
resizeEdgeSize:
fullscreen.value ? kFullScreenEdgeSize : kWindowEdgeSize,
windowId: windowId(),
child: tabWidget));
}
void onRemoveId(String id) {
if (tabController.state.value.tabs.isEmpty) {
WindowController.fromWindowId(windowId()).hide();
}
ConnectionTypeState.delete(id);
_update_remote_count();
}
int windowId() {
return widget.params["windowId"];
}
Future<bool> handleWindowCloseButton() async {
final connLength = tabController.length;
if (connLength <= 1) {
tabController.clear();
return true;
} else {
final opt = "enable-confirm-closing-tabs";
final bool res;
if (!option2bool(opt, await bind.mainGetOption(key: opt))) {
res = true;
} else {
res = await closeConfirmDialog();
}
if (res) {
tabController.clear();
}
return res;
}
}
_update_remote_count() =>
RemoteCountState.find().value = tabController.length;
}