mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
Merge branch 'master' into modern-dialog
This commit is contained in:
@@ -19,7 +19,7 @@ import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart';
|
||||
import '../../common/widgets/dialog.dart';
|
||||
import '../../common/widgets/login.dart';
|
||||
|
||||
const double _kTabWidth = 235;
|
||||
const double _kTabWidth = 200;
|
||||
const double _kTabHeight = 42;
|
||||
const double _kCardFixedWidth = 540;
|
||||
const double _kCardLeftMargin = 15;
|
||||
@@ -538,6 +538,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
translate('Screen Share'),
|
||||
translate('Deny remote access'),
|
||||
],
|
||||
enabled: enabled,
|
||||
initialKey: initialKey,
|
||||
onChanged: (mode) async {
|
||||
String modeValue;
|
||||
@@ -667,6 +668,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
|
||||
return _Card(title: 'Password', children: [
|
||||
_ComboBox(
|
||||
enabled: !locked,
|
||||
keys: modeKeys,
|
||||
values: modeValues,
|
||||
initialKey: modeInitialKey,
|
||||
@@ -1722,7 +1724,6 @@ class _ComboBox extends StatelessWidget {
|
||||
required this.values,
|
||||
required this.initialKey,
|
||||
required this.onChanged,
|
||||
// ignore: unused_element
|
||||
this.enabled = true,
|
||||
}) : super(key: key);
|
||||
|
||||
@@ -1735,7 +1736,12 @@ class _ComboBox extends StatelessWidget {
|
||||
var ref = values[index].obs;
|
||||
current = keys[index];
|
||||
return Container(
|
||||
decoration: BoxDecoration(border: Border.all(color: MyTheme.border)),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: enabled
|
||||
? MyTheme.color(context).border2 ?? MyTheme.border
|
||||
: MyTheme.border,
|
||||
)),
|
||||
height: 30,
|
||||
child: Obx(() => DropdownButton<String>(
|
||||
isExpanded: true,
|
||||
@@ -1744,6 +1750,10 @@ class _ComboBox extends StatelessWidget {
|
||||
underline: Container(
|
||||
height: 25,
|
||||
),
|
||||
style: TextStyle(
|
||||
color: enabled
|
||||
? Theme.of(context).textTheme.titleMedium?.color
|
||||
: _disabledTextColor(context, enabled)),
|
||||
icon: const Icon(
|
||||
Icons.expand_more_sharp,
|
||||
size: 20,
|
||||
|
||||
@@ -75,7 +75,7 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
|
||||
isClose: false,
|
||||
),
|
||||
)));
|
||||
return Platform.isMacOS
|
||||
return Platform.isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
: Obx(
|
||||
() => DragToResizeArea(
|
||||
|
||||
@@ -98,7 +98,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
|
||||
labelGetter: DesktopTab.labelGetterAlias,
|
||||
)),
|
||||
);
|
||||
return Platform.isMacOS
|
||||
return Platform.isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
: SubWindowDragToResizeArea(
|
||||
child: tabWidget,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/common.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
@@ -13,7 +15,51 @@ class InstallPage extends StatefulWidget {
|
||||
State<InstallPage> createState() => _InstallPageState();
|
||||
}
|
||||
|
||||
class _InstallPageState extends State<InstallPage> with WindowListener {
|
||||
class _InstallPageState extends State<InstallPage> {
|
||||
final tabController = DesktopTabController(tabType: DesktopTabType.main);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Get.put<DesktopTabController>(tabController);
|
||||
const lable = "install";
|
||||
tabController.add(TabInfo(
|
||||
key: lable,
|
||||
label: lable,
|
||||
closable: false,
|
||||
page: _InstallPageBody(
|
||||
key: const ValueKey(lable),
|
||||
)));
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
Get.delete<DesktopTabController>();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DragToResizeArea(
|
||||
resizeEdgeSize: stateGlobal.resizeEdgeSize.value,
|
||||
child: Container(
|
||||
child: Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
body: DesktopTab(controller: tabController)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _InstallPageBody extends StatefulWidget {
|
||||
const _InstallPageBody({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<_InstallPageBody> createState() => _InstallPageBodyState();
|
||||
}
|
||||
|
||||
class _InstallPageBodyState extends State<_InstallPageBody>
|
||||
with WindowListener {
|
||||
late final TextEditingController controller;
|
||||
final RxBool startmenu = true.obs;
|
||||
final RxBool desktopicon = true.obs;
|
||||
@@ -46,15 +92,19 @@ class _InstallPageState extends State<InstallPage> with WindowListener {
|
||||
final double em = 13;
|
||||
final btnFontSize = 0.9 * em;
|
||||
final double button_radius = 6;
|
||||
final isDarkTheme = MyTheme.currentThemeMode() == ThemeMode.dark;
|
||||
final buttonStyle = OutlinedButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(button_radius)),
|
||||
));
|
||||
final inputBorder = OutlineInputBorder(
|
||||
borderRadius: BorderRadius.zero,
|
||||
borderSide: BorderSide(color: Colors.black12));
|
||||
borderSide:
|
||||
BorderSide(color: isDarkTheme ? Colors.white70 : Colors.black12));
|
||||
final textColor = isDarkTheme ? null : Colors.black87;
|
||||
final dividerColor = isDarkTheme ? Colors.white70 : Colors.black87;
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
backgroundColor: null,
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -91,8 +141,7 @@ class _InstallPageState extends State<InstallPage> with WindowListener {
|
||||
style: buttonStyle,
|
||||
child: Text(translate('Change Path'),
|
||||
style: TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: btnFontSize)))
|
||||
color: textColor, fontSize: btnFontSize)))
|
||||
.marginOnly(left: em))
|
||||
],
|
||||
).marginSymmetric(vertical: 2 * em),
|
||||
@@ -127,8 +176,7 @@ class _InstallPageState extends State<InstallPage> with WindowListener {
|
||||
)).marginOnly(top: 2 * em),
|
||||
Row(children: [Text(translate('agreement_tip'))])
|
||||
.marginOnly(top: em),
|
||||
Divider(color: Colors.black87)
|
||||
.marginSymmetric(vertical: 0.5 * em),
|
||||
Divider(color: dividerColor).marginSymmetric(vertical: 0.5 * em),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
@@ -143,8 +191,7 @@ class _InstallPageState extends State<InstallPage> with WindowListener {
|
||||
style: buttonStyle,
|
||||
child: Text(translate('Cancel'),
|
||||
style: TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: btnFontSize)))
|
||||
color: textColor, fontSize: btnFontSize)))
|
||||
.marginOnly(right: 2 * em)),
|
||||
Obx(() => ElevatedButton(
|
||||
onPressed: btnEnabled.value ? install : null,
|
||||
@@ -167,8 +214,7 @@ class _InstallPageState extends State<InstallPage> with WindowListener {
|
||||
style: buttonStyle,
|
||||
child: Text(translate('Run without install'),
|
||||
style: TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: btnFontSize)))
|
||||
color: textColor, fontSize: btnFontSize)))
|
||||
.marginOnly(left: 2 * em)),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -107,13 +107,15 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
|
||||
labelGetter: DesktopTab.labelGetterAlias,
|
||||
)),
|
||||
);
|
||||
return Platform.isMacOS
|
||||
return Platform.isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
: SubWindowDragToResizeArea(
|
||||
child: tabWidget,
|
||||
resizeEdgeSize: stateGlobal.resizeEdgeSize.value,
|
||||
windowId: stateGlobal.windowId,
|
||||
);
|
||||
: Obx(
|
||||
() => SubWindowDragToResizeArea(
|
||||
child: tabWidget,
|
||||
resizeEdgeSize: stateGlobal.resizeEdgeSize.value,
|
||||
windowId: stateGlobal.windowId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void onRemoveId(String id) {
|
||||
|
||||
@@ -205,11 +205,13 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
),
|
||||
),
|
||||
);
|
||||
return Platform.isMacOS
|
||||
return Platform.isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
: Obx(() => SubWindowDragToResizeArea(
|
||||
key: contentKey,
|
||||
child: tabWidget,
|
||||
// Specially configured for a better resize area and remote control.
|
||||
childPadding: kDragToResizeAreaPadding,
|
||||
resizeEdgeSize: stateGlobal.resizeEdgeSize.value,
|
||||
windowId: stateGlobal.windowId,
|
||||
));
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/common.dart';
|
||||
import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart';
|
||||
@@ -26,6 +28,9 @@ class DesktopRemoteScreen extends StatelessWidget {
|
||||
ChangeNotifierProvider.value(value: gFFI.canvasModel),
|
||||
],
|
||||
child: Scaffold(
|
||||
// Set transparent background for padding the resize area out of the flutter view.
|
||||
// This allows the wallpaper goes through our resize area. (Linux only now).
|
||||
backgroundColor: Platform.isLinux ? Colors.transparent : null,
|
||||
body: ConnectionTabPage(
|
||||
params: params,
|
||||
),
|
||||
|
||||
@@ -942,6 +942,7 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
disableClipboard(),
|
||||
lockAfterSessionEnd(),
|
||||
privacyMode(),
|
||||
swapKey(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -975,12 +976,13 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
|
||||
final canvasModel = widget.ffi.canvasModel;
|
||||
final width = (canvasModel.getDisplayWidth() * canvasModel.scale +
|
||||
canvasModel.windowBorderWidth * 2) *
|
||||
CanvasModel.leftToEdge +
|
||||
CanvasModel.rightToEdge) *
|
||||
scale +
|
||||
magicWidth;
|
||||
final height = (canvasModel.getDisplayHeight() * canvasModel.scale +
|
||||
canvasModel.tabBarHeight +
|
||||
canvasModel.windowBorderWidth * 2) *
|
||||
CanvasModel.topToEdge +
|
||||
CanvasModel.bottomToEdge) *
|
||||
scale +
|
||||
magicHeight;
|
||||
double left = wndRect.left + (wndRect.width - width) / 2;
|
||||
@@ -1049,10 +1051,10 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
final canvasModel = widget.ffi.canvasModel;
|
||||
final displayWidth = canvasModel.getDisplayWidth();
|
||||
final displayHeight = canvasModel.getDisplayHeight();
|
||||
final requiredWidth = displayWidth +
|
||||
(canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2);
|
||||
final requiredHeight = displayHeight +
|
||||
(canvasModel.tabBarHeight + canvasModel.windowBorderWidth * 2);
|
||||
final requiredWidth =
|
||||
CanvasModel.leftToEdge + displayWidth + CanvasModel.rightToEdge;
|
||||
final requiredHeight =
|
||||
CanvasModel.topToEdge + displayHeight + CanvasModel.bottomToEdge;
|
||||
return selfWidth > (requiredWidth * scale) &&
|
||||
selfHeight > (requiredHeight * scale);
|
||||
}
|
||||
@@ -1549,6 +1551,23 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
ffi: widget.ffi,
|
||||
child: Text(translate('Privacy mode')));
|
||||
}
|
||||
|
||||
swapKey() {
|
||||
final visible = perms['keyboard'] != false &&
|
||||
((Platform.isMacOS && pi.platform != kPeerPlatformMacOS) ||
|
||||
(!Platform.isMacOS && pi.platform == kPeerPlatformMacOS));
|
||||
if (!visible) return Offstage();
|
||||
final option = 'allow_swap_key';
|
||||
final value = bind.sessionGetToggleOptionSync(id: widget.id, arg: option);
|
||||
return _CheckboxMenuButton(
|
||||
value: value,
|
||||
onChanged: (value) {
|
||||
if (value == null) return;
|
||||
bind.sessionToggleOption(id: widget.id, value: option);
|
||||
},
|
||||
ffi: widget.ffi,
|
||||
child: Text(translate('Swap control-command key')));
|
||||
}
|
||||
}
|
||||
|
||||
class _KeyboardMenu extends StatelessWidget {
|
||||
@@ -1564,9 +1583,8 @@ class _KeyboardMenu extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Do not check permission here?
|
||||
// var ffiModel = Provider.of<FfiModel>(context);
|
||||
// if (ffiModel.permissions['keyboard'] == false) return Offstage();
|
||||
var ffiModel = Provider.of<FfiModel>(context);
|
||||
if (ffiModel.permissions['keyboard'] == false) return Offstage();
|
||||
if (stateGlobal.grabKeyboard) {
|
||||
if (bind.sessionIsKeyboardModeSupported(id: id, mode: _kKeyMapMode)) {
|
||||
bind.sessionSetKeyboardMode(id: id, value: _kKeyMapMode);
|
||||
|
||||
@@ -14,6 +14,7 @@ class DesktopScrollWrapper extends StatelessWidget {
|
||||
return ImprovedScrolling(
|
||||
scrollController: scrollController,
|
||||
enableCustomMouseWheelScrolling: true,
|
||||
// enableKeyboardScrolling: true, // strange behavior on mac
|
||||
customMouseWheelScrollConfig: CustomMouseWheelScrollConfig(
|
||||
scrollDuration: kDefaultScrollDuration,
|
||||
scrollCurve: Curves.linearToEaseOut,
|
||||
|
||||
@@ -53,6 +53,7 @@ enum DesktopTabType {
|
||||
remoteScreen,
|
||||
fileTransfer,
|
||||
portForward,
|
||||
install,
|
||||
}
|
||||
|
||||
class DesktopTabState {
|
||||
@@ -249,8 +250,9 @@ class DesktopTab extends StatelessWidget {
|
||||
this.unSelectedTabBackgroundColor,
|
||||
}) : super(key: key) {
|
||||
tabType = controller.tabType;
|
||||
isMainWindow =
|
||||
tabType == DesktopTabType.main || tabType == DesktopTabType.cm;
|
||||
isMainWindow = tabType == DesktopTabType.main ||
|
||||
tabType == DesktopTabType.cm ||
|
||||
tabType == DesktopTabType.install;
|
||||
}
|
||||
|
||||
static RxString labelGetterAlias(String peerId) {
|
||||
@@ -361,7 +363,8 @@ class DesktopTab extends StatelessWidget {
|
||||
/// - hide single item when only has one item (home) on [DesktopTabPage].
|
||||
bool isHideSingleItem() {
|
||||
return state.value.tabs.length == 1 &&
|
||||
controller.tabType == DesktopTabType.main;
|
||||
(controller.tabType == DesktopTabType.main ||
|
||||
controller.tabType == DesktopTabType.install);
|
||||
}
|
||||
|
||||
Widget _buildBar() {
|
||||
@@ -523,12 +526,18 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _setMaximize(bool maximize) {
|
||||
stateGlobal.setMaximize(maximize);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void onWindowMaximize() {
|
||||
// catch maximize from system
|
||||
if (!widget.isMaximized.value) {
|
||||
widget.isMaximized.value = true;
|
||||
}
|
||||
_setMaximize(true);
|
||||
super.onWindowMaximize();
|
||||
}
|
||||
|
||||
@@ -538,6 +547,7 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||
if (widget.isMaximized.value) {
|
||||
widget.isMaximized.value = false;
|
||||
}
|
||||
_setMaximize(false);
|
||||
super.onWindowUnmaximize();
|
||||
}
|
||||
|
||||
@@ -752,7 +762,8 @@ class _ListView extends StatelessWidget {
|
||||
/// - hide single item when only has one item (home) on [DesktopTabPage].
|
||||
bool isHideSingleItem() {
|
||||
return state.value.tabs.length == 1 &&
|
||||
controller.tabType == DesktopTabType.main;
|
||||
controller.tabType == DesktopTabType.main ||
|
||||
controller.tabType == DesktopTabType.install;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user