mobile view mode menu (#8707)
* mobile add view mode menu, disable same menus as desktop * show forbidden cursor when not view mode && no keyboard permission && not show remote cursor * hide keyboard/mouse bottom action when keyboard disabled * fix not listen keyboard permission change * mobile missing changing resolution and http proxy setting, will add if needed. Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
parent
d0a54a6cc6
commit
3a0ece1447
@ -650,6 +650,18 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
v.addAll(toolbarKeyboardToggles(ffi));
|
v.addAll(toolbarKeyboardToggles(ffi));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// view mode (mobile only, desktop is in keyboard menu)
|
||||||
|
if (isMobile && versionCmp(pi.version, '1.2.0') >= 0) {
|
||||||
|
v.add(TToggleMenu(
|
||||||
|
value: ffiModel.viewOnly,
|
||||||
|
onChanged: (value) async {
|
||||||
|
if (value == null) return;
|
||||||
|
await bind.sessionToggleOption(
|
||||||
|
sessionId: ffi.sessionId, value: kOptionToggleViewOnly);
|
||||||
|
ffiModel.setViewOnly(id, value);
|
||||||
|
},
|
||||||
|
child: Text(translate('View Mode'))));
|
||||||
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,12 +277,10 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get keyboard => gFFI.ffiModel.permissions['keyboard'] != false;
|
|
||||||
|
|
||||||
Widget _bottomWidget() => _showGestureHelp
|
Widget _bottomWidget() => _showGestureHelp
|
||||||
? getGestureHelp()
|
? getGestureHelp()
|
||||||
: (_showBar && gFFI.ffiModel.pi.displays.isNotEmpty
|
: (_showBar && gFFI.ffiModel.pi.displays.isNotEmpty
|
||||||
? getBottomAppBar(keyboard)
|
? getBottomAppBar()
|
||||||
: Offstage());
|
: Offstage());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -349,7 +347,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
return Container(
|
return Container(
|
||||||
color: kColorCanvas,
|
color: kColorCanvas,
|
||||||
child: isWebDesktop
|
child: isWebDesktop
|
||||||
? getBodyForDesktopWithListener(keyboard)
|
? getBodyForDesktopWithListener()
|
||||||
: SafeArea(
|
: SafeArea(
|
||||||
child:
|
child:
|
||||||
OrientationBuilder(builder: (ctx, orientation) {
|
OrientationBuilder(builder: (ctx, orientation) {
|
||||||
@ -381,9 +379,9 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget getRawPointerAndKeyBody(Widget child) {
|
Widget getRawPointerAndKeyBody(Widget child) {
|
||||||
final keyboard = gFFI.ffiModel.permissions['keyboard'] != false;
|
final ffiModel = Provider.of<FfiModel>(context);
|
||||||
return RawPointerMouseRegion(
|
return RawPointerMouseRegion(
|
||||||
cursor: keyboard ? SystemMouseCursors.none : MouseCursor.defer,
|
cursor: ffiModel.keyboard ? SystemMouseCursors.none : MouseCursor.defer,
|
||||||
inputModel: inputModel,
|
inputModel: inputModel,
|
||||||
// Disable RawKeyFocusScope before the connecting is established.
|
// Disable RawKeyFocusScope before the connecting is established.
|
||||||
// The "Delete" key on the soft keyboard may be grabbed when inputting the password dialog.
|
// The "Delete" key on the soft keyboard may be grabbed when inputting the password dialog.
|
||||||
@ -396,7 +394,8 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getBottomAppBar(bool keyboard) {
|
Widget getBottomAppBar() {
|
||||||
|
final ffiModel = Provider.of<FfiModel>(context);
|
||||||
return BottomAppBar(
|
return BottomAppBar(
|
||||||
elevation: 10,
|
elevation: 10,
|
||||||
color: MyTheme.accent,
|
color: MyTheme.accent,
|
||||||
@ -422,7 +421,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
] +
|
] +
|
||||||
(isWebDesktop
|
(isWebDesktop || ffiModel.viewOnly || !ffiModel.keyboard
|
||||||
? []
|
? []
|
||||||
: gFFI.ffiModel.isPeerAndroid
|
: gFFI.ffiModel.isPeerAndroid
|
||||||
? [
|
? [
|
||||||
@ -534,19 +533,20 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
if (showCursorPaint) {
|
if (showCursorPaint) {
|
||||||
paints.add(CursorPaint());
|
paints.add(CursorPaint(widget.id));
|
||||||
}
|
}
|
||||||
return paints;
|
return paints;
|
||||||
}()));
|
}()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getBodyForDesktopWithListener(bool keyboard) {
|
Widget getBodyForDesktopWithListener() {
|
||||||
|
final ffiModel = Provider.of<FfiModel>(context);
|
||||||
var paints = <Widget>[ImagePaint()];
|
var paints = <Widget>[ImagePaint()];
|
||||||
if (showCursorPaint) {
|
if (showCursorPaint) {
|
||||||
final cursor = bind.sessionGetToggleOptionSync(
|
final cursor = bind.sessionGetToggleOptionSync(
|
||||||
sessionId: sessionId, arg: 'show-remote-cursor');
|
sessionId: sessionId, arg: 'show-remote-cursor');
|
||||||
if (keyboard || cursor) {
|
if (ffiModel.keyboard || cursor) {
|
||||||
paints.add(CursorPaint());
|
paints.add(CursorPaint(widget.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Container(
|
return Container(
|
||||||
@ -949,22 +949,34 @@ class ImagePaint extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CursorPaint extends StatelessWidget {
|
class CursorPaint extends StatelessWidget {
|
||||||
|
late final String id;
|
||||||
|
CursorPaint(this.id);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final m = Provider.of<CursorModel>(context);
|
final m = Provider.of<CursorModel>(context);
|
||||||
final c = Provider.of<CanvasModel>(context);
|
final c = Provider.of<CanvasModel>(context);
|
||||||
|
final ffiModel = Provider.of<FfiModel>(context);
|
||||||
final adjust = gFFI.cursorModel.adjustForKeyboard();
|
final adjust = gFFI.cursorModel.adjustForKeyboard();
|
||||||
final s = c.scale;
|
final s = c.scale;
|
||||||
double hotx = m.hotx;
|
double hotx = m.hotx;
|
||||||
double hoty = m.hoty;
|
double hoty = m.hoty;
|
||||||
if (m.image == null) {
|
var image = m.image;
|
||||||
|
if (image == null) {
|
||||||
if (preDefaultCursor.image != null) {
|
if (preDefaultCursor.image != null) {
|
||||||
|
image = preDefaultCursor.image;
|
||||||
hotx = preDefaultCursor.image!.width / 2;
|
hotx = preDefaultCursor.image!.width / 2;
|
||||||
hoty = preDefaultCursor.image!.height / 2;
|
hoty = preDefaultCursor.image!.height / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (preForbiddenCursor.image != null &&
|
||||||
final image = m.image ?? preDefaultCursor.image;
|
!ffiModel.viewOnly &&
|
||||||
|
!ffiModel.keyboard &&
|
||||||
|
!ShowRemoteCursorState.find(id).value) {
|
||||||
|
image = preForbiddenCursor.image;
|
||||||
|
hotx = preForbiddenCursor.image!.width / 2;
|
||||||
|
hoty = preForbiddenCursor.image!.height / 2;
|
||||||
|
}
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
return Offstage();
|
return Offstage();
|
||||||
}
|
}
|
||||||
@ -1060,22 +1072,40 @@ void showOptions(
|
|||||||
var codec = (codecRadios.isNotEmpty ? codecRadios[0].groupValue : '').obs;
|
var codec = (codecRadios.isNotEmpty ? codecRadios[0].groupValue : '').obs;
|
||||||
final radios = [
|
final radios = [
|
||||||
for (var e in viewStyleRadios)
|
for (var e in viewStyleRadios)
|
||||||
Obx(() => getRadio<String>(e.child, e.value, viewStyle.value, (v) {
|
Obx(() => getRadio<String>(
|
||||||
e.onChanged?.call(v);
|
e.child,
|
||||||
if (v != null) viewStyle.value = v;
|
e.value,
|
||||||
})),
|
viewStyle.value,
|
||||||
|
e.onChanged != null
|
||||||
|
? (v) {
|
||||||
|
e.onChanged?.call(v);
|
||||||
|
if (v != null) viewStyle.value = v;
|
||||||
|
}
|
||||||
|
: null)),
|
||||||
const Divider(color: MyTheme.border),
|
const Divider(color: MyTheme.border),
|
||||||
for (var e in imageQualityRadios)
|
for (var e in imageQualityRadios)
|
||||||
Obx(() => getRadio<String>(e.child, e.value, imageQuality.value, (v) {
|
Obx(() => getRadio<String>(
|
||||||
e.onChanged?.call(v);
|
e.child,
|
||||||
if (v != null) imageQuality.value = v;
|
e.value,
|
||||||
})),
|
imageQuality.value,
|
||||||
|
e.onChanged != null
|
||||||
|
? (v) {
|
||||||
|
e.onChanged?.call(v);
|
||||||
|
if (v != null) imageQuality.value = v;
|
||||||
|
}
|
||||||
|
: null)),
|
||||||
const Divider(color: MyTheme.border),
|
const Divider(color: MyTheme.border),
|
||||||
for (var e in codecRadios)
|
for (var e in codecRadios)
|
||||||
Obx(() => getRadio<String>(e.child, e.value, codec.value, (v) {
|
Obx(() => getRadio<String>(
|
||||||
e.onChanged?.call(v);
|
e.child,
|
||||||
if (v != null) codec.value = v;
|
e.value,
|
||||||
})),
|
codec.value,
|
||||||
|
e.onChanged != null
|
||||||
|
? (v) {
|
||||||
|
e.onChanged?.call(v);
|
||||||
|
if (v != null) codec.value = v;
|
||||||
|
}
|
||||||
|
: null)),
|
||||||
if (codecRadios.isNotEmpty) const Divider(color: MyTheme.border),
|
if (codecRadios.isNotEmpty) const Divider(color: MyTheme.border),
|
||||||
];
|
];
|
||||||
final rxCursorToggleValues = cursorToggles.map((e) => e.value.obs).toList();
|
final rxCursorToggleValues = cursorToggles.map((e) => e.value.obs).toList();
|
||||||
@ -1086,10 +1116,12 @@ void showOptions(
|
|||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
value: rxCursorToggleValues[e.key].value,
|
value: rxCursorToggleValues[e.key].value,
|
||||||
onChanged: (v) {
|
onChanged: e.value.onChanged != null
|
||||||
e.value.onChanged?.call(v);
|
? (v) {
|
||||||
if (v != null) rxCursorToggleValues[e.key].value = v;
|
e.value.onChanged?.call(v);
|
||||||
},
|
if (v != null) rxCursorToggleValues[e.key].value = v;
|
||||||
|
}
|
||||||
|
: null,
|
||||||
title: e.value.child)))
|
title: e.value.child)))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
@ -1101,10 +1133,12 @@ void showOptions(
|
|||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
value: rxToggleValues[e.key].value,
|
value: rxToggleValues[e.key].value,
|
||||||
onChanged: (v) {
|
onChanged: e.value.onChanged != null
|
||||||
e.value.onChanged?.call(v);
|
? (v) {
|
||||||
if (v != null) rxToggleValues[e.key].value = v;
|
e.value.onChanged?.call(v);
|
||||||
},
|
if (v != null) rxToggleValues[e.key].value = v;
|
||||||
|
}
|
||||||
|
: null,
|
||||||
title: e.value.child)))
|
title: e.value.child)))
|
||||||
.toList();
|
.toList();
|
||||||
final toggles = [
|
final toggles = [
|
||||||
|
@ -192,7 +192,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
_permissions[k] = v == 'true';
|
_permissions[k] = v == 'true';
|
||||||
});
|
});
|
||||||
// Only inited at remote page
|
// Only inited at remote page
|
||||||
if (desktopType == DesktopType.remote) {
|
if (parent.target?.connType == ConnType.defaultConn) {
|
||||||
KeyboardEnabledState.find(id).value = _permissions['keyboard'] != false;
|
KeyboardEnabledState.find(id).value = _permissions['keyboard'] != false;
|
||||||
}
|
}
|
||||||
debugPrint('updatePermission: $_permissions');
|
debugPrint('updatePermission: $_permissions');
|
||||||
@ -1726,7 +1726,7 @@ class PredefinedCursor {
|
|||||||
_image2 = img2.decodePng(base64Decode(png));
|
_image2 = img2.decodePng(base64Decode(png));
|
||||||
if (_image2 != null) {
|
if (_image2 != null) {
|
||||||
// The png type of forbidden cursor image is `PngColorType.indexed`.
|
// The png type of forbidden cursor image is `PngColorType.indexed`.
|
||||||
if (isWindows && id == kPreForbiddenCursorId) {
|
if (id == kPreForbiddenCursorId) {
|
||||||
_image2 = _image2!.convert(format: img2.Format.uint8, numChannels: 4);
|
_image2 = _image2!.convert(format: img2.Format.uint8, numChannels: 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1614,5 +1614,13 @@ class RustdeskImpl {
|
|||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mainHasValidBotSync({dynamic hint}) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> mainVerifyBot({required String token, dynamic hint}) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user