mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
commit
c9c0d13dc8
@ -2,3 +2,5 @@ const double kDesktopRemoteTabBarHeight = 48.0;
|
|||||||
const String kAppTypeMain = "main";
|
const String kAppTypeMain = "main";
|
||||||
const String kAppTypeDesktopRemote = "remote";
|
const String kAppTypeDesktopRemote = "remote";
|
||||||
const String kAppTypeDesktopFileTransfer = "file transfer";
|
const String kAppTypeDesktopFileTransfer = "file transfer";
|
||||||
|
const String kTabLabelHomePage = "Home";
|
||||||
|
const String kTabLabelSettingPage = "Settings";
|
||||||
|
|||||||
@ -57,7 +57,6 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(color: isDarkTheme() ? null : MyTheme.grayBg),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -9,7 +8,6 @@ import 'package:flutter_hbb/desktop/pages/remote_page.dart';
|
|||||||
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
|
||||||
|
|
||||||
import '../../models/model.dart';
|
import '../../models/model.dart';
|
||||||
|
|
||||||
@ -26,24 +24,23 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
|
|||||||
with TickerProviderStateMixin {
|
with TickerProviderStateMixin {
|
||||||
// refactor List<int> when using multi-tab
|
// refactor List<int> when using multi-tab
|
||||||
// this singleton is only for test
|
// this singleton is only for test
|
||||||
var connectionIds = RxList<String>.empty(growable: true);
|
RxList<TabInfo> tabs = RxList<TabInfo>.empty(growable: true);
|
||||||
var initialIndex = 0;
|
|
||||||
late Rx<TabController> tabController;
|
late Rx<TabController> tabController;
|
||||||
static final Rx<int> _selected = 0.obs;
|
static final Rx<int> _selected = 0.obs;
|
||||||
|
IconData icon = Icons.desktop_windows_sharp;
|
||||||
|
|
||||||
var connectionMap = RxList<Widget>.empty(growable: true);
|
var connectionMap = RxList<Widget>.empty(growable: true);
|
||||||
|
|
||||||
_ConnectionTabPageState(Map<String, dynamic> params) {
|
_ConnectionTabPageState(Map<String, dynamic> params) {
|
||||||
if (params['id'] != null) {
|
if (params['id'] != null) {
|
||||||
connectionIds.add(params['id']);
|
tabs.add(TabInfo(label: params['id'], icon: icon));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
tabController =
|
tabController = TabController(length: tabs.length, vsync: this).obs;
|
||||||
TabController(length: connectionIds.length, vsync: this).obs;
|
|
||||||
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
|
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
|
||||||
print(
|
print(
|
||||||
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
|
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
|
||||||
@ -52,23 +49,13 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
|
|||||||
final args = jsonDecode(call.arguments);
|
final args = jsonDecode(call.arguments);
|
||||||
final id = args['id'];
|
final id = args['id'];
|
||||||
window_on_top(windowId());
|
window_on_top(windowId());
|
||||||
final indexOf = connectionIds.indexOf(id);
|
DesktopTabBar.onAdd(this, tabController, tabs, _selected,
|
||||||
if (indexOf >= 0) {
|
TabInfo(label: id, icon: icon));
|
||||||
initialIndex = indexOf;
|
|
||||||
tabController.value.animateTo(initialIndex, duration: Duration.zero);
|
|
||||||
} else {
|
|
||||||
connectionIds.add(id);
|
|
||||||
initialIndex = connectionIds.length - 1;
|
|
||||||
tabController.value = TabController(
|
|
||||||
length: connectionIds.length,
|
|
||||||
vsync: this,
|
|
||||||
initialIndex: initialIndex);
|
|
||||||
}
|
|
||||||
_selected.value = initialIndex;
|
|
||||||
} else if (call.method == "onDestroy") {
|
} else if (call.method == "onDestroy") {
|
||||||
print("executing onDestroy hook, closing ${connectionIds}");
|
print(
|
||||||
connectionIds.forEach((id) {
|
"executing onDestroy hook, closing ${tabs.map((tab) => tab.label).toList()}");
|
||||||
final tag = '${id}';
|
tabs.forEach((tab) {
|
||||||
|
final tag = '${tab.label}';
|
||||||
ffi(tag).close().then((_) {
|
ffi(tag).close().then((_) {
|
||||||
Get.delete<FFI>(tag: tag);
|
Get.delete<FFI>(tag: tag);
|
||||||
});
|
});
|
||||||
@ -83,20 +70,21 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
Obx(() => DesktopTabBar(
|
DesktopTabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: connectionIds.toList(),
|
tabs: tabs,
|
||||||
onTabClose: onRemoveId,
|
onTabClose: onRemoveId,
|
||||||
tabIcon: Icons.desktop_windows_sharp,
|
selected: _selected,
|
||||||
selected: _selected,
|
dark: isDarkTheme(),
|
||||||
)),
|
mainTab: false,
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Obx(() => TabBarView(
|
child: Obx(() => TabBarView(
|
||||||
controller: tabController.value,
|
controller: tabController.value,
|
||||||
children: connectionIds
|
children: tabs
|
||||||
.map((e) => RemotePage(
|
.map((tab) => RemotePage(
|
||||||
key: ValueKey(e),
|
key: ValueKey(tab.label),
|
||||||
id: e,
|
id: tab.label,
|
||||||
tabBarHeight: kDesktopRemoteTabBarHeight,
|
tabBarHeight: kDesktopRemoteTabBarHeight,
|
||||||
)) //RemotePage(key: ValueKey(e), id: e))
|
)) //RemotePage(key: ValueKey(e), id: e))
|
||||||
.toList()))),
|
.toList()))),
|
||||||
@ -106,15 +94,8 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onRemoveId(String id) {
|
void onRemoveId(String id) {
|
||||||
final indexOf = connectionIds.indexOf(id);
|
DesktopTabBar.onClose(this, tabController, tabs, id);
|
||||||
if (indexOf == -1) {
|
if (tabs.length == 0) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
connectionIds.removeAt(indexOf);
|
|
||||||
initialIndex = max(0, initialIndex - 1);
|
|
||||||
tabController.value = TabController(
|
|
||||||
length: connectionIds.length, vsync: this, initialIndex: initialIndex);
|
|
||||||
if (connectionIds.length == 0) {
|
|
||||||
WindowController.fromWindowId(windowId()).close();
|
WindowController.fromWindowId(windowId()).close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import 'package:flutter/material.dart' hide MenuItem;
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
import 'package:flutter_hbb/desktop/pages/connection_page.dart';
|
import 'package:flutter_hbb/desktop/pages/connection_page.dart';
|
||||||
import 'package:flutter_hbb/desktop/widgets/titlebar_widget.dart';
|
|
||||||
import 'package:flutter_hbb/models/platform_model.dart';
|
import 'package:flutter_hbb/models/platform_model.dart';
|
||||||
import 'package:flutter_hbb/models/server_model.dart';
|
import 'package:flutter_hbb/models/server_model.dart';
|
||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
@ -46,38 +45,17 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Row(
|
||||||
body: Column(
|
children: [
|
||||||
children: [
|
Flexible(
|
||||||
DesktopTitleBar(
|
child: buildServerInfo(context),
|
||||||
child: Center(
|
flex: 1,
|
||||||
child: Text(
|
),
|
||||||
"RustDesk",
|
Flexible(
|
||||||
style: TextStyle(
|
child: buildServerBoard(context),
|
||||||
color: Colors.white,
|
flex: 4,
|
||||||
fontSize: 20,
|
),
|
||||||
fontWeight: FontWeight.bold),
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: buildServerInfo(context),
|
|
||||||
flex: 1,
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: buildServerBoard(context),
|
|
||||||
flex: 4,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
flutter/lib/desktop/pages/desktop_setting_page.dart
Normal file
15
flutter/lib/desktop/pages/desktop_setting_page.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
|
class DesktopSettingPage extends StatefulWidget {
|
||||||
|
DesktopSettingPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DesktopSettingPage> createState() => _DesktopSettingPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopSettingPageState extends State<DesktopSettingPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Text("Settings");
|
||||||
|
}
|
||||||
|
}
|
||||||
73
flutter/lib/desktop/pages/desktop_tab_page.dart
Normal file
73
flutter/lib/desktop/pages/desktop_tab_page.dart
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hbb/common.dart';
|
||||||
|
import 'package:flutter_hbb/consts.dart';
|
||||||
|
import 'package:flutter_hbb/desktop/pages/desktop_home_page.dart';
|
||||||
|
import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart';
|
||||||
|
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class DesktopTabPage extends StatefulWidget {
|
||||||
|
const DesktopTabPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DesktopTabPage> createState() => _DesktopTabPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopTabPageState extends State<DesktopTabPage>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
|
late Rx<TabController> tabController;
|
||||||
|
late RxList<TabInfo> tabs;
|
||||||
|
static final Rx<int> _selected = 0.obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
tabs = RxList.from([
|
||||||
|
TabInfo(label: kTabLabelHomePage, icon: Icons.home_sharp, closable: false)
|
||||||
|
], growable: true);
|
||||||
|
tabController =
|
||||||
|
TabController(length: tabs.length, vsync: this, initialIndex: 0).obs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
DesktopTabBar(
|
||||||
|
controller: tabController,
|
||||||
|
tabs: tabs,
|
||||||
|
onTabClose: onTabClose,
|
||||||
|
selected: _selected,
|
||||||
|
dark: isDarkTheme(),
|
||||||
|
mainTab: true,
|
||||||
|
onAddSetting: onAddSetting,
|
||||||
|
),
|
||||||
|
Obx((() => Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
controller: tabController.value,
|
||||||
|
children: tabs.map((tab) {
|
||||||
|
switch (tab.label) {
|
||||||
|
case kTabLabelHomePage:
|
||||||
|
return DesktopHomePage(key: ValueKey(tab.label));
|
||||||
|
case kTabLabelSettingPage:
|
||||||
|
return DesktopSettingPage(key: ValueKey(tab.label));
|
||||||
|
default:
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
}).toList()),
|
||||||
|
))),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onTabClose(String label) {
|
||||||
|
DesktopTabBar.onClose(this, tabController, tabs, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onAddSetting() {
|
||||||
|
DesktopTabBar.onAdd(this, tabController, tabs, _selected,
|
||||||
|
TabInfo(label: kTabLabelSettingPage, icon: Icons.settings));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -73,7 +73,6 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: isDarkTheme() ? MyTheme.dark : MyTheme.grayBg,
|
|
||||||
body: Row(
|
body: Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(flex: 3, child: body(isLocal: true)),
|
Flexible(flex: 3, child: body(isLocal: true)),
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -9,7 +8,6 @@ import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
|||||||
import 'package:flutter_hbb/models/model.dart';
|
import 'package:flutter_hbb/models/model.dart';
|
||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
|
||||||
|
|
||||||
/// File Transfer for multi tabs
|
/// File Transfer for multi tabs
|
||||||
class FileManagerTabPage extends StatefulWidget {
|
class FileManagerTabPage extends StatefulWidget {
|
||||||
@ -25,22 +23,21 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
|
|||||||
with TickerProviderStateMixin {
|
with TickerProviderStateMixin {
|
||||||
// refactor List<int> when using multi-tab
|
// refactor List<int> when using multi-tab
|
||||||
// this singleton is only for test
|
// this singleton is only for test
|
||||||
var connectionIds = List<String>.empty(growable: true).obs;
|
RxList<TabInfo> tabs = List<TabInfo>.empty(growable: true).obs;
|
||||||
var initialIndex = 0;
|
|
||||||
late Rx<TabController> tabController;
|
late Rx<TabController> tabController;
|
||||||
static final Rx<int> _selected = 0.obs;
|
static final Rx<int> _selected = 0.obs;
|
||||||
|
IconData icon = Icons.file_copy_sharp;
|
||||||
|
|
||||||
_FileManagerTabPageState(Map<String, dynamic> params) {
|
_FileManagerTabPageState(Map<String, dynamic> params) {
|
||||||
if (params['id'] != null) {
|
if (params['id'] != null) {
|
||||||
connectionIds.add(params['id']);
|
tabs.add(TabInfo(label: params['id'], icon: icon));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
tabController =
|
tabController = TabController(length: tabs.length, vsync: this).obs;
|
||||||
TabController(length: connectionIds.length, vsync: this).obs;
|
|
||||||
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
|
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
|
||||||
print(
|
print(
|
||||||
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
|
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
|
||||||
@ -49,23 +46,13 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
|
|||||||
final args = jsonDecode(call.arguments);
|
final args = jsonDecode(call.arguments);
|
||||||
final id = args['id'];
|
final id = args['id'];
|
||||||
window_on_top(windowId());
|
window_on_top(windowId());
|
||||||
final indexOf = connectionIds.indexOf(id);
|
DesktopTabBar.onAdd(this, tabController, tabs, _selected,
|
||||||
if (indexOf >= 0) {
|
TabInfo(label: id, icon: icon));
|
||||||
initialIndex = indexOf;
|
|
||||||
tabController.value.animateTo(initialIndex, duration: Duration.zero);
|
|
||||||
} else {
|
|
||||||
connectionIds.add(id);
|
|
||||||
initialIndex = connectionIds.length - 1;
|
|
||||||
tabController.value = TabController(
|
|
||||||
length: connectionIds.length,
|
|
||||||
initialIndex: initialIndex,
|
|
||||||
vsync: this);
|
|
||||||
}
|
|
||||||
_selected.value = initialIndex;
|
|
||||||
} else if (call.method == "onDestroy") {
|
} else if (call.method == "onDestroy") {
|
||||||
print("executing onDestroy hook, closing ${connectionIds}");
|
print(
|
||||||
connectionIds.forEach((id) {
|
"executing onDestroy hook, closing ${tabs.map((tab) => tab.label).toList()}");
|
||||||
final tag = 'ft_${id}';
|
tabs.forEach((tab) {
|
||||||
|
final tag = 'ft_${tab.label}';
|
||||||
ffi(tag).close().then((_) {
|
ffi(tag).close().then((_) {
|
||||||
Get.delete<FFI>(tag: tag);
|
Get.delete<FFI>(tag: tag);
|
||||||
});
|
});
|
||||||
@ -80,23 +67,22 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
Obx(
|
DesktopTabBar(
|
||||||
() => DesktopTabBar(
|
controller: tabController,
|
||||||
controller: tabController,
|
tabs: tabs,
|
||||||
tabs: connectionIds.toList(),
|
onTabClose: onRemoveId,
|
||||||
onTabClose: onRemoveId,
|
selected: _selected,
|
||||||
tabIcon: Icons.file_copy_sharp,
|
dark: isDarkTheme(),
|
||||||
selected: _selected,
|
mainTab: false,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => TabBarView(
|
() => TabBarView(
|
||||||
controller: tabController.value,
|
controller: tabController.value,
|
||||||
children: connectionIds
|
children: tabs
|
||||||
.map((e) => FileManagerPage(
|
.map((tab) => FileManagerPage(
|
||||||
key: ValueKey(e),
|
key: ValueKey(tab.label),
|
||||||
id: e)) //RemotePage(key: ValueKey(e), id: e))
|
id: tab.label)) //RemotePage(key: ValueKey(e), id: e))
|
||||||
.toList()),
|
.toList()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -106,15 +92,8 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onRemoveId(String id) {
|
void onRemoveId(String id) {
|
||||||
final indexOf = connectionIds.indexOf(id);
|
DesktopTabBar.onClose(this, tabController, tabs, id);
|
||||||
if (indexOf == -1) {
|
if (tabs.length == 0) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
connectionIds.removeAt(indexOf);
|
|
||||||
initialIndex = max(0, initialIndex - 1);
|
|
||||||
tabController.value = TabController(
|
|
||||||
length: connectionIds.length, initialIndex: initialIndex, vsync: this);
|
|
||||||
if (connectionIds.length == 0) {
|
|
||||||
WindowController.fromWindowId(windowId()).close();
|
WindowController.fromWindowId(windowId()).close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -263,7 +263,6 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
OverlayEntry(builder: (context) {
|
OverlayEntry(builder: (context) {
|
||||||
_ffi.chatModel.setOverlayState(Overlay.of(context));
|
_ffi.chatModel.setOverlayState(Overlay.of(context));
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.black,
|
|
||||||
child: getRawPointerAndKeyBody(getBodyForDesktop(keyboard)));
|
child: getRawPointerAndKeyBody(getBodyForDesktop(keyboard)));
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
@ -500,25 +499,20 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
|
|
||||||
Widget getBodyForDesktop(bool keyboard) {
|
Widget getBodyForDesktop(bool keyboard) {
|
||||||
var paints = <Widget>[
|
var paints = <Widget>[
|
||||||
MouseRegion(
|
MouseRegion(onEnter: (evt) {
|
||||||
onEnter: (evt) {
|
bind.hostStopSystemKeyPropagate(stopped: false);
|
||||||
bind.hostStopSystemKeyPropagate(stopped: false);
|
}, onExit: (evt) {
|
||||||
},
|
bind.hostStopSystemKeyPropagate(stopped: true);
|
||||||
onExit: (evt) {
|
}, child: Container(
|
||||||
bind.hostStopSystemKeyPropagate(stopped: true);
|
child: LayoutBuilder(builder: (context, constraints) {
|
||||||
},
|
Future.delayed(Duration.zero, () {
|
||||||
child: Container(
|
Provider.of<CanvasModel>(context, listen: false).updateViewStyle();
|
||||||
color: MyTheme.canvasColor,
|
});
|
||||||
child: LayoutBuilder(builder: (context, constraints) {
|
return ImagePaint(
|
||||||
Future.delayed(Duration.zero, () {
|
id: widget.id,
|
||||||
Provider.of<CanvasModel>(context, listen: false)
|
);
|
||||||
.updateViewStyle();
|
}),
|
||||||
});
|
))
|
||||||
return ImagePaint(
|
|
||||||
id: widget.id,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
))
|
|
||||||
];
|
];
|
||||||
final cursor = bind.getSessionToggleOptionSync(
|
final cursor = bind.getSessionToggleOptionSync(
|
||||||
id: widget.id, arg: 'show-remote-cursor');
|
id: widget.id, arg: 'show-remote-cursor');
|
||||||
|
|||||||
@ -20,27 +20,11 @@ class DesktopFileTransferScreen extends StatelessWidget {
|
|||||||
ChangeNotifierProvider.value(value: gFFI.cursorModel),
|
ChangeNotifierProvider.value(value: gFFI.cursorModel),
|
||||||
ChangeNotifierProvider.value(value: gFFI.canvasModel),
|
ChangeNotifierProvider.value(value: gFFI.canvasModel),
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: Scaffold(
|
||||||
navigatorKey: globalKey,
|
body: FileManagerTabPage(
|
||||||
debugShowCheckedModeBanner: false,
|
params: params,
|
||||||
title: 'RustDesk - File Transfer',
|
),
|
||||||
theme: ThemeData(
|
),
|
||||||
primarySwatch: Colors.blue,
|
|
||||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
|
||||||
),
|
|
||||||
home: FileManagerTabPage(
|
|
||||||
params: params,
|
|
||||||
),
|
|
||||||
navigatorObservers: [
|
|
||||||
// FirebaseAnalyticsObserver(analytics: analytics),
|
|
||||||
FlutterSmartDialog.observer
|
|
||||||
],
|
|
||||||
builder: FlutterSmartDialog.init(
|
|
||||||
builder: isAndroid
|
|
||||||
? (_, child) => AccessibilityListener(
|
|
||||||
child: child,
|
|
||||||
)
|
|
||||||
: null)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,33 +13,16 @@ class DesktopRemoteScreen extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
ChangeNotifierProvider.value(value: gFFI.ffiModel),
|
ChangeNotifierProvider.value(value: gFFI.ffiModel),
|
||||||
ChangeNotifierProvider.value(value: gFFI.imageModel),
|
ChangeNotifierProvider.value(value: gFFI.imageModel),
|
||||||
ChangeNotifierProvider.value(value: gFFI.cursorModel),
|
ChangeNotifierProvider.value(value: gFFI.cursorModel),
|
||||||
ChangeNotifierProvider.value(value: gFFI.canvasModel),
|
ChangeNotifierProvider.value(value: gFFI.canvasModel),
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: Scaffold(
|
||||||
navigatorKey: globalKey,
|
body: ConnectionTabPage(
|
||||||
debugShowCheckedModeBanner: false,
|
|
||||||
title: 'RustDesk - Remote Desktop',
|
|
||||||
theme: ThemeData(
|
|
||||||
primarySwatch: Colors.blue,
|
|
||||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
|
||||||
),
|
|
||||||
home: ConnectionTabPage(
|
|
||||||
params: params,
|
params: params,
|
||||||
),
|
),
|
||||||
navigatorObservers: [
|
));
|
||||||
// FirebaseAnalyticsObserver(analytics: analytics),
|
|
||||||
FlutterSmartDialog.observer
|
|
||||||
],
|
|
||||||
builder: FlutterSmartDialog.init(
|
|
||||||
builder: isAndroid
|
|
||||||
? (_, child) => AccessibilityListener(
|
|
||||||
child: child,
|
|
||||||
)
|
|
||||||
: null)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,275 +6,319 @@ import 'package:flutter_hbb/consts.dart';
|
|||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
const Color _bgColor = Color.fromARGB(255, 231, 234, 237);
|
|
||||||
const Color _tabUnselectedColor = Color.fromARGB(255, 240, 240, 240);
|
|
||||||
const Color _tabHoverColor = Color.fromARGB(255, 245, 245, 245);
|
|
||||||
const Color _tabSelectedColor = Color.fromARGB(255, 255, 255, 255);
|
|
||||||
const Color _tabIconColor = MyTheme.accent50;
|
|
||||||
const Color _tabindicatorColor = _tabIconColor;
|
|
||||||
const Color _textColor = Color.fromARGB(255, 108, 111, 145);
|
|
||||||
const Color _iconColor = Color.fromARGB(255, 102, 106, 109);
|
|
||||||
const Color _iconHoverColor = Colors.black12;
|
|
||||||
const Color _iconPressedColor = Colors.black26;
|
|
||||||
const Color _dividerColor = Colors.black12;
|
|
||||||
|
|
||||||
const double _kTabBarHeight = kDesktopRemoteTabBarHeight;
|
const double _kTabBarHeight = kDesktopRemoteTabBarHeight;
|
||||||
const double _kTabFixedWidth = 150;
|
const double _kTabFixedWidth = 150;
|
||||||
const double _kIconSize = 18;
|
const double _kIconSize = 18;
|
||||||
const double _kDividerIndent = 10;
|
const double _kDividerIndent = 10;
|
||||||
const double _kAddIconSize = _kTabBarHeight - 15;
|
const double _kAddIconSize = _kTabBarHeight - 15;
|
||||||
|
|
||||||
|
class TabInfo {
|
||||||
|
late final String label;
|
||||||
|
late final IconData icon;
|
||||||
|
late final bool closable;
|
||||||
|
|
||||||
|
TabInfo({required this.label, required this.icon, this.closable = true});
|
||||||
|
}
|
||||||
|
|
||||||
class DesktopTabBar extends StatelessWidget {
|
class DesktopTabBar extends StatelessWidget {
|
||||||
late final Rx<TabController> controller;
|
late final Rx<TabController> controller;
|
||||||
late final List<String> tabs;
|
late final RxList<TabInfo> tabs;
|
||||||
late final Function(String) onTabClose;
|
late final Function(String) onTabClose;
|
||||||
late final IconData tabIcon;
|
|
||||||
late final Rx<int> selected;
|
late final Rx<int> selected;
|
||||||
|
late final bool dark;
|
||||||
|
late final _Theme _theme;
|
||||||
|
late final bool mainTab;
|
||||||
|
late final Function()? onAddSetting;
|
||||||
|
|
||||||
DesktopTabBar(
|
DesktopTabBar({
|
||||||
{Key? key,
|
Key? key,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
required this.tabs,
|
required this.tabs,
|
||||||
required this.onTabClose,
|
required this.onTabClose,
|
||||||
required this.tabIcon,
|
required this.selected,
|
||||||
required this.selected})
|
required this.dark,
|
||||||
: super(key: key);
|
required this.mainTab,
|
||||||
|
this.onAddSetting,
|
||||||
|
}) : _theme = dark ? _Theme.dark() : _Theme.light(),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
color: _bgColor,
|
|
||||||
height: _kTabBarHeight,
|
height: _kTabBarHeight,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Expanded(
|
||||||
child: Obx(() => TabBar(
|
child: Row(
|
||||||
indicatorColor: _tabindicatorColor,
|
children: [
|
||||||
indicatorSize: TabBarIndicatorSize.tab,
|
Offstage(
|
||||||
indicatorWeight: 4,
|
offstage: !mainTab,
|
||||||
labelPadding:
|
child: Row(children: [
|
||||||
const EdgeInsets.symmetric(vertical: 0, horizontal: 0),
|
Image.asset('assets/logo.ico'),
|
||||||
indicatorPadding: EdgeInsets.zero,
|
Text("RustDesk"),
|
||||||
isScrollable: true,
|
]).paddingSymmetric(horizontal: 12, vertical: 5),
|
||||||
physics: BouncingScrollPhysics(),
|
),
|
||||||
controller: controller.value,
|
Flexible(
|
||||||
tabs: tabs
|
child: Obx(() => TabBar(
|
||||||
.asMap()
|
indicator: BoxDecoration(),
|
||||||
.entries
|
indicatorColor: Colors.transparent,
|
||||||
.map((e) => _Tab(
|
labelPadding: const EdgeInsets.symmetric(
|
||||||
index: e.key,
|
vertical: 0, horizontal: 0),
|
||||||
text: e.value,
|
isScrollable: true,
|
||||||
icon: tabIcon,
|
indicatorWeight: 0.1,
|
||||||
|
physics: BouncingScrollPhysics(),
|
||||||
|
controller: controller.value,
|
||||||
|
tabs: tabs.asMap().entries.map((e) {
|
||||||
|
int index = e.key;
|
||||||
|
String label = e.value.label;
|
||||||
|
|
||||||
|
return _Tab(
|
||||||
|
index: index,
|
||||||
|
label: label,
|
||||||
|
icon: e.value.icon,
|
||||||
|
closable: e.value.closable,
|
||||||
selected: selected.value,
|
selected: selected.value,
|
||||||
onClose: () {
|
onClose: () {
|
||||||
onTabClose(e.value);
|
onTabClose(label);
|
||||||
// TODO
|
if (index <= selected.value) {
|
||||||
if (e.key <= selected.value) {
|
|
||||||
selected.value = max(0, selected.value - 1);
|
selected.value = max(0, selected.value - 1);
|
||||||
}
|
}
|
||||||
controller.value.animateTo(selected.value);
|
controller.value.animateTo(selected.value,
|
||||||
|
duration: Duration.zero);
|
||||||
},
|
},
|
||||||
onSelected: () {
|
onSelected: () {
|
||||||
selected.value = e.key;
|
selected.value = index;
|
||||||
controller.value.animateTo(e.key);
|
controller.value
|
||||||
|
.animateTo(index, duration: Duration.zero);
|
||||||
},
|
},
|
||||||
))
|
theme: _theme,
|
||||||
.toList())),
|
);
|
||||||
),
|
}).toList())),
|
||||||
Padding(
|
),
|
||||||
padding: EdgeInsets.only(left: 10),
|
Offstage(
|
||||||
child: _AddButton(),
|
offstage: mainTab,
|
||||||
|
child: _AddButton(
|
||||||
|
theme: _theme,
|
||||||
|
).paddingOnly(left: 10),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
Offstage(
|
||||||
|
offstage: onAddSetting == null,
|
||||||
|
child: Tooltip(
|
||||||
|
message: translate("Settings"),
|
||||||
|
child: InkWell(
|
||||||
|
child: Icon(
|
||||||
|
Icons.menu,
|
||||||
|
color: _theme.unSelectedIconColor,
|
||||||
|
),
|
||||||
|
onTap: () => onAddSetting?.call(),
|
||||||
|
).paddingOnly(right: 10),
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static onClose(
|
||||||
|
TickerProvider vsync,
|
||||||
|
Rx<TabController> controller,
|
||||||
|
RxList<TabInfo> tabs,
|
||||||
|
String label,
|
||||||
|
) {
|
||||||
|
tabs.removeWhere((tab) => tab.label == label);
|
||||||
|
controller.value = TabController(
|
||||||
|
length: tabs.length,
|
||||||
|
vsync: vsync,
|
||||||
|
initialIndex: max(0, tabs.length - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static onAdd(TickerProvider vsync, Rx<TabController> controller,
|
||||||
|
RxList<TabInfo> tabs, Rx<int> selected, TabInfo tab) {
|
||||||
|
int index = tabs.indexWhere((e) => e.label == tab.label);
|
||||||
|
if (index >= 0) {
|
||||||
|
controller.value.animateTo(index, duration: Duration.zero);
|
||||||
|
selected.value = index;
|
||||||
|
} else {
|
||||||
|
tabs.add(tab);
|
||||||
|
controller.value = TabController(
|
||||||
|
length: tabs.length, vsync: vsync, initialIndex: tabs.length - 1);
|
||||||
|
controller.value.animateTo(tabs.length - 1, duration: Duration.zero);
|
||||||
|
selected.value = tabs.length - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Tab extends StatelessWidget {
|
class _Tab extends StatelessWidget {
|
||||||
late final int index;
|
late final int index;
|
||||||
late final String text;
|
late final String label;
|
||||||
late final IconData icon;
|
late final IconData icon;
|
||||||
|
late final bool closable;
|
||||||
late final int selected;
|
late final int selected;
|
||||||
late final Function() onClose;
|
late final Function() onClose;
|
||||||
late final Function() onSelected;
|
late final Function() onSelected;
|
||||||
final RxBool _hover = false.obs;
|
final RxBool _hover = false.obs;
|
||||||
|
late final _Theme theme;
|
||||||
|
|
||||||
_Tab({
|
_Tab(
|
||||||
Key? key,
|
{Key? key,
|
||||||
required this.index,
|
required this.index,
|
||||||
required this.text,
|
required this.label,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
required this.selected,
|
required this.closable,
|
||||||
required this.onClose,
|
required this.selected,
|
||||||
required this.onSelected,
|
required this.onClose,
|
||||||
}) : super(key: key);
|
required this.onSelected,
|
||||||
|
required this.theme})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool is_selected = index == selected;
|
bool is_selected = index == selected;
|
||||||
bool show_divider = index != selected - 1 && index != selected;
|
bool show_divider = index != selected - 1 && index != selected;
|
||||||
return Obx(
|
return Ink(
|
||||||
(() => _Hoverable(
|
width: _kTabFixedWidth,
|
||||||
onHover: (hover) => _hover.value = hover,
|
child: InkWell(
|
||||||
onTapUp: () => onSelected(),
|
onHover: (hover) => _hover.value = hover,
|
||||||
child: Container(
|
onTap: () => onSelected(),
|
||||||
width: _kTabFixedWidth,
|
child: Row(
|
||||||
decoration: BoxDecoration(
|
children: [
|
||||||
color: is_selected
|
Expanded(
|
||||||
? _tabSelectedColor
|
child: Tab(
|
||||||
: _hover.value
|
key: this.key,
|
||||||
? _tabHoverColor
|
child: Row(
|
||||||
: _tabUnselectedColor,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
),
|
children: [
|
||||||
child: Row(
|
Icon(
|
||||||
children: [
|
icon,
|
||||||
Expanded(
|
size: _kIconSize,
|
||||||
child: Tab(
|
color: is_selected
|
||||||
key: this.key,
|
? theme.selectedtabIconColor
|
||||||
child: Row(
|
: theme.unSelectedtabIconColor,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
).paddingSymmetric(horizontal: 5),
|
||||||
children: [
|
Expanded(
|
||||||
Padding(
|
child: Text(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 5),
|
translate(label),
|
||||||
child: Icon(
|
style: TextStyle(
|
||||||
icon,
|
color: is_selected
|
||||||
size: _kIconSize,
|
? theme.selectedTextColor
|
||||||
color: _tabIconColor,
|
: theme.unSelectedTextColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Obx((() => _CloseButton(
|
||||||
child: Text(
|
visiable: _hover.value && closable,
|
||||||
text,
|
tabSelected: is_selected,
|
||||||
style: const TextStyle(color: _textColor),
|
onClose: () => onClose(),
|
||||||
),
|
theme: theme,
|
||||||
),
|
))),
|
||||||
_CloseButton(
|
])),
|
||||||
tabHovered: _hover.value,
|
|
||||||
onClose: () => onClose(),
|
|
||||||
),
|
|
||||||
])),
|
|
||||||
),
|
|
||||||
show_divider
|
|
||||||
? VerticalDivider(
|
|
||||||
width: 1,
|
|
||||||
indent: _kDividerIndent,
|
|
||||||
endIndent: _kDividerIndent,
|
|
||||||
color: _dividerColor,
|
|
||||||
thickness: 1,
|
|
||||||
)
|
|
||||||
: Container(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)),
|
Offstage(
|
||||||
|
offstage: !show_divider,
|
||||||
|
child: VerticalDivider(
|
||||||
|
width: 1,
|
||||||
|
indent: _kDividerIndent,
|
||||||
|
endIndent: _kDividerIndent,
|
||||||
|
color: theme.dividerColor,
|
||||||
|
thickness: 1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AddButton extends StatelessWidget {
|
class _AddButton extends StatelessWidget {
|
||||||
final RxBool _hover = false.obs;
|
late final _Theme theme;
|
||||||
final RxBool _pressed = false.obs;
|
|
||||||
|
|
||||||
_AddButton({
|
_AddButton({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
required this.theme,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return _Hoverable(
|
return Ink(
|
||||||
onHover: (hover) => _hover.value = hover,
|
height: _kTabBarHeight,
|
||||||
onPressed: (pressed) => _pressed.value = pressed,
|
child: InkWell(
|
||||||
onTapUp: () =>
|
customBorder: const CircleBorder(),
|
||||||
rustDeskWinManager.call(WindowType.Main, "main_window_on_top", ""),
|
onTap: () =>
|
||||||
child: Obx((() => Container(
|
rustDeskWinManager.call(WindowType.Main, "main_window_on_top", ""),
|
||||||
height: _kTabBarHeight,
|
child: Icon(
|
||||||
decoration: ShapeDecoration(
|
Icons.add_sharp,
|
||||||
shape: const CircleBorder(),
|
size: _kAddIconSize,
|
||||||
color: _pressed.value
|
color: theme.unSelectedIconColor,
|
||||||
? _iconPressedColor
|
),
|
||||||
: _hover.value
|
),
|
||||||
? _iconHoverColor
|
|
||||||
: Colors.transparent,
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.add_sharp,
|
|
||||||
color: _iconColor,
|
|
||||||
size: _kAddIconSize,
|
|
||||||
),
|
|
||||||
))),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CloseButton extends StatelessWidget {
|
class _CloseButton extends StatelessWidget {
|
||||||
final bool tabHovered;
|
final bool visiable;
|
||||||
|
final bool tabSelected;
|
||||||
final Function onClose;
|
final Function onClose;
|
||||||
final RxBool _hover = false.obs;
|
late final _Theme theme;
|
||||||
final RxBool _pressed = false.obs;
|
|
||||||
|
|
||||||
_CloseButton({
|
_CloseButton({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.tabHovered,
|
required this.visiable,
|
||||||
|
required this.tabSelected,
|
||||||
required this.onClose,
|
required this.onClose,
|
||||||
|
required this.theme,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return SizedBox(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 5),
|
width: _kIconSize,
|
||||||
child: SizedBox(
|
child: Offstage(
|
||||||
width: _kIconSize,
|
offstage: !visiable,
|
||||||
child: tabHovered
|
child: InkWell(
|
||||||
? Obx((() => _Hoverable(
|
customBorder: RoundedRectangleBorder(),
|
||||||
onHover: (hover) => _hover.value = hover,
|
onTap: () => onClose(),
|
||||||
onPressed: (pressed) => _pressed.value = pressed,
|
child: Icon(
|
||||||
onTapUp: () => onClose(),
|
Icons.close,
|
||||||
child: Container(
|
size: _kIconSize,
|
||||||
color: _pressed.value
|
color: tabSelected
|
||||||
? _iconPressedColor
|
? theme.selectedIconColor
|
||||||
: _hover.value
|
: theme.unSelectedIconColor,
|
||||||
? _iconHoverColor
|
),
|
||||||
: Colors.transparent,
|
),
|
||||||
child: const Icon(
|
)).paddingSymmetric(horizontal: 5);
|
||||||
Icons.close,
|
|
||||||
size: _kIconSize,
|
|
||||||
color: _iconColor,
|
|
||||||
)),
|
|
||||||
)))
|
|
||||||
: Container(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Hoverable extends StatelessWidget {
|
class _Theme {
|
||||||
final Widget child;
|
late Color unSelectedtabIconColor;
|
||||||
final Function(bool hover) onHover;
|
late Color selectedtabIconColor;
|
||||||
final Function(bool pressed)? onPressed;
|
late Color selectedTextColor;
|
||||||
final Function()? onTapUp;
|
late Color unSelectedTextColor;
|
||||||
|
late Color selectedIconColor;
|
||||||
|
late Color unSelectedIconColor;
|
||||||
|
late Color dividerColor;
|
||||||
|
|
||||||
const _Hoverable(
|
_Theme.light() {
|
||||||
{Key? key,
|
unSelectedtabIconColor = Color.fromARGB(255, 162, 203, 241);
|
||||||
required this.child,
|
selectedtabIconColor = MyTheme.accent;
|
||||||
required this.onHover,
|
selectedTextColor = Color.fromARGB(255, 26, 26, 26);
|
||||||
this.onPressed,
|
unSelectedTextColor = Color.fromARGB(255, 96, 96, 96);
|
||||||
this.onTapUp})
|
selectedIconColor = Color.fromARGB(255, 26, 26, 26);
|
||||||
: super(key: key);
|
unSelectedIconColor = Color.fromARGB(255, 96, 96, 96);
|
||||||
|
dividerColor = Color.fromARGB(255, 238, 238, 238);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
_Theme.dark() {
|
||||||
Widget build(BuildContext context) {
|
unSelectedtabIconColor = Color.fromARGB(255, 30, 65, 98);
|
||||||
return MouseRegion(
|
selectedtabIconColor = MyTheme.accent;
|
||||||
onEnter: (_) => onHover(true),
|
selectedTextColor = Color.fromARGB(255, 255, 255, 255);
|
||||||
onExit: (_) => onHover(false),
|
unSelectedTextColor = Color.fromARGB(255, 207, 207, 207);
|
||||||
child: onPressed == null && onTapUp == null
|
selectedIconColor = Color.fromARGB(255, 215, 215, 215);
|
||||||
? child
|
unSelectedIconColor = Color.fromARGB(255, 255, 255, 255);
|
||||||
: GestureDetector(
|
dividerColor = Color.fromARGB(255, 64, 64, 64);
|
||||||
onTapDown: (details) => onPressed?.call(true),
|
|
||||||
onTapUp: (details) {
|
|
||||||
onPressed?.call(false);
|
|
||||||
onTapUp?.call();
|
|
||||||
},
|
|
||||||
child: child,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/desktop/pages/desktop_home_page.dart';
|
import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
|
||||||
import 'package:flutter_hbb/desktop/screen/desktop_file_transfer_screen.dart';
|
import 'package:flutter_hbb/desktop/screen/desktop_file_transfer_screen.dart';
|
||||||
import 'package:flutter_hbb/desktop/screen/desktop_remote_screen.dart';
|
import 'package:flutter_hbb/desktop/screen/desktop_remote_screen.dart';
|
||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
@ -86,18 +86,44 @@ void runMainApp(bool startService) async {
|
|||||||
void runRemoteScreen(Map<String, dynamic> argument) async {
|
void runRemoteScreen(Map<String, dynamic> argument) async {
|
||||||
await initEnv(kAppTypeDesktopRemote);
|
await initEnv(kAppTypeDesktopRemote);
|
||||||
runApp(GetMaterialApp(
|
runApp(GetMaterialApp(
|
||||||
|
navigatorKey: globalKey,
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
title: 'RustDesk - Remote Desktop',
|
||||||
theme: getCurrentTheme(),
|
theme: getCurrentTheme(),
|
||||||
home: DesktopRemoteScreen(
|
home: DesktopRemoteScreen(
|
||||||
params: argument,
|
params: argument,
|
||||||
),
|
),
|
||||||
|
navigatorObservers: [
|
||||||
|
// FirebaseAnalyticsObserver(analytics: analytics),
|
||||||
|
FlutterSmartDialog.observer
|
||||||
|
],
|
||||||
|
builder: FlutterSmartDialog.init(
|
||||||
|
builder: isAndroid
|
||||||
|
? (_, child) => AccessibilityListener(
|
||||||
|
child: child,
|
||||||
|
)
|
||||||
|
: null),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void runFileTransferScreen(Map<String, dynamic> argument) async {
|
void runFileTransferScreen(Map<String, dynamic> argument) async {
|
||||||
await initEnv(kAppTypeDesktopFileTransfer);
|
await initEnv(kAppTypeDesktopFileTransfer);
|
||||||
runApp(GetMaterialApp(
|
runApp(GetMaterialApp(
|
||||||
|
navigatorKey: globalKey,
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
title: 'RustDesk - File Transfer',
|
||||||
theme: getCurrentTheme(),
|
theme: getCurrentTheme(),
|
||||||
home: DesktopFileTransferScreen(params: argument)));
|
home: DesktopFileTransferScreen(params: argument),
|
||||||
|
navigatorObservers: [
|
||||||
|
// FirebaseAnalyticsObserver(analytics: analytics),
|
||||||
|
FlutterSmartDialog.observer
|
||||||
|
],
|
||||||
|
builder: FlutterSmartDialog.init(
|
||||||
|
builder: isAndroid
|
||||||
|
? (_, child) => AccessibilityListener(
|
||||||
|
child: child,
|
||||||
|
)
|
||||||
|
: null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
class App extends StatelessWidget {
|
class App extends StatelessWidget {
|
||||||
@ -121,7 +147,7 @@ class App extends StatelessWidget {
|
|||||||
title: 'RustDesk',
|
title: 'RustDesk',
|
||||||
theme: getCurrentTheme(),
|
theme: getCurrentTheme(),
|
||||||
home: isDesktop
|
home: isDesktop
|
||||||
? DesktopHomePage()
|
? DesktopTabPage()
|
||||||
: !isAndroid
|
: !isAndroid
|
||||||
? WebHomePage()
|
? WebHomePage()
|
||||||
: HomePage(),
|
: HomePage(),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user