Merge branch 'master' into modern-dialog

This commit is contained in:
NicKoehler
2023-03-01 18:00:56 +01:00
parent 55831948f8
commit ab4ef977f4
88 changed files with 2293 additions and 658 deletions

View File

@@ -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,

View File

@@ -75,7 +75,7 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
isClose: false,
),
)));
return Platform.isMacOS
return Platform.isMacOS || kUseCompatibleUiMode
? tabWidget
: Obx(
() => DragToResizeArea(

View File

@@ -98,7 +98,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
labelGetter: DesktopTab.labelGetterAlias,
)),
);
return Platform.isMacOS
return Platform.isMacOS || kUseCompatibleUiMode
? tabWidget
: SubWindowDragToResizeArea(
child: tabWidget,

View File

@@ -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)),
),
],

View File

@@ -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) {

View File

@@ -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,
));

View File

@@ -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,
),

View File

@@ -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);

View File

@@ -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,

View File

@@ -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