Merge pull request #1608 from fufesou/flutter_desktop_popupmenu_adjust
flutter_desktop: remove animation & adjust popup menu
This commit is contained in:
commit
95a241bdf4
@ -177,6 +177,12 @@ class MyTheme {
|
|||||||
),
|
),
|
||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
highlightColor: Colors.transparent,
|
highlightColor: Colors.transparent,
|
||||||
|
splashFactory: isDesktop ? NoSplash.splashFactory : null,
|
||||||
|
textButtonTheme: isDesktop
|
||||||
|
? TextButtonThemeData(
|
||||||
|
style: ButtonStyle(splashFactory: NoSplash.splashFactory),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
).copyWith(
|
).copyWith(
|
||||||
extensions: <ThemeExtension<dynamic>>[
|
extensions: <ThemeExtension<dynamic>>[
|
||||||
ColorThemeExtension.light,
|
ColorThemeExtension.light,
|
||||||
@ -192,6 +198,12 @@ class MyTheme {
|
|||||||
),
|
),
|
||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
highlightColor: Colors.transparent,
|
highlightColor: Colors.transparent,
|
||||||
|
splashFactory: isDesktop ? NoSplash.splashFactory : null,
|
||||||
|
textButtonTheme: isDesktop
|
||||||
|
? TextButtonThemeData(
|
||||||
|
style: ButtonStyle(splashFactory: NoSplash.splashFactory),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
).copyWith(
|
).copyWith(
|
||||||
extensions: <ThemeExtension<dynamic>>[
|
extensions: <ThemeExtension<dynamic>>[
|
||||||
ColorThemeExtension.dark,
|
ColorThemeExtension.dark,
|
||||||
|
@ -11,7 +11,8 @@ import '../../mobile/pages/settings_page.dart';
|
|||||||
import '../../models/platform_model.dart';
|
import '../../models/platform_model.dart';
|
||||||
|
|
||||||
class AddressBook extends StatefulWidget {
|
class AddressBook extends StatefulWidget {
|
||||||
const AddressBook({Key? key}) : super(key: key);
|
final EdgeInsets? menuPadding;
|
||||||
|
const AddressBook({Key? key, this.menuPadding}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
State<StatefulWidget> createState() {
|
||||||
@ -180,7 +181,9 @@ class _AddressBookState extends State<AddressBook> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
child: AddressBookPeersView()),
|
child: AddressBookPeersView(
|
||||||
|
menuPadding: widget.menuPadding,
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
|
@ -14,7 +14,7 @@ import '../../desktop/widgets/popup_menu.dart';
|
|||||||
class _PopupMenuTheme {
|
class _PopupMenuTheme {
|
||||||
static const Color commonColor = MyTheme.accent;
|
static const Color commonColor = MyTheme.accent;
|
||||||
// kMinInteractiveDimension
|
// kMinInteractiveDimension
|
||||||
static const double height = 25.0;
|
static const double height = 20.0;
|
||||||
static const double dividerHeight = 3.0;
|
static const double dividerHeight = 3.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,8 +319,10 @@ class _PeerCardState extends State<_PeerCard>
|
|||||||
|
|
||||||
abstract class BasePeerCard extends StatelessWidget {
|
abstract class BasePeerCard extends StatelessWidget {
|
||||||
final Peer peer;
|
final Peer peer;
|
||||||
|
final EdgeInsets? menuPadding;
|
||||||
|
|
||||||
BasePeerCard({required this.peer, Key? key}) : super(key: key);
|
BasePeerCard({required this.peer, this.menuPadding, Key? key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -365,6 +367,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
isRDP: isRDP,
|
isRDP: isRDP,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -414,17 +417,25 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
|
child: Transform.scale(
|
||||||
|
scale: 0.8,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
icon: const Icon(Icons.edit),
|
icon: const Icon(Icons.edit),
|
||||||
onPressed: () => _rdpDialog(id),
|
padding: EdgeInsets.zero,
|
||||||
),
|
onPressed: () {
|
||||||
|
if (Navigator.canPop(context)) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
_rdpDialog(id);
|
||||||
|
},
|
||||||
|
)),
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
proc: () {
|
proc: () {
|
||||||
connect(context, id, isRDP: true);
|
connect(context, id, isRDP: true);
|
||||||
},
|
},
|
||||||
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -439,6 +450,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
proc: () {
|
proc: () {
|
||||||
bind.mainWol(id: id);
|
bind.mainWol(id: id);
|
||||||
},
|
},
|
||||||
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -447,6 +459,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
Future<MenuEntryBase<String>> _forceAlwaysRelayAction(String id) async {
|
Future<MenuEntryBase<String>> _forceAlwaysRelayAction(String id) async {
|
||||||
const option = 'force-always-relay';
|
const option = 'force-always-relay';
|
||||||
return MenuEntrySwitch<String>(
|
return MenuEntrySwitch<String>(
|
||||||
|
switchType: SwitchType.scheckbox,
|
||||||
text: translate('Always connect via relay'),
|
text: translate('Always connect via relay'),
|
||||||
getter: () async {
|
getter: () async {
|
||||||
return (await bind.mainGetPeerOption(id: id, key: option)).isNotEmpty;
|
return (await bind.mainGetPeerOption(id: id, key: option)).isNotEmpty;
|
||||||
@ -461,7 +474,8 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
await bind.mainSetPeerOption(id: id, key: option, value: value);
|
await bind.mainSetPeerOption(id: id, key: option, value: value);
|
||||||
},
|
},
|
||||||
dismissOnClicked: false,
|
padding: menuPadding,
|
||||||
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,6 +489,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
proc: () {
|
proc: () {
|
||||||
_rename(id, isAddressBook);
|
_rename(id, isAddressBook);
|
||||||
},
|
},
|
||||||
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -494,6 +509,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
await reloadFunc();
|
await reloadFunc();
|
||||||
}();
|
}();
|
||||||
},
|
},
|
||||||
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -508,6 +524,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
proc: () {
|
proc: () {
|
||||||
bind.mainForgetPassword(id: id);
|
bind.mainForgetPassword(id: id);
|
||||||
},
|
},
|
||||||
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -528,6 +545,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
},
|
},
|
||||||
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -549,6 +567,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
},
|
},
|
||||||
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -616,7 +635,8 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RecentPeerCard extends BasePeerCard {
|
class RecentPeerCard extends BasePeerCard {
|
||||||
RecentPeerCard({required Peer peer, Key? key}) : super(peer: peer, key: key);
|
RecentPeerCard({required Peer peer, EdgeInsets? menuPadding, Key? key})
|
||||||
|
: super(peer: peer, menuPadding: menuPadding, key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<MenuEntryBase<String>>> _buildMenuItems(
|
Future<List<MenuEntryBase<String>>> _buildMenuItems(
|
||||||
@ -645,8 +665,8 @@ class RecentPeerCard extends BasePeerCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FavoritePeerCard extends BasePeerCard {
|
class FavoritePeerCard extends BasePeerCard {
|
||||||
FavoritePeerCard({required Peer peer, Key? key})
|
FavoritePeerCard({required Peer peer, EdgeInsets? menuPadding, Key? key})
|
||||||
: super(peer: peer, key: key);
|
: super(peer: peer, menuPadding: menuPadding, key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<MenuEntryBase<String>>> _buildMenuItems(
|
Future<List<MenuEntryBase<String>>> _buildMenuItems(
|
||||||
@ -677,8 +697,8 @@ class FavoritePeerCard extends BasePeerCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DiscoveredPeerCard extends BasePeerCard {
|
class DiscoveredPeerCard extends BasePeerCard {
|
||||||
DiscoveredPeerCard({required Peer peer, Key? key})
|
DiscoveredPeerCard({required Peer peer, EdgeInsets? menuPadding, Key? key})
|
||||||
: super(peer: peer, key: key);
|
: super(peer: peer, menuPadding: menuPadding, key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<MenuEntryBase<String>>> _buildMenuItems(
|
Future<List<MenuEntryBase<String>>> _buildMenuItems(
|
||||||
@ -706,8 +726,8 @@ class DiscoveredPeerCard extends BasePeerCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AddressBookPeerCard extends BasePeerCard {
|
class AddressBookPeerCard extends BasePeerCard {
|
||||||
AddressBookPeerCard({required Peer peer, Key? key})
|
AddressBookPeerCard({required Peer peer, EdgeInsets? menuPadding, Key? key})
|
||||||
: super(peer: peer, key: key);
|
: super(peer: peer, menuPadding: menuPadding, key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<MenuEntryBase<String>>> _buildMenuItems(
|
Future<List<MenuEntryBase<String>>> _buildMenuItems(
|
||||||
@ -748,6 +768,7 @@ class AddressBookPeerCard extends BasePeerCard {
|
|||||||
await gFFI.abModel.updateAb();
|
await gFFI.abModel.updateAb();
|
||||||
}();
|
}();
|
||||||
},
|
},
|
||||||
|
padding: super.menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -762,6 +783,7 @@ class AddressBookPeerCard extends BasePeerCard {
|
|||||||
proc: () {
|
proc: () {
|
||||||
_abEditTag(id);
|
_abEditTag(id);
|
||||||
},
|
},
|
||||||
|
padding: super.menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ abstract class BasePeersView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RecentPeersView extends BasePeersView {
|
class RecentPeersView extends BasePeersView {
|
||||||
RecentPeersView({Key? key})
|
RecentPeersView({Key? key, EdgeInsets? menuPadding})
|
||||||
: super(
|
: super(
|
||||||
key: key,
|
key: key,
|
||||||
name: 'recent peer',
|
name: 'recent peer',
|
||||||
@ -232,6 +232,7 @@ class RecentPeersView extends BasePeersView {
|
|||||||
offstageFunc: (Peer peer) => false,
|
offstageFunc: (Peer peer) => false,
|
||||||
peerCardBuilder: (Peer peer) => RecentPeerCard(
|
peerCardBuilder: (Peer peer) => RecentPeerCard(
|
||||||
peer: peer,
|
peer: peer,
|
||||||
|
menuPadding: menuPadding,
|
||||||
),
|
),
|
||||||
initPeers: [],
|
initPeers: [],
|
||||||
);
|
);
|
||||||
@ -245,7 +246,7 @@ class RecentPeersView extends BasePeersView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FavoritePeersView extends BasePeersView {
|
class FavoritePeersView extends BasePeersView {
|
||||||
FavoritePeersView({Key? key})
|
FavoritePeersView({Key? key, EdgeInsets? menuPadding})
|
||||||
: super(
|
: super(
|
||||||
key: key,
|
key: key,
|
||||||
name: 'favorite peer',
|
name: 'favorite peer',
|
||||||
@ -253,6 +254,7 @@ class FavoritePeersView extends BasePeersView {
|
|||||||
offstageFunc: (Peer peer) => false,
|
offstageFunc: (Peer peer) => false,
|
||||||
peerCardBuilder: (Peer peer) => FavoritePeerCard(
|
peerCardBuilder: (Peer peer) => FavoritePeerCard(
|
||||||
peer: peer,
|
peer: peer,
|
||||||
|
menuPadding: menuPadding,
|
||||||
),
|
),
|
||||||
initPeers: [],
|
initPeers: [],
|
||||||
);
|
);
|
||||||
@ -266,7 +268,7 @@ class FavoritePeersView extends BasePeersView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DiscoveredPeersView extends BasePeersView {
|
class DiscoveredPeersView extends BasePeersView {
|
||||||
DiscoveredPeersView({Key? key})
|
DiscoveredPeersView({Key? key, EdgeInsets? menuPadding})
|
||||||
: super(
|
: super(
|
||||||
key: key,
|
key: key,
|
||||||
name: 'discovered peer',
|
name: 'discovered peer',
|
||||||
@ -274,6 +276,7 @@ class DiscoveredPeersView extends BasePeersView {
|
|||||||
offstageFunc: (Peer peer) => false,
|
offstageFunc: (Peer peer) => false,
|
||||||
peerCardBuilder: (Peer peer) => DiscoveredPeerCard(
|
peerCardBuilder: (Peer peer) => DiscoveredPeerCard(
|
||||||
peer: peer,
|
peer: peer,
|
||||||
|
menuPadding: menuPadding,
|
||||||
),
|
),
|
||||||
initPeers: [],
|
initPeers: [],
|
||||||
);
|
);
|
||||||
@ -287,7 +290,7 @@ class DiscoveredPeersView extends BasePeersView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AddressBookPeersView extends BasePeersView {
|
class AddressBookPeersView extends BasePeersView {
|
||||||
AddressBookPeersView({Key? key})
|
AddressBookPeersView({Key? key, EdgeInsets? menuPadding})
|
||||||
: super(
|
: super(
|
||||||
key: key,
|
key: key,
|
||||||
name: 'address book peer',
|
name: 'address book peer',
|
||||||
@ -296,6 +299,7 @@ class AddressBookPeersView extends BasePeersView {
|
|||||||
!_hitTag(gFFI.abModel.selectedTags, peer.tags),
|
!_hitTag(gFFI.abModel.selectedTags, peer.tags),
|
||||||
peerCardBuilder: (Peer peer) => AddressBookPeerCard(
|
peerCardBuilder: (Peer peer) => AddressBookPeerCard(
|
||||||
peer: peer,
|
peer: peer,
|
||||||
|
menuPadding: menuPadding,
|
||||||
),
|
),
|
||||||
initPeers: _loadPeers(),
|
initPeers: _loadPeers(),
|
||||||
);
|
);
|
||||||
|
@ -74,10 +74,18 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
translate('Address Book')
|
translate('Address Book')
|
||||||
],
|
],
|
||||||
children: [
|
children: [
|
||||||
RecentPeersView(),
|
RecentPeersView(
|
||||||
FavoritePeersView(),
|
menuPadding: EdgeInsets.only(left: 12.0, right: 3.0),
|
||||||
DiscoveredPeersView(),
|
),
|
||||||
const AddressBook(),
|
FavoritePeersView(
|
||||||
|
menuPadding: EdgeInsets.only(left: 12.0, right: 3.0),
|
||||||
|
),
|
||||||
|
DiscoveredPeersView(
|
||||||
|
menuPadding: EdgeInsets.only(left: 12.0, right: 3.0),
|
||||||
|
),
|
||||||
|
const AddressBook(
|
||||||
|
menuPadding: EdgeInsets.only(left: 12.0, right: 3.0),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
|
@ -14,7 +14,8 @@ import 'package:flutter/material.dart';
|
|||||||
// void setState(VoidCallback fn) { }
|
// void setState(VoidCallback fn) { }
|
||||||
// enum Menu { itemOne, itemTwo, itemThree, itemFour }
|
// enum Menu { itemOne, itemTwo, itemThree, itemFour }
|
||||||
|
|
||||||
const Duration _kMenuDuration = Duration(milliseconds: 300);
|
// const Duration _kMenuDuration = Duration(milliseconds: 300);
|
||||||
|
const Duration _kMenuDuration = Duration(milliseconds: 0);
|
||||||
const double _kMenuCloseIntervalEnd = 2.0 / 3.0;
|
const double _kMenuCloseIntervalEnd = 2.0 / 3.0;
|
||||||
const double _kMenuHorizontalPadding = 16.0;
|
const double _kMenuHorizontalPadding = 16.0;
|
||||||
const double _kMenuDividerHeight = 16.0;
|
const double _kMenuDividerHeight = 16.0;
|
||||||
@ -22,7 +23,7 @@ const double _kMenuDividerHeight = 16.0;
|
|||||||
const double _kMenuMinWidth = 2.0 * _kMenuWidthStep;
|
const double _kMenuMinWidth = 2.0 * _kMenuWidthStep;
|
||||||
const double _kMenuMaxWidth = double.infinity;
|
const double _kMenuMaxWidth = double.infinity;
|
||||||
// const double _kMenuVerticalPadding = 8.0;
|
// const double _kMenuVerticalPadding = 8.0;
|
||||||
const double _kMenuVerticalPadding = 0.0;
|
const double _kMenuVerticalPadding = 8.0;
|
||||||
const double _kMenuWidthStep = 0.0;
|
const double _kMenuWidthStep = 0.0;
|
||||||
//const double _kMenuScreenPadding = 8.0;
|
//const double _kMenuScreenPadding = 8.0;
|
||||||
const double _kMenuScreenPadding = 0.0;
|
const double _kMenuScreenPadding = 0.0;
|
||||||
|
@ -78,7 +78,8 @@ class MyPopupMenuItemState<T, W extends PopupMenuChildrenItem<T>>
|
|||||||
duration: kThemeChangeDuration,
|
duration: kThemeChangeDuration,
|
||||||
child: Container(
|
child: Container(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
constraints: BoxConstraints(minHeight: widget.height),
|
constraints: BoxConstraints(
|
||||||
|
minHeight: widget.height, maxHeight: widget.height),
|
||||||
padding:
|
padding:
|
||||||
widget.padding ?? const EdgeInsets.symmetric(horizontal: 16),
|
widget.padding ?? const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
@ -156,12 +157,14 @@ class MenuEntryRadios<T> extends MenuEntryBase<T> {
|
|||||||
final RadioCurOptionGetter curOptionGetter;
|
final RadioCurOptionGetter curOptionGetter;
|
||||||
final RadioOptionSetter optionSetter;
|
final RadioOptionSetter optionSetter;
|
||||||
final RxString _curOption = "".obs;
|
final RxString _curOption = "".obs;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
|
||||||
MenuEntryRadios({
|
MenuEntryRadios({
|
||||||
required this.text,
|
required this.text,
|
||||||
required this.optionsGetter,
|
required this.optionsGetter,
|
||||||
required this.curOptionGetter,
|
required this.curOptionGetter,
|
||||||
required this.optionSetter,
|
required this.optionSetter,
|
||||||
|
this.padding,
|
||||||
dismissOnClicked = false,
|
dismissOnClicked = false,
|
||||||
RxBool? enabled,
|
RxBool? enabled,
|
||||||
}) : super(dismissOnClicked: dismissOnClicked, enabled: enabled) {
|
}) : super(dismissOnClicked: dismissOnClicked, enabled: enabled) {
|
||||||
@ -189,8 +192,10 @@ class MenuEntryRadios<T> extends MenuEntryBase<T> {
|
|||||||
height: conf.height,
|
height: conf.height,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
child: Container(
|
child: Container(
|
||||||
|
padding: padding,
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
constraints: BoxConstraints(minHeight: conf.height),
|
constraints:
|
||||||
|
BoxConstraints(minHeight: conf.height, maxHeight: conf.height),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
@ -203,16 +208,21 @@ class MenuEntryRadios<T> extends MenuEntryBase<T> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: SizedBox(
|
child: Transform.scale(
|
||||||
width: 20.0,
|
scale: MenuConfig.iconScale,
|
||||||
height: 20.0,
|
|
||||||
child: Obx(() => opt.value == curOption.value
|
child: Obx(() => opt.value == curOption.value
|
||||||
? Icon(
|
? IconButton(
|
||||||
|
padding: const EdgeInsets.fromLTRB(
|
||||||
|
8.0, 0.0, 8.0, 0.0),
|
||||||
|
hoverColor: Colors.transparent,
|
||||||
|
focusColor: Colors.transparent,
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(
|
||||||
Icons.check,
|
Icons.check,
|
||||||
color: conf.commonColor,
|
color: conf.commonColor,
|
||||||
)
|
))
|
||||||
: const SizedBox.shrink())),
|
: const SizedBox.shrink()),
|
||||||
)),
|
))),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -239,12 +249,14 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
|||||||
final RadioCurOptionGetter curOptionGetter;
|
final RadioCurOptionGetter curOptionGetter;
|
||||||
final RadioOptionSetter optionSetter;
|
final RadioOptionSetter optionSetter;
|
||||||
final RxString _curOption = "".obs;
|
final RxString _curOption = "".obs;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
|
||||||
MenuEntrySubRadios({
|
MenuEntrySubRadios({
|
||||||
required this.text,
|
required this.text,
|
||||||
required this.optionsGetter,
|
required this.optionsGetter,
|
||||||
required this.curOptionGetter,
|
required this.curOptionGetter,
|
||||||
required this.optionSetter,
|
required this.optionSetter,
|
||||||
|
this.padding,
|
||||||
dismissOnClicked = false,
|
dismissOnClicked = false,
|
||||||
RxBool? enabled,
|
RxBool? enabled,
|
||||||
}) : super(
|
}) : super(
|
||||||
@ -275,8 +287,10 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
|||||||
height: conf.height,
|
height: conf.height,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
child: Container(
|
child: Container(
|
||||||
|
padding: padding,
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
constraints: BoxConstraints(minHeight: conf.height),
|
constraints:
|
||||||
|
BoxConstraints(minHeight: conf.height, maxHeight: conf.height),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
@ -289,14 +303,18 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: SizedBox(
|
child: Transform.scale(
|
||||||
width: 20.0,
|
scale: MenuConfig.iconScale,
|
||||||
height: 20.0,
|
|
||||||
child: Obx(() => opt.value == curOption.value
|
child: Obx(() => opt.value == curOption.value
|
||||||
? Icon(
|
? IconButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
hoverColor: Colors.transparent,
|
||||||
|
focusColor: Colors.transparent,
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(
|
||||||
Icons.check,
|
Icons.check,
|
||||||
color: conf.commonColor,
|
color: conf.commonColor,
|
||||||
)
|
))
|
||||||
: const SizedBox.shrink())),
|
: const SizedBox.shrink())),
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
@ -318,7 +336,7 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
|||||||
return [
|
return [
|
||||||
PopupMenuChildrenItem(
|
PopupMenuChildrenItem(
|
||||||
enabled: super.enabled,
|
enabled: super.enabled,
|
||||||
padding: EdgeInsets.zero,
|
padding: padding,
|
||||||
height: conf.height,
|
height: conf.height,
|
||||||
itemBuilder: (BuildContext context) =>
|
itemBuilder: (BuildContext context) =>
|
||||||
options.map((opt) => _buildSecondMenu(context, conf, opt)).toList(),
|
options.map((opt) => _buildSecondMenu(context, conf, opt)).toList(),
|
||||||
@ -345,22 +363,31 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SwitchType {
|
||||||
|
sswitch,
|
||||||
|
scheckbox,
|
||||||
|
}
|
||||||
|
|
||||||
typedef SwitchGetter = Future<bool> Function();
|
typedef SwitchGetter = Future<bool> Function();
|
||||||
typedef SwitchSetter = Future<void> Function(bool);
|
typedef SwitchSetter = Future<void> Function(bool);
|
||||||
|
|
||||||
abstract class MenuEntrySwitchBase<T> extends MenuEntryBase<T> {
|
abstract class MenuEntrySwitchBase<T> extends MenuEntryBase<T> {
|
||||||
|
final SwitchType switchType;
|
||||||
final String text;
|
final String text;
|
||||||
|
final EdgeInsets? padding;
|
||||||
Rx<TextStyle>? textStyle;
|
Rx<TextStyle>? textStyle;
|
||||||
|
|
||||||
MenuEntrySwitchBase({
|
MenuEntrySwitchBase({
|
||||||
|
required this.switchType,
|
||||||
required this.text,
|
required this.text,
|
||||||
required dismissOnClicked,
|
required dismissOnClicked,
|
||||||
this.textStyle,
|
this.textStyle,
|
||||||
|
this.padding,
|
||||||
RxBool? enabled,
|
RxBool? enabled,
|
||||||
}) : super(dismissOnClicked: dismissOnClicked, enabled: enabled);
|
}) : super(dismissOnClicked: dismissOnClicked, enabled: enabled);
|
||||||
|
|
||||||
RxBool get curOption;
|
RxBool get curOption;
|
||||||
Future<void> setOption(bool option);
|
Future<void> setOption(bool? option);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<mod_menu.PopupMenuEntry<T>> build(
|
List<mod_menu.PopupMenuEntry<T>> build(
|
||||||
@ -376,6 +403,7 @@ abstract class MenuEntrySwitchBase<T> extends MenuEntryBase<T> {
|
|||||||
height: conf.height,
|
height: conf.height,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
child: Container(
|
child: Container(
|
||||||
|
padding: padding,
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
height: conf.height,
|
height: conf.height,
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
@ -386,7 +414,11 @@ abstract class MenuEntrySwitchBase<T> extends MenuEntryBase<T> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Obx(() => Switch(
|
child: Transform.scale(
|
||||||
|
scale: MenuConfig.iconScale,
|
||||||
|
child: Obx(() {
|
||||||
|
if (switchType == SwitchType.sswitch) {
|
||||||
|
return Switch(
|
||||||
value: curOption.value,
|
value: curOption.value,
|
||||||
onChanged: (v) {
|
onChanged: (v) {
|
||||||
if (super.dismissOnClicked &&
|
if (super.dismissOnClicked &&
|
||||||
@ -395,7 +427,20 @@ abstract class MenuEntrySwitchBase<T> extends MenuEntryBase<T> {
|
|||||||
}
|
}
|
||||||
setOption(v);
|
setOption(v);
|
||||||
},
|
},
|
||||||
)),
|
);
|
||||||
|
} else {
|
||||||
|
return Checkbox(
|
||||||
|
value: curOption.value,
|
||||||
|
onChanged: (v) {
|
||||||
|
if (super.dismissOnClicked &&
|
||||||
|
Navigator.canPop(context)) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
setOption(v);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})),
|
||||||
))
|
))
|
||||||
])),
|
])),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -416,15 +461,19 @@ class MenuEntrySwitch<T> extends MenuEntrySwitchBase<T> {
|
|||||||
final RxBool _curOption = false.obs;
|
final RxBool _curOption = false.obs;
|
||||||
|
|
||||||
MenuEntrySwitch({
|
MenuEntrySwitch({
|
||||||
|
required SwitchType switchType,
|
||||||
required String text,
|
required String text,
|
||||||
required this.getter,
|
required this.getter,
|
||||||
required this.setter,
|
required this.setter,
|
||||||
Rx<TextStyle>? textStyle,
|
Rx<TextStyle>? textStyle,
|
||||||
|
EdgeInsets? padding,
|
||||||
dismissOnClicked = false,
|
dismissOnClicked = false,
|
||||||
RxBool? enabled,
|
RxBool? enabled,
|
||||||
}) : super(
|
}) : super(
|
||||||
|
switchType: switchType,
|
||||||
text: text,
|
text: text,
|
||||||
textStyle: textStyle,
|
textStyle: textStyle,
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: dismissOnClicked,
|
dismissOnClicked: dismissOnClicked,
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
) {
|
) {
|
||||||
@ -436,7 +485,8 @@ class MenuEntrySwitch<T> extends MenuEntrySwitchBase<T> {
|
|||||||
@override
|
@override
|
||||||
RxBool get curOption => _curOption;
|
RxBool get curOption => _curOption;
|
||||||
@override
|
@override
|
||||||
setOption(bool option) async {
|
setOption(bool? option) async {
|
||||||
|
if (option != null) {
|
||||||
await setter(option);
|
await setter(option);
|
||||||
final opt = await getter();
|
final opt = await getter();
|
||||||
if (_curOption.value != opt) {
|
if (_curOption.value != opt) {
|
||||||
@ -444,6 +494,7 @@ class MenuEntrySwitch<T> extends MenuEntrySwitchBase<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef Switch2Getter = RxBool Function();
|
typedef Switch2Getter = RxBool Function();
|
||||||
typedef Switch2Setter = Future<void> Function(bool);
|
typedef Switch2Setter = Future<void> Function(bool);
|
||||||
@ -453,32 +504,40 @@ class MenuEntrySwitch2<T> extends MenuEntrySwitchBase<T> {
|
|||||||
final SwitchSetter setter;
|
final SwitchSetter setter;
|
||||||
|
|
||||||
MenuEntrySwitch2({
|
MenuEntrySwitch2({
|
||||||
|
required SwitchType switchType,
|
||||||
required String text,
|
required String text,
|
||||||
required this.getter,
|
required this.getter,
|
||||||
required this.setter,
|
required this.setter,
|
||||||
Rx<TextStyle>? textStyle,
|
Rx<TextStyle>? textStyle,
|
||||||
|
EdgeInsets? padding,
|
||||||
dismissOnClicked = false,
|
dismissOnClicked = false,
|
||||||
RxBool? enabled,
|
RxBool? enabled,
|
||||||
}) : super(
|
}) : super(
|
||||||
|
switchType: switchType,
|
||||||
text: text,
|
text: text,
|
||||||
textStyle: textStyle,
|
textStyle: textStyle,
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: dismissOnClicked);
|
dismissOnClicked: dismissOnClicked);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
RxBool get curOption => getter();
|
RxBool get curOption => getter();
|
||||||
@override
|
@override
|
||||||
setOption(bool option) async {
|
setOption(bool? option) async {
|
||||||
|
if (option != null) {
|
||||||
await setter(option);
|
await setter(option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MenuEntrySubMenu<T> extends MenuEntryBase<T> {
|
class MenuEntrySubMenu<T> extends MenuEntryBase<T> {
|
||||||
final String text;
|
final String text;
|
||||||
final List<MenuEntryBase<T>> entries;
|
final List<MenuEntryBase<T>> entries;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
|
||||||
MenuEntrySubMenu({
|
MenuEntrySubMenu({
|
||||||
required this.text,
|
required this.text,
|
||||||
required this.entries,
|
required this.entries,
|
||||||
|
this.padding,
|
||||||
RxBool? enabled,
|
RxBool? enabled,
|
||||||
}) : super(enabled: enabled);
|
}) : super(enabled: enabled);
|
||||||
|
|
||||||
@ -490,7 +549,7 @@ class MenuEntrySubMenu<T> extends MenuEntryBase<T> {
|
|||||||
PopupMenuChildrenItem(
|
PopupMenuChildrenItem(
|
||||||
enabled: super.enabled,
|
enabled: super.enabled,
|
||||||
height: conf.height,
|
height: conf.height,
|
||||||
padding: EdgeInsets.zero,
|
padding: padding,
|
||||||
position: mod_menu.PopupMenuPosition.overSide,
|
position: mod_menu.PopupMenuPosition.overSide,
|
||||||
itemBuilder: (BuildContext context) => entries
|
itemBuilder: (BuildContext context) => entries
|
||||||
.map((entry) => entry.build(context, conf))
|
.map((entry) => entry.build(context, conf))
|
||||||
@ -522,10 +581,12 @@ class MenuEntrySubMenu<T> extends MenuEntryBase<T> {
|
|||||||
class MenuEntryButton<T> extends MenuEntryBase<T> {
|
class MenuEntryButton<T> extends MenuEntryBase<T> {
|
||||||
final Widget Function(TextStyle? style) childBuilder;
|
final Widget Function(TextStyle? style) childBuilder;
|
||||||
Function() proc;
|
Function() proc;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
|
||||||
MenuEntryButton({
|
MenuEntryButton({
|
||||||
required this.childBuilder,
|
required this.childBuilder,
|
||||||
required this.proc,
|
required this.proc,
|
||||||
|
this.padding,
|
||||||
dismissOnClicked = false,
|
dismissOnClicked = false,
|
||||||
RxBool? enabled,
|
RxBool? enabled,
|
||||||
}) : super(
|
}) : super(
|
||||||
@ -553,8 +614,10 @@ class MenuEntryButton<T> extends MenuEntryBase<T> {
|
|||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: Container(
|
child: Container(
|
||||||
|
padding: padding,
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
constraints: BoxConstraints(minHeight: conf.height),
|
constraints:
|
||||||
|
BoxConstraints(minHeight: conf.height, maxHeight: conf.height),
|
||||||
child: childBuilder(
|
child: childBuilder(
|
||||||
super.enabled!.value ? enabledStyle : disabledStyle),
|
super.enabled!.value ? enabledStyle : disabledStyle),
|
||||||
),
|
),
|
||||||
|
@ -19,7 +19,7 @@ import './material_mod_popup_menu.dart' as mod_menu;
|
|||||||
class _MenubarTheme {
|
class _MenubarTheme {
|
||||||
static const Color commonColor = MyTheme.accent;
|
static const Color commonColor = MyTheme.accent;
|
||||||
// kMinInteractiveDimension
|
// kMinInteractiveDimension
|
||||||
static const double height = 25.0;
|
static const double height = 20.0;
|
||||||
static const double dividerHeight = 12.0;
|
static const double dividerHeight = 12.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,11 +367,14 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
List<MenuEntryBase<String>> _getControlMenu(BuildContext context) {
|
List<MenuEntryBase<String>> _getControlMenu(BuildContext context) {
|
||||||
final pi = widget.ffi.ffiModel.pi;
|
final pi = widget.ffi.ffiModel.pi;
|
||||||
final perms = widget.ffi.ffiModel.permissions;
|
final perms = widget.ffi.ffiModel.permissions;
|
||||||
|
const EdgeInsets padding = EdgeInsets.only(left: 14.0, right: 5.0);
|
||||||
final List<MenuEntryBase<String>> displayMenu = [];
|
final List<MenuEntryBase<String>> displayMenu = [];
|
||||||
displayMenu.addAll([
|
displayMenu.addAll([
|
||||||
MenuEntryButton<String>(
|
MenuEntryButton<String>(
|
||||||
childBuilder: (TextStyle? style) => Row(
|
childBuilder: (TextStyle? style) => Container(
|
||||||
|
alignment: AlignmentDirectional.center,
|
||||||
|
height: _MenubarTheme.height,
|
||||||
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
translate('OS Password'),
|
translate('OS Password'),
|
||||||
@ -380,18 +383,25 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
|
child: Transform.scale(
|
||||||
|
scale: 0.8,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
icon: const Icon(Icons.edit),
|
icon: const Icon(Icons.edit),
|
||||||
onPressed: () => showSetOSPassword(
|
onPressed: () {
|
||||||
widget.id, false, widget.ffi.dialogManager),
|
if (Navigator.canPop(context)) {
|
||||||
),
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
showSetOSPassword(
|
||||||
|
widget.id, false, widget.ffi.dialogManager);
|
||||||
|
})),
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
),
|
)),
|
||||||
proc: () {
|
proc: () {
|
||||||
showSetOSPassword(widget.id, false, widget.ffi.dialogManager);
|
showSetOSPassword(widget.id, false, widget.ffi.dialogManager);
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
),
|
),
|
||||||
MenuEntryButton<String>(
|
MenuEntryButton<String>(
|
||||||
@ -402,6 +412,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
proc: () {
|
proc: () {
|
||||||
connect(context, widget.id, isFileTransfer: true);
|
connect(context, widget.id, isFileTransfer: true);
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
),
|
),
|
||||||
MenuEntryButton<String>(
|
MenuEntryButton<String>(
|
||||||
@ -409,6 +420,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
translate('TCP Tunneling'),
|
translate('TCP Tunneling'),
|
||||||
style: style,
|
style: style,
|
||||||
),
|
),
|
||||||
|
padding: padding,
|
||||||
proc: () {
|
proc: () {
|
||||||
connect(context, widget.id, isTcpTunneling: true);
|
connect(context, widget.id, isTcpTunneling: true);
|
||||||
},
|
},
|
||||||
@ -427,6 +439,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
proc: () {
|
proc: () {
|
||||||
showAuditDialog(widget.id, widget.ffi.dialogManager);
|
showAuditDialog(widget.id, widget.ffi.dialogManager);
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -443,6 +456,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
proc: () {
|
proc: () {
|
||||||
bind.sessionCtrlAltDel(id: widget.id);
|
bind.sessionCtrlAltDel(id: widget.id);
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -459,6 +473,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
proc: () {
|
proc: () {
|
||||||
showRestartRemoteDevice(pi, widget.id, gFFI.dialogManager);
|
showRestartRemoteDevice(pi, widget.id, gFFI.dialogManager);
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -472,6 +487,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
proc: () {
|
proc: () {
|
||||||
bind.sessionLockScreen(id: widget.id);
|
bind.sessionLockScreen(id: widget.id);
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -489,6 +505,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
value: '${blockInput.value ? "un" : ""}block-input');
|
value: '${blockInput.value ? "un" : ""}block-input');
|
||||||
blockInput.value = !blockInput.value;
|
blockInput.value = !blockInput.value;
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -503,6 +520,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
proc: () {
|
proc: () {
|
||||||
bind.sessionRefresh(id: widget.id);
|
bind.sessionRefresh(id: widget.id);
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -523,6 +541,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
// }
|
// }
|
||||||
// }();
|
// }();
|
||||||
// },
|
// },
|
||||||
|
// padding: padding,
|
||||||
// dismissOnClicked: true,
|
// dismissOnClicked: true,
|
||||||
// ));
|
// ));
|
||||||
// }
|
// }
|
||||||
@ -535,6 +554,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
proc: () {
|
proc: () {
|
||||||
widget.ffi.cursorModel.reset();
|
widget.ffi.cursorModel.reset();
|
||||||
},
|
},
|
||||||
|
padding: padding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -543,14 +563,21 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<MenuEntryBase<String>> _getDisplayMenu(dynamic futureData) {
|
List<MenuEntryBase<String>> _getDisplayMenu(dynamic futureData) {
|
||||||
|
const EdgeInsets padding = EdgeInsets.only(left: 18.0, right: 8.0);
|
||||||
final displayMenu = [
|
final displayMenu = [
|
||||||
MenuEntryRadios<String>(
|
MenuEntryRadios<String>(
|
||||||
text: translate('Ratio'),
|
text: translate('Ratio'),
|
||||||
optionsGetter: () => [
|
optionsGetter: () => [
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(
|
||||||
text: translate('Scale original'), value: 'original'),
|
text: translate('Scale original'),
|
||||||
|
value: 'original',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(
|
||||||
text: translate('Scale adaptive'), value: 'adaptive'),
|
text: translate('Scale adaptive'),
|
||||||
|
value: 'adaptive',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
curOptionGetter: () async {
|
curOptionGetter: () async {
|
||||||
return await bind.sessionGetOption(
|
return await bind.sessionGetOption(
|
||||||
@ -561,15 +588,24 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
await bind.sessionPeerOption(
|
await bind.sessionPeerOption(
|
||||||
id: widget.id, name: "view-style", value: newValue);
|
id: widget.id, name: "view-style", value: newValue);
|
||||||
widget.ffi.canvasModel.updateViewStyle();
|
widget.ffi.canvasModel.updateViewStyle();
|
||||||
}),
|
},
|
||||||
|
padding: padding,
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
MenuEntryDivider<String>(),
|
MenuEntryDivider<String>(),
|
||||||
MenuEntryRadios<String>(
|
MenuEntryRadios<String>(
|
||||||
text: translate('Scroll Style'),
|
text: translate('Scroll Style'),
|
||||||
optionsGetter: () => [
|
optionsGetter: () => [
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(
|
||||||
text: translate('ScrollAuto'), value: 'scrollauto'),
|
text: translate('ScrollAuto'),
|
||||||
|
value: 'scrollauto',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(
|
||||||
text: translate('Scrollbar'), value: 'scrollbar'),
|
text: translate('Scrollbar'),
|
||||||
|
value: 'scrollbar',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
curOptionGetter: () async {
|
curOptionGetter: () async {
|
||||||
return await bind.sessionGetOption(
|
return await bind.sessionGetOption(
|
||||||
@ -580,17 +616,29 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
await bind.sessionPeerOption(
|
await bind.sessionPeerOption(
|
||||||
id: widget.id, name: "scroll-style", value: newValue);
|
id: widget.id, name: "scroll-style", value: newValue);
|
||||||
widget.ffi.canvasModel.updateScrollStyle();
|
widget.ffi.canvasModel.updateScrollStyle();
|
||||||
}),
|
},
|
||||||
|
padding: padding,
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
MenuEntryDivider<String>(),
|
MenuEntryDivider<String>(),
|
||||||
MenuEntryRadios<String>(
|
MenuEntryRadios<String>(
|
||||||
text: translate('Image Quality'),
|
text: translate('Image Quality'),
|
||||||
optionsGetter: () => [
|
optionsGetter: () => [
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(
|
||||||
text: translate('Good image quality'), value: 'best'),
|
text: translate('Good image quality'),
|
||||||
|
value: 'best',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(
|
||||||
text: translate('Balanced'), value: 'balanced'),
|
text: translate('Balanced'),
|
||||||
|
value: 'balanced',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(
|
||||||
text: translate('Optimize reaction time'), value: 'low'),
|
text: translate('Optimize reaction time'),
|
||||||
|
value: 'low',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(
|
||||||
text: translate('Custom'),
|
text: translate('Custom'),
|
||||||
value: 'custom',
|
value: 'custom',
|
||||||
@ -661,7 +709,9 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
msgBoxCommon(widget.ffi.dialogManager, 'Custom Image Quality',
|
msgBoxCommon(widget.ffi.dialogManager, 'Custom Image Quality',
|
||||||
content, [btnCancel]);
|
content, [btnCancel]);
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
padding: padding,
|
||||||
|
),
|
||||||
MenuEntryDivider<String>(),
|
MenuEntryDivider<String>(),
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -680,14 +730,30 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
text: translate('Codec Preference'),
|
text: translate('Codec Preference'),
|
||||||
optionsGetter: () {
|
optionsGetter: () {
|
||||||
final list = [
|
final list = [
|
||||||
MenuEntryRadioOption(text: translate('Auto'), value: 'auto'),
|
MenuEntryRadioOption(
|
||||||
MenuEntryRadioOption(text: 'VP9', value: 'vp9'),
|
text: translate('Auto'),
|
||||||
|
value: 'auto',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
|
MenuEntryRadioOption(
|
||||||
|
text: 'VP9',
|
||||||
|
value: 'vp9',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
),
|
||||||
];
|
];
|
||||||
if (codecs[0]) {
|
if (codecs[0]) {
|
||||||
list.add(MenuEntryRadioOption(text: 'H264', value: 'h264'));
|
list.add(MenuEntryRadioOption(
|
||||||
|
text: 'H264',
|
||||||
|
value: 'h264',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (codecs[1]) {
|
if (codecs[1]) {
|
||||||
list.add(MenuEntryRadioOption(text: 'H265', value: 'h265'));
|
list.add(MenuEntryRadioOption(
|
||||||
|
text: 'H265',
|
||||||
|
value: 'h265',
|
||||||
|
dismissOnClicked: true,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
},
|
},
|
||||||
@ -700,7 +766,10 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
await bind.sessionPeerOption(
|
await bind.sessionPeerOption(
|
||||||
id: widget.id, name: "codec-preference", value: newValue);
|
id: widget.id, name: "codec-preference", value: newValue);
|
||||||
bind.sessionChangePreferCodec(id: widget.id);
|
bind.sessionChangePreferCodec(id: widget.id);
|
||||||
}));
|
},
|
||||||
|
padding: padding,
|
||||||
|
dismissOnClicked: true,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,6 +777,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
displayMenu.add(() {
|
displayMenu.add(() {
|
||||||
final state = ShowRemoteCursorState.find(widget.id);
|
final state = ShowRemoteCursorState.find(widget.id);
|
||||||
return MenuEntrySwitch2<String>(
|
return MenuEntrySwitch2<String>(
|
||||||
|
switchType: SwitchType.scheckbox,
|
||||||
text: translate('Show remote cursor'),
|
text: translate('Show remote cursor'),
|
||||||
getter: () {
|
getter: () {
|
||||||
return state;
|
return state;
|
||||||
@ -716,11 +786,15 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
state.value = v;
|
state.value = v;
|
||||||
await bind.sessionToggleOption(
|
await bind.sessionToggleOption(
|
||||||
id: widget.id, value: 'show-remote-cursor');
|
id: widget.id, value: 'show-remote-cursor');
|
||||||
});
|
},
|
||||||
|
padding: padding,
|
||||||
|
dismissOnClicked: true,
|
||||||
|
);
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/// Show quality monitor
|
/// Show quality monitor
|
||||||
displayMenu.add(MenuEntrySwitch<String>(
|
displayMenu.add(MenuEntrySwitch<String>(
|
||||||
|
switchType: SwitchType.scheckbox,
|
||||||
text: translate('Show quality monitor'),
|
text: translate('Show quality monitor'),
|
||||||
getter: () async {
|
getter: () async {
|
||||||
return bind.sessionGetToggleOptionSync(
|
return bind.sessionGetToggleOptionSync(
|
||||||
@ -730,32 +804,36 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
await bind.sessionToggleOption(
|
await bind.sessionToggleOption(
|
||||||
id: widget.id, value: 'show-quality-monitor');
|
id: widget.id, value: 'show-quality-monitor');
|
||||||
widget.ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id);
|
widget.ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id);
|
||||||
}));
|
},
|
||||||
|
padding: padding,
|
||||||
|
dismissOnClicked: true,
|
||||||
|
));
|
||||||
|
|
||||||
final perms = widget.ffi.ffiModel.permissions;
|
final perms = widget.ffi.ffiModel.permissions;
|
||||||
final pi = widget.ffi.ffiModel.pi;
|
final pi = widget.ffi.ffiModel.pi;
|
||||||
|
|
||||||
if (perms['audio'] != false) {
|
if (perms['audio'] != false) {
|
||||||
displayMenu.add(_createSwitchMenuEntry('Mute', 'disable-audio'));
|
displayMenu
|
||||||
|
.add(_createSwitchMenuEntry('Mute', 'disable-audio', padding, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Platform.isWindows &&
|
if (Platform.isWindows &&
|
||||||
pi.platform == 'Windows' &&
|
pi.platform == 'Windows' &&
|
||||||
perms['file'] != false) {
|
perms['file'] != false) {
|
||||||
displayMenu.add(_createSwitchMenuEntry(
|
displayMenu.add(_createSwitchMenuEntry(
|
||||||
'Allow file copy and paste', 'enable-file-transfer'));
|
'Allow file copy and paste', 'enable-file-transfer', padding, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perms['keyboard'] != false) {
|
if (perms['keyboard'] != false) {
|
||||||
if (perms['clipboard'] != false) {
|
if (perms['clipboard'] != false) {
|
||||||
displayMenu.add(
|
displayMenu.add(_createSwitchMenuEntry(
|
||||||
_createSwitchMenuEntry('Disable clipboard', 'disable-clipboard'));
|
'Disable clipboard', 'disable-clipboard', padding, true));
|
||||||
}
|
}
|
||||||
displayMenu.add(_createSwitchMenuEntry(
|
displayMenu.add(_createSwitchMenuEntry(
|
||||||
'Lock after session end', 'lock-after-session-end'));
|
'Lock after session end', 'lock-after-session-end', padding, true));
|
||||||
if (pi.platform == 'Windows') {
|
if (pi.platform == 'Windows') {
|
||||||
displayMenu.add(MenuEntrySwitch2<String>(
|
displayMenu.add(MenuEntrySwitch2<String>(
|
||||||
dismissOnClicked: true,
|
switchType: SwitchType.scheckbox,
|
||||||
text: translate('Privacy mode'),
|
text: translate('Privacy mode'),
|
||||||
getter: () {
|
getter: () {
|
||||||
return PrivacyModeState.find(widget.id);
|
return PrivacyModeState.find(widget.id);
|
||||||
@ -763,7 +841,10 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
setter: (bool v) async {
|
setter: (bool v) async {
|
||||||
await bind.sessionToggleOption(
|
await bind.sessionToggleOption(
|
||||||
id: widget.id, value: 'privacy-mode');
|
id: widget.id, value: 'privacy-mode');
|
||||||
}));
|
},
|
||||||
|
padding: padding,
|
||||||
|
dismissOnClicked: true,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return displayMenu;
|
return displayMenu;
|
||||||
@ -774,8 +855,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
MenuEntryRadios<String>(
|
MenuEntryRadios<String>(
|
||||||
text: translate('Ratio'),
|
text: translate('Ratio'),
|
||||||
optionsGetter: () => [
|
optionsGetter: () => [
|
||||||
MenuEntryRadioOption(
|
MenuEntryRadioOption(text: translate('Legacy mode'), value: 'legacy'),
|
||||||
text: translate('Legacy mode'), value: 'legacy'),
|
|
||||||
MenuEntryRadioOption(text: translate('Map mode'), value: 'map'),
|
MenuEntryRadioOption(text: translate('Map mode'), value: 'map'),
|
||||||
],
|
],
|
||||||
curOptionGetter: () async {
|
curOptionGetter: () async {
|
||||||
@ -785,21 +865,27 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
await bind.sessionSetKeyboardMode(
|
await bind.sessionSetKeyboardMode(
|
||||||
id: widget.id, keyboardMode: newValue);
|
id: widget.id, keyboardMode: newValue);
|
||||||
widget.ffi.canvasModel.updateViewStyle();
|
widget.ffi.canvasModel.updateViewStyle();
|
||||||
})
|
},
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
return keyboardMenu;
|
return keyboardMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuEntrySwitch<String> _createSwitchMenuEntry(String text, String option) {
|
MenuEntrySwitch<String> _createSwitchMenuEntry(
|
||||||
|
String text, String option, EdgeInsets? padding, bool dismissOnClicked) {
|
||||||
return MenuEntrySwitch<String>(
|
return MenuEntrySwitch<String>(
|
||||||
|
switchType: SwitchType.scheckbox,
|
||||||
text: translate(text),
|
text: translate(text),
|
||||||
getter: () async {
|
getter: () async {
|
||||||
return bind.sessionGetToggleOptionSync(id: widget.id, arg: option);
|
return bind.sessionGetToggleOptionSync(id: widget.id, arg: option);
|
||||||
},
|
},
|
||||||
setter: (bool v) async {
|
setter: (bool v) async {
|
||||||
await bind.sessionToggleOption(id: widget.id, value: option);
|
await bind.sessionToggleOption(id: widget.id, value: option);
|
||||||
});
|
},
|
||||||
|
padding: padding,
|
||||||
|
dismissOnClicked: dismissOnClicked,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user