choose keyboard layout type, mid commit

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou
2022-12-27 16:45:13 +08:00
parent 5b3b7bd3c0
commit 48e684335e
11 changed files with 345 additions and 10 deletions

View File

@@ -23,6 +23,7 @@ import '../../models/model.dart';
import '../../models/platform_model.dart';
import '../../common/shared_state.dart';
import '../widgets/remote_menubar.dart';
import '../widgets/kb_layout_type_chooser.dart';
bool _isCustomCursorInited = false;
final SimpleWrapper<bool> _firstEnterImage = SimpleWrapper(false);
@@ -95,6 +96,10 @@ class _RemotePageState extends State<RemotePage>
_initStates(widget.id);
_ffi = FFI();
Get.put(_ffi, tag: widget.id);
_ffi.imageModel.addCallbackOnFirstImage((String peerId) {
showKBLayoutTypeChooserIfNeeded(
_ffi.ffiModel.pi.platform, _ffi.dialogManager);
});
_ffi.start(widget.id);
WidgetsBinding.instance.addPostFrameCallback((_) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);

View File

@@ -0,0 +1,227 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_hbb/models/platform_model.dart';
import '../../common.dart';
typedef KBChoosedCallback = bool Function(String);
const double _kImageMarginVertical = 6.0;
const double _kImageMarginHorizental = 10.0;
const double _kImageBoarderWidth = 4.0;
const double _kImagePaddingWidth = 4.0;
const Color _kImageBorderColor = Color.fromARGB(125, 202, 247, 2);
const double _kBorderRadius = 6.0;
const String _kKBLayoutTypeISO = 'ISO';
const String _kKBLayoutTypeNotISO = 'Not ISO';
const _kKBLayoutImageMap = {
_kKBLayoutTypeISO: 'KB_LAYOUT_ISO',
_kKBLayoutTypeNotISO: 'KB_LAYOUT_NOT_ISO',
};
class _KBImage extends StatelessWidget {
final String kbLayoutType;
final double imageWidth;
final RxString choosedType;
const _KBImage({
Key? key,
required this.kbLayoutType,
required this.imageWidth,
required this.choosedType,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Obx(() {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(_kBorderRadius),
border: Border.all(
color: choosedType.value == kbLayoutType
? _kImageBorderColor
: Colors.transparent,
width: _kImageBoarderWidth,
),
),
margin: EdgeInsets.symmetric(
horizontal: _kImageMarginHorizental,
vertical: _kImageMarginVertical,
),
padding: EdgeInsets.all(_kImagePaddingWidth),
child: SvgPicture.asset(
'assets/${_kKBLayoutImageMap[kbLayoutType] ?? ""}.svg',
width: imageWidth -
_kImageMarginHorizental * 2 -
_kImagePaddingWidth * 2 -
_kImageBoarderWidth * 2,
),
);
});
}
}
class _KBChooser extends StatelessWidget {
final String kbLayoutType;
final double imageWidth;
final RxString choosedType;
final KBChoosedCallback cb;
const _KBChooser({
Key? key,
required this.kbLayoutType,
required this.imageWidth,
required this.choosedType,
required this.cb,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
TextButton(
onPressed: () {
choosedType.value = kbLayoutType;
},
child: _KBImage(
kbLayoutType: kbLayoutType,
imageWidth: imageWidth,
choosedType: choosedType,
),
style: TextButton.styleFrom(padding: EdgeInsets.zero),
),
TextButton(
child: Row(
children: [
Obx(() => Radio(
splashRadius: 0,
value: kbLayoutType,
groupValue: choosedType.value,
onChanged: (String? newValue) {
if (newValue != null) {
if (cb(newValue)) {
choosedType.value = newValue;
}
}
},
)),
Text(kbLayoutType),
],
),
onPressed: () {
if (cb(kbLayoutType)) {
choosedType.value = kbLayoutType;
}
},
),
],
);
}
}
class KBLayoutTypeChooser extends StatelessWidget {
final RxString choosedType;
final double width;
final double height;
final double dividerWidth;
final KBChoosedCallback cb;
KBLayoutTypeChooser({
Key? key,
required this.choosedType,
required this.width,
required this.height,
required this.dividerWidth,
required this.cb,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final imageWidth = width / 2 - dividerWidth;
return Container(
color: Colors.white,
child: SizedBox(
width: width,
height: height,
child: Center(
child: Row(
children: [
_KBChooser(
kbLayoutType: _kKBLayoutTypeISO,
imageWidth: imageWidth,
choosedType: choosedType,
cb: cb,
),
VerticalDivider(
width: dividerWidth * 2,
),
_KBChooser(
kbLayoutType: _kKBLayoutTypeNotISO,
imageWidth: imageWidth,
choosedType: choosedType,
cb: cb,
),
],
),
),
),
);
}
}
RxString KBLayoutType = ''.obs;
String getLocalPlatformForKBLayoutType(String peerPlatform) {
String localPlatform = '';
if (peerPlatform != 'Mac OS') {
return localPlatform;
}
if (Platform.isWindows) {
localPlatform = 'Windows';
} else if (Platform.isLinux) {
localPlatform = 'Linux';
}
// to-do: web desktop support ?
return localPlatform;
}
showKBLayoutTypeChooserIfNeeded(
String peerPlatform,
OverlayDialogManager dialogManager,
) async {
final localPlatform = getLocalPlatformForKBLayoutType(peerPlatform);
if (localPlatform == '') {
return;
}
KBLayoutType.value = bind.getLocalKbLayoutType();
if (KBLayoutType.value == _kKBLayoutTypeISO ||
KBLayoutType.value == _kKBLayoutTypeNotISO) {
return;
}
showKBLayoutTypeChooser(localPlatform, dialogManager);
}
showKBLayoutTypeChooser(
String localPlatform,
OverlayDialogManager dialogManager,
) {
dialogManager.show((setState, close) {
return CustomAlertDialog(
title:
Text('${translate('Select local keyboard type')} ($localPlatform)'),
content: KBLayoutTypeChooser(
choosedType: KBLayoutType,
width: 360,
height: 200,
dividerWidth: 4.0,
cb: (String v) {
bind.setLocalKbLayoutType(kbLayoutType: v);
KBLayoutType.value = bind.getLocalKbLayoutType();
return v == KBLayoutType.value;
}),
actions: [msgBoxButton(translate('Close'), close)],
onCancel: close,
);
});
}

View File

@@ -9,7 +9,7 @@ import 'package:url_launcher/url_launcher.dart';
import '../../common.dart';
final kMidButtonPadding = const EdgeInsets.fromLTRB(15, 0, 15, 0);
final _kMidButtonPadding = const EdgeInsets.fromLTRB(15, 0, 15, 0);
class _IconOP extends StatelessWidget {
final String icon;
@@ -53,7 +53,7 @@ class ButtonOP extends StatelessWidget {
Expanded(
child: Container(
height: height,
padding: kMidButtonPadding,
padding: _kMidButtonPadding,
child: Obx(() => ElevatedButton(
style: ElevatedButton.styleFrom(
primary: curOP.value.isEmpty || curOP.value == op
@@ -315,7 +315,7 @@ class LoginWidgetUserPass extends StatelessWidget {
height: 8.0,
),
Container(
padding: kMidButtonPadding,
padding: _kMidButtonPadding,
child: Row(
children: [
ConstrainedBox(
@@ -343,7 +343,7 @@ class LoginWidgetUserPass extends StatelessWidget {
height: 8.0,
),
Container(
padding: kMidButtonPadding,
padding: _kMidButtonPadding,
child: Row(
children: [
ConstrainedBox(
@@ -377,7 +377,7 @@ class LoginWidgetUserPass extends StatelessWidget {
Expanded(
child: Container(
height: 38,
padding: kMidButtonPadding,
padding: _kMidButtonPadding,
child: Obx(() => ElevatedButton(
style: curOP.value.isEmpty || curOP.value == 'rustdesk'
? null

View File

@@ -22,6 +22,7 @@ import '../../models/platform_model.dart';
import '../../common/shared_state.dart';
import './popup_menu.dart';
import './material_mod_popup_menu.dart' as mod_menu;
import './kb_layout_type_chooser.dart';
class MenubarState {
final kStoreKey = 'remoteMenubarState';
@@ -1187,7 +1188,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
}
List<MenuEntryBase<String>> _getKeyboardMenu() {
final keyboardMenu = [
final List<MenuEntryBase<String>> keyboardMenu = [
MenuEntryRadios<String>(
text: translate('Ratio'),
optionsGetter: () => [
@@ -1203,7 +1204,55 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
},
)
];
final localPlatform =
getLocalPlatformForKBLayoutType(widget.ffi.ffiModel.pi.platform);
if (localPlatform != '') {
keyboardMenu.add(MenuEntryDivider());
keyboardMenu.add(
MenuEntryButton<String>(
childBuilder: (TextStyle? style) => Container(
alignment: AlignmentDirectional.center,
height: _MenubarTheme.height,
child: Row(
children: [
Obx(() => RichText(
text: TextSpan(
text: '${translate('Local keyboard type')}: ',
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: KBLayoutType.value,
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
)),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Transform.scale(
scale: 0.8,
child: IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.settings),
onPressed: () {
if (Navigator.canPop(context)) {
Navigator.pop(context);
}
showKBLayoutTypeChooser(
localPlatform, widget.ffi.dialogManager);
},
),
),
))
],
)),
proc: () {},
padding: EdgeInsets.zero,
dismissOnClicked: false,
),
);
}
return keyboardMenu;
}

View File

@@ -381,12 +381,22 @@ class ImageModel with ChangeNotifier {
WeakReference<FFI> parent;
final List<Function(String)> _callbacksOnFirstImage = [];
ImageModel(this.parent);
addCallbackOnFirstImage(Function(String) cb) =>
_callbacksOnFirstImage.add(cb);
onRgba(Uint8List rgba) {
if (_waitForImage[id]!) {
_waitForImage[id] = false;
parent.target?.dialogManager.dismissAll();
if (isDesktop) {
for (final cb in _callbacksOnFirstImage) {
cb(id);
}
}
}
final pid = parent.target?.id;
ui.decodeImageFromPixels(