feat: main window custom bar & drag
Signed-off-by: Kingtous <kingtous@qq.com>
This commit is contained in:
parent
58b471e26b
commit
b8f7e85c0b
@ -2,9 +2,9 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
// import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
// import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
import '../../common.dart';
|
import '../../common.dart';
|
||||||
import '../../mobile/pages/home_page.dart';
|
import '../../mobile/pages/home_page.dart';
|
||||||
@ -143,8 +143,15 @@ class ConnectionManager extends StatelessWidget {
|
|||||||
// serverModel.clients[0] = Client(
|
// serverModel.clients[0] = Client(
|
||||||
// false, false, "Readmi-M21sdfsdf", "123123123", true, false, false);
|
// false, false, "Readmi-M21sdfsdf", "123123123", true, false, false);
|
||||||
return serverModel.clients.isEmpty
|
return serverModel.clients.isEmpty
|
||||||
? Center(
|
? Column(
|
||||||
|
children: [
|
||||||
|
buildTitleBar(Offstage()),
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
child: Text(translate("Waiting")),
|
child: Text(translate("Waiting")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
: DefaultTabController(
|
: DefaultTabController(
|
||||||
length: serverModel.clients.length,
|
length: serverModel.clients.length,
|
||||||
@ -153,11 +160,11 @@ class ConnectionManager extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: kTextTabBarHeight,
|
height: kTextTabBarHeight,
|
||||||
child: TabBar(
|
child: buildTitleBar(TabBar(
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
tabs: serverModel.clients.entries
|
tabs: serverModel.clients.entries
|
||||||
.map((entry) => buildTab(entry))
|
.map((entry) => buildTab(entry))
|
||||||
.toList(growable: false)),
|
.toList(growable: false))),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
@ -170,6 +177,25 @@ class ConnectionManager extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildTitleBar(Widget middle) {
|
||||||
|
return GestureDetector(
|
||||||
|
onPanDown: (d) {
|
||||||
|
windowManager.startDragging();
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
_AppIcon(),
|
||||||
|
Expanded(child: middle),
|
||||||
|
const SizedBox(
|
||||||
|
width: 4.0,
|
||||||
|
),
|
||||||
|
_CloseButton()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget buildConnectionCard(MapEntry<int, Client> entry) {
|
Widget buildConnectionCard(MapEntry<int, Client> entry) {
|
||||||
final client = entry.value;
|
final client = entry.value;
|
||||||
return Column(
|
return Column(
|
||||||
@ -204,6 +230,40 @@ class ConnectionManager extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _AppIcon extends StatelessWidget {
|
||||||
|
const _AppIcon({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/logo.ico',
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CloseButton extends StatelessWidget {
|
||||||
|
const _CloseButton({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Ink(
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
windowManager.close();
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.close,
|
||||||
|
size: 30,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _CmHeader extends StatefulWidget {
|
class _CmHeader extends StatefulWidget {
|
||||||
final Client client;
|
final Client client;
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
|
import 'package:flutter_hbb/main.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';
|
||||||
|
|
||||||
const double _kTabBarHeight = kDesktopRemoteTabBarHeight;
|
const double _kTabBarHeight = kDesktopRemoteTabBarHeight;
|
||||||
const double _kIconSize = 18;
|
const double _kIconSize = 18;
|
||||||
@ -76,7 +79,13 @@ class DesktopTabBar extends StatelessWidget {
|
|||||||
Text("RustDesk").paddingOnly(left: 5),
|
Text("RustDesk").paddingOnly(left: 5),
|
||||||
]).paddingSymmetric(horizontal: 12, vertical: 5),
|
]).paddingSymmetric(horizontal: 12, vertical: 5),
|
||||||
),
|
),
|
||||||
Flexible(
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onPanStart: (_) {
|
||||||
|
if (mainTab) {
|
||||||
|
windowManager.startDragging();
|
||||||
|
}
|
||||||
|
},
|
||||||
child: Obx(() => TabBar(
|
child: Obx(() => TabBar(
|
||||||
key: tabBarKey,
|
key: tabBarKey,
|
||||||
indicatorColor: _theme.indicatorColor,
|
indicatorColor: _theme.indicatorColor,
|
||||||
@ -113,6 +122,7 @@ class DesktopTabBar extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}).toList())),
|
}).toList())),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: mainTab,
|
offstage: mainTab,
|
||||||
child: _AddButton(
|
child: _AddButton(
|
||||||
@ -134,6 +144,10 @@ class DesktopTabBar extends StatelessWidget {
|
|||||||
onTap: () => onAddSetting?.call(),
|
onTap: () => onAddSetting?.call(),
|
||||||
).paddingOnly(right: 10),
|
).paddingOnly(right: 10),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
WindowActionPanel(
|
||||||
|
mainTab: mainTab,
|
||||||
|
color: _theme.unSelectedIconColor,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -169,6 +183,79 @@ class DesktopTabBar extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WindowActionPanel extends StatelessWidget {
|
||||||
|
final bool mainTab;
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
const WindowActionPanel(
|
||||||
|
{Key? key, required this.mainTab, required this.color})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Tooltip(
|
||||||
|
message: translate("Minimize"),
|
||||||
|
child: InkWell(
|
||||||
|
child: Icon(
|
||||||
|
Icons.minimize,
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (mainTab) {
|
||||||
|
windowManager.minimize();
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
// WindowController.fromWindowId(windowId!).close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).paddingOnly(right: 10),
|
||||||
|
),
|
||||||
|
Tooltip(
|
||||||
|
message: translate("Maximize"),
|
||||||
|
child: InkWell(
|
||||||
|
child: Icon(
|
||||||
|
Icons.rectangle_outlined,
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (mainTab) {
|
||||||
|
windowManager.isMaximized().then((maximized) {
|
||||||
|
if (maximized) {
|
||||||
|
windowManager.unmaximize();
|
||||||
|
} else {
|
||||||
|
windowManager.maximize();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
// WindowController.fromWindowId(windowId!).();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).paddingOnly(right: 10),
|
||||||
|
),
|
||||||
|
Tooltip(
|
||||||
|
message: translate("Close"),
|
||||||
|
child: InkWell(
|
||||||
|
child: Icon(
|
||||||
|
Icons.close,
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (mainTab) {
|
||||||
|
windowManager.close();
|
||||||
|
} else {
|
||||||
|
WindowController.fromWindowId(windowId!).close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).paddingOnly(right: 10),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _Tab extends StatelessWidget {
|
class _Tab extends StatelessWidget {
|
||||||
late final int index;
|
late final int index;
|
||||||
late final String label;
|
late final String label;
|
||||||
|
@ -77,7 +77,14 @@ Future<void> initEnv(String appType) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void runMainApp(bool startService) async {
|
void runMainApp(bool startService) async {
|
||||||
await initEnv(kAppTypeMain);
|
WindowOptions windowOptions = getHiddenTitleBarWindowOptions(Size(1280, 720));
|
||||||
|
await Future.wait([
|
||||||
|
initEnv(kAppTypeMain),
|
||||||
|
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||||
|
await windowManager.show();
|
||||||
|
await windowManager.focus();
|
||||||
|
})
|
||||||
|
]);
|
||||||
if (startService) {
|
if (startService) {
|
||||||
// await windowManager.ensureInitialized();
|
// await windowManager.ensureInitialized();
|
||||||
// disable tray
|
// disable tray
|
||||||
@ -118,13 +125,7 @@ void runFileTransferScreen(Map<String, dynamic> argument) async {
|
|||||||
|
|
||||||
void runConnectionManagerScreen() async {
|
void runConnectionManagerScreen() async {
|
||||||
// initialize window
|
// initialize window
|
||||||
WindowOptions windowOptions = WindowOptions(
|
WindowOptions windowOptions = getHiddenTitleBarWindowOptions(Size(300, 400));
|
||||||
size: Size(300, 400),
|
|
||||||
center: true,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
skipTaskbar: false,
|
|
||||||
titleBarStyle: TitleBarStyle.normal,
|
|
||||||
);
|
|
||||||
await Future.wait([
|
await Future.wait([
|
||||||
initEnv(kAppTypeConnectionManager),
|
initEnv(kAppTypeConnectionManager),
|
||||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||||
@ -134,7 +135,20 @@ void runConnectionManagerScreen() async {
|
|||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
;
|
;
|
||||||
runApp(GetMaterialApp(theme: getCurrentTheme(), home: DesktopServerPage()));
|
runApp(GetMaterialApp(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
theme: getCurrentTheme(),
|
||||||
|
home: DesktopServerPage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowOptions getHiddenTitleBarWindowOptions(Size size) {
|
||||||
|
return WindowOptions(
|
||||||
|
size: size,
|
||||||
|
center: true,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
skipTaskbar: false,
|
||||||
|
titleBarStyle: TitleBarStyle.hidden,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class App extends StatelessWidget {
|
class App extends StatelessWidget {
|
||||||
|
@ -67,7 +67,10 @@ dependencies:
|
|||||||
url: https://github.com/Kingtous/rustdesk_desktop_multi_window
|
url: https://github.com/Kingtous/rustdesk_desktop_multi_window
|
||||||
ref: 2b1176d53f195cc55e8d37151bb3d9f6bd52fad3
|
ref: 2b1176d53f195cc55e8d37151bb3d9f6bd52fad3
|
||||||
freezed_annotation: ^2.0.3
|
freezed_annotation: ^2.0.3
|
||||||
tray_manager: 0.1.7
|
tray_manager:
|
||||||
|
git:
|
||||||
|
url: https://github.com/Kingtous/rustdesk_tray_manager
|
||||||
|
ref: 3aa37c86e47ea748e7b5507cbe59f2c54ebdb23a
|
||||||
get: ^4.6.5
|
get: ^4.6.5
|
||||||
visibility_detector: ^0.3.3
|
visibility_detector: ^0.3.3
|
||||||
contextmenu: ^3.0.0
|
contextmenu: ^3.0.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user