flutter_desktop: remote menubar remove submenu
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
f42c6ffeaf
commit
4d914e9a01
@ -97,15 +97,18 @@ class MenuConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class MenuEntryBase<T> {
|
abstract class MenuEntryBase<T> {
|
||||||
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf);
|
List<mod_menu.PopupMenuEntry<T>> build(BuildContext context, MenuConfig conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MenuEntryDivider<T> extends MenuEntryBase<T> {
|
class MenuEntryDivider<T> extends MenuEntryBase<T> {
|
||||||
@override
|
@override
|
||||||
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) {
|
List<mod_menu.PopupMenuEntry<T>> build(
|
||||||
return mod_menu.PopupMenuDivider(
|
BuildContext context, MenuConfig conf) {
|
||||||
height: conf.dividerHeight,
|
return [
|
||||||
);
|
mod_menu.PopupMenuDivider(
|
||||||
|
height: conf.dividerHeight,
|
||||||
|
)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,6 +116,85 @@ typedef RadioOptionsGetter = List<Tuple2<String, String>> Function();
|
|||||||
typedef RadioCurOptionGetter = Future<String> Function();
|
typedef RadioCurOptionGetter = Future<String> Function();
|
||||||
typedef RadioOptionSetter = Future<void> Function(String);
|
typedef RadioOptionSetter = Future<void> Function(String);
|
||||||
|
|
||||||
|
class MenuEntryRadioUtils<T> {}
|
||||||
|
|
||||||
|
class MenuEntryRadios<T> extends MenuEntryBase<T> {
|
||||||
|
final String text;
|
||||||
|
final RadioOptionsGetter optionsGetter;
|
||||||
|
final RadioCurOptionGetter curOptionGetter;
|
||||||
|
final RadioOptionSetter optionSetter;
|
||||||
|
final RxString _curOption = "".obs;
|
||||||
|
|
||||||
|
MenuEntryRadios(
|
||||||
|
{required this.text,
|
||||||
|
required this.optionsGetter,
|
||||||
|
required this.curOptionGetter,
|
||||||
|
required this.optionSetter}) {
|
||||||
|
() async {
|
||||||
|
_curOption.value = await curOptionGetter();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Tuple2<String, String>> get options => optionsGetter();
|
||||||
|
RxString get curOption => _curOption;
|
||||||
|
setOption(String option) async {
|
||||||
|
await optionSetter(option);
|
||||||
|
final opt = await curOptionGetter();
|
||||||
|
if (_curOption.value != opt) {
|
||||||
|
_curOption.value = opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod_menu.PopupMenuEntry<T> _buildMenuItem(
|
||||||
|
BuildContext context, MenuConfig conf, Tuple2<String, String> opt) {
|
||||||
|
return mod_menu.PopupMenuItem(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
height: conf.height,
|
||||||
|
child: TextButton(
|
||||||
|
child: Container(
|
||||||
|
alignment: AlignmentDirectional.centerStart,
|
||||||
|
constraints: BoxConstraints(minHeight: conf.height),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
opt.item1,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.black,
|
||||||
|
fontSize: MenuConfig.fontSize,
|
||||||
|
fontWeight: FontWeight.normal),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: SizedBox(
|
||||||
|
width: 20.0,
|
||||||
|
height: 20.0,
|
||||||
|
child: Obx(() => opt.item2 == curOption.value
|
||||||
|
? Icon(
|
||||||
|
Icons.check,
|
||||||
|
color: conf.commonColor,
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink())),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
if (opt.item2 != curOption.value) {
|
||||||
|
setOption(opt.item2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<mod_menu.PopupMenuEntry<T>> build(
|
||||||
|
BuildContext context, MenuConfig conf) {
|
||||||
|
return options.map((opt) => _buildMenuItem(context, conf, opt)).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
||||||
final String text;
|
final String text;
|
||||||
final RadioOptionsGetter optionsGetter;
|
final RadioOptionsGetter optionsGetter;
|
||||||
@ -151,23 +233,26 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
|||||||
constraints: BoxConstraints(minHeight: conf.height),
|
constraints: BoxConstraints(minHeight: conf.height),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
|
||||||
width: 20.0,
|
|
||||||
height: 20.0,
|
|
||||||
child: Obx(() => opt.item2 == curOption.value
|
|
||||||
? Icon(
|
|
||||||
Icons.check,
|
|
||||||
color: conf.commonColor,
|
|
||||||
)
|
|
||||||
: const SizedBox.shrink())),
|
|
||||||
const SizedBox(width: MenuConfig.midPadding),
|
|
||||||
Text(
|
Text(
|
||||||
opt.item1,
|
opt.item1,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
fontSize: MenuConfig.fontSize,
|
fontSize: MenuConfig.fontSize,
|
||||||
fontWeight: FontWeight.normal),
|
fontWeight: FontWeight.normal),
|
||||||
)
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: SizedBox(
|
||||||
|
width: 20.0,
|
||||||
|
height: 20.0,
|
||||||
|
child: Obx(() => opt.item2 == curOption.value
|
||||||
|
? Icon(
|
||||||
|
Icons.check,
|
||||||
|
color: conf.commonColor,
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink())),
|
||||||
|
)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -181,31 +266,34 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) {
|
List<mod_menu.PopupMenuEntry<T>> build(
|
||||||
return PopupMenuChildrenItem(
|
BuildContext context, MenuConfig conf) {
|
||||||
padding: EdgeInsets.zero,
|
return [
|
||||||
height: conf.height,
|
PopupMenuChildrenItem(
|
||||||
itemBuilder: (BuildContext context) =>
|
padding: EdgeInsets.zero,
|
||||||
options.map((opt) => _buildSecondMenu(context, conf, opt)).toList(),
|
height: conf.height,
|
||||||
child: Row(children: [
|
itemBuilder: (BuildContext context) =>
|
||||||
const SizedBox(width: MenuConfig.midPadding),
|
options.map((opt) => _buildSecondMenu(context, conf, opt)).toList(),
|
||||||
Text(
|
child: Row(children: [
|
||||||
text,
|
const SizedBox(width: MenuConfig.midPadding),
|
||||||
style: const TextStyle(
|
Text(
|
||||||
color: Colors.black,
|
text,
|
||||||
fontSize: MenuConfig.fontSize,
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.normal),
|
color: Colors.black,
|
||||||
),
|
fontSize: MenuConfig.fontSize,
|
||||||
Expanded(
|
fontWeight: FontWeight.normal),
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: Icon(
|
|
||||||
Icons.keyboard_arrow_right,
|
|
||||||
color: conf.commonColor,
|
|
||||||
),
|
),
|
||||||
))
|
Expanded(
|
||||||
]),
|
child: Align(
|
||||||
);
|
alignment: Alignment.centerRight,
|
||||||
|
child: Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: conf.commonColor,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,35 +309,38 @@ abstract class MenuEntrySwitchBase<T> extends MenuEntryBase<T> {
|
|||||||
Future<void> setOption(bool option);
|
Future<void> setOption(bool option);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) {
|
List<mod_menu.PopupMenuEntry<T>> build(
|
||||||
return mod_menu.PopupMenuItem(
|
BuildContext context, MenuConfig conf) {
|
||||||
padding: EdgeInsets.zero,
|
return [
|
||||||
height: conf.height,
|
mod_menu.PopupMenuItem(
|
||||||
child: Obx(
|
padding: EdgeInsets.zero,
|
||||||
() => SwitchListTile(
|
height: conf.height,
|
||||||
value: curOption.value,
|
child: Obx(
|
||||||
onChanged: (v) {
|
() => SwitchListTile(
|
||||||
setOption(v);
|
value: curOption.value,
|
||||||
},
|
onChanged: (v) {
|
||||||
title: Container(
|
setOption(v);
|
||||||
alignment: AlignmentDirectional.centerStart,
|
},
|
||||||
constraints: BoxConstraints(minHeight: conf.height),
|
title: Container(
|
||||||
child: Text(
|
alignment: AlignmentDirectional.centerStart,
|
||||||
text,
|
constraints: BoxConstraints(minHeight: conf.height),
|
||||||
style: const TextStyle(
|
child: Text(
|
||||||
color: Colors.black,
|
text,
|
||||||
fontSize: MenuConfig.fontSize,
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.normal),
|
color: Colors.black,
|
||||||
)),
|
fontSize: MenuConfig.fontSize,
|
||||||
dense: true,
|
fontWeight: FontWeight.normal),
|
||||||
visualDensity: const VisualDensity(
|
)),
|
||||||
horizontal: VisualDensity.minimumDensity,
|
dense: true,
|
||||||
vertical: VisualDensity.minimumDensity,
|
visualDensity: const VisualDensity(
|
||||||
|
horizontal: VisualDensity.minimumDensity,
|
||||||
|
vertical: VisualDensity.minimumDensity,
|
||||||
|
),
|
||||||
|
contentPadding: const EdgeInsets.only(left: 8.0),
|
||||||
),
|
),
|
||||||
contentPadding: const EdgeInsets.only(left: 8.0),
|
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
);
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,32 +398,37 @@ class MenuEntrySubMenu<T> extends MenuEntryBase<T> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) {
|
List<mod_menu.PopupMenuEntry<T>> build(
|
||||||
return PopupMenuChildrenItem(
|
BuildContext context, MenuConfig conf) {
|
||||||
height: conf.height,
|
return [
|
||||||
padding: EdgeInsets.zero,
|
PopupMenuChildrenItem(
|
||||||
position: mod_menu.PopupMenuPosition.overSide,
|
height: conf.height,
|
||||||
itemBuilder: (BuildContext context) =>
|
padding: EdgeInsets.zero,
|
||||||
entries.map((entry) => entry.build(context, conf)).toList(),
|
position: mod_menu.PopupMenuPosition.overSide,
|
||||||
child: Row(children: [
|
itemBuilder: (BuildContext context) => entries
|
||||||
const SizedBox(width: MenuConfig.midPadding),
|
.map((entry) => entry.build(context, conf))
|
||||||
Text(
|
.expand((i) => i)
|
||||||
text,
|
.toList(),
|
||||||
style: const TextStyle(
|
child: Row(children: [
|
||||||
color: Colors.black,
|
const SizedBox(width: MenuConfig.midPadding),
|
||||||
fontSize: MenuConfig.fontSize,
|
Text(
|
||||||
fontWeight: FontWeight.normal),
|
text,
|
||||||
),
|
style: const TextStyle(
|
||||||
Expanded(
|
color: Colors.black,
|
||||||
child: Align(
|
fontSize: MenuConfig.fontSize,
|
||||||
alignment: Alignment.centerRight,
|
fontWeight: FontWeight.normal),
|
||||||
child: Icon(
|
|
||||||
Icons.keyboard_arrow_right,
|
|
||||||
color: conf.commonColor,
|
|
||||||
),
|
),
|
||||||
))
|
Expanded(
|
||||||
]),
|
child: Align(
|
||||||
);
|
alignment: Alignment.centerRight,
|
||||||
|
child: Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: conf.commonColor,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,24 +442,27 @@ class MenuEntryButton<T> extends MenuEntryBase<T> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) {
|
List<mod_menu.PopupMenuEntry<T>> build(
|
||||||
return mod_menu.PopupMenuItem(
|
BuildContext context, MenuConfig conf) {
|
||||||
padding: EdgeInsets.zero,
|
return [
|
||||||
height: conf.height,
|
mod_menu.PopupMenuItem(
|
||||||
child: TextButton(
|
padding: EdgeInsets.zero,
|
||||||
child: Container(
|
height: conf.height,
|
||||||
alignment: AlignmentDirectional.centerStart,
|
child: TextButton(
|
||||||
constraints: BoxConstraints(minHeight: conf.height),
|
child: Container(
|
||||||
child: childBuilder(
|
alignment: AlignmentDirectional.centerStart,
|
||||||
const TextStyle(
|
constraints: BoxConstraints(minHeight: conf.height),
|
||||||
color: Colors.black,
|
child: childBuilder(
|
||||||
fontSize: MenuConfig.fontSize,
|
const TextStyle(
|
||||||
fontWeight: FontWeight.normal),
|
color: Colors.black,
|
||||||
)),
|
fontSize: MenuConfig.fontSize,
|
||||||
onPressed: () {
|
fontWeight: FontWeight.normal),
|
||||||
proc();
|
)),
|
||||||
},
|
onPressed: () {
|
||||||
),
|
proc();
|
||||||
);
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
height: _MenubarTheme.height,
|
height: _MenubarTheme.height,
|
||||||
dividerHeight: _MenubarTheme.dividerHeight,
|
dividerHeight: _MenubarTheme.dividerHeight,
|
||||||
)))
|
)))
|
||||||
|
.expand((i) => i)
|
||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -258,6 +259,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
height: _MenubarTheme.height,
|
height: _MenubarTheme.height,
|
||||||
dividerHeight: _MenubarTheme.dividerHeight,
|
dividerHeight: _MenubarTheme.dividerHeight,
|
||||||
)))
|
)))
|
||||||
|
.expand((i) => i)
|
||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -401,7 +403,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
|
|
||||||
List<MenuEntryBase<String>> _getDisplayMenu() {
|
List<MenuEntryBase<String>> _getDisplayMenu() {
|
||||||
final displayMenu = [
|
final displayMenu = [
|
||||||
MenuEntrySubRadios<String>(
|
MenuEntryRadios<String>(
|
||||||
text: translate('Ratio'),
|
text: translate('Ratio'),
|
||||||
optionsGetter: () => [
|
optionsGetter: () => [
|
||||||
Tuple2<String, String>(translate('Original'), 'original'),
|
Tuple2<String, String>(translate('Original'), 'original'),
|
||||||
@ -418,7 +420,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
id: widget.id, name: "view-style", value: v);
|
id: widget.id, name: "view-style", value: v);
|
||||||
widget.ffi.canvasModel.updateViewStyle();
|
widget.ffi.canvasModel.updateViewStyle();
|
||||||
}),
|
}),
|
||||||
MenuEntrySubRadios<String>(
|
MenuEntryDivider<String>(),
|
||||||
|
MenuEntryRadios<String>(
|
||||||
text: translate('Scroll Style'),
|
text: translate('Scroll Style'),
|
||||||
optionsGetter: () => [
|
optionsGetter: () => [
|
||||||
Tuple2<String, String>(translate('ScrollAuto'), 'scrollauto'),
|
Tuple2<String, String>(translate('ScrollAuto'), 'scrollauto'),
|
||||||
@ -434,7 +437,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
id: widget.id, name: "scroll-style", value: v);
|
id: widget.id, name: "scroll-style", value: v);
|
||||||
widget.ffi.canvasModel.updateScrollStyle();
|
widget.ffi.canvasModel.updateScrollStyle();
|
||||||
}),
|
}),
|
||||||
MenuEntrySubRadios<String>(
|
MenuEntryDivider<String>(),
|
||||||
|
MenuEntryRadios<String>(
|
||||||
text: translate('Image Quality'),
|
text: translate('Image Quality'),
|
||||||
optionsGetter: () => [
|
optionsGetter: () => [
|
||||||
Tuple2<String, String>(translate('Good image quality'), 'best'),
|
Tuple2<String, String>(translate('Good image quality'), 'best'),
|
||||||
@ -451,6 +455,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
optionSetter: (String v) async {
|
optionSetter: (String v) async {
|
||||||
await bind.sessionSetImageQuality(id: widget.id, value: v);
|
await bind.sessionSetImageQuality(id: widget.id, value: v);
|
||||||
}),
|
}),
|
||||||
|
MenuEntryDivider<String>(),
|
||||||
MenuEntrySwitch<String>(
|
MenuEntrySwitch<String>(
|
||||||
text: translate('Show remote cursor'),
|
text: translate('Show remote cursor'),
|
||||||
getter: () async {
|
getter: () async {
|
||||||
|
@ -40,10 +40,7 @@ dependencies:
|
|||||||
url_launcher: ^6.0.9
|
url_launcher: ^6.0.9
|
||||||
shared_preferences: ^2.0.6
|
shared_preferences: ^2.0.6
|
||||||
toggle_switch: ^1.4.0
|
toggle_switch: ^1.4.0
|
||||||
dash_chat_2:
|
dash_chat_2: ^0.0.14
|
||||||
git:
|
|
||||||
url: https://github.com/fufesou/Dash-Chat-2
|
|
||||||
ref: feat_maxWidth
|
|
||||||
draggable_float_widget: ^0.0.2
|
draggable_float_widget: ^0.0.2
|
||||||
settings_ui: ^2.0.2
|
settings_ui: ^2.0.2
|
||||||
flutter_breadcrumb: ^1.0.1
|
flutter_breadcrumb: ^1.0.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user