more menu items
This commit is contained in:
		
							parent
							
								
									98434eb11e
								
							
						
					
					
						commit
						3e7c20f303
					
				@ -16,6 +16,7 @@ class FfiModel with ChangeNotifier {
 | 
			
		||||
  var _decoding = false;
 | 
			
		||||
  bool _waitForImage;
 | 
			
		||||
  bool _initialized = false;
 | 
			
		||||
  var _inputBlocked = false;
 | 
			
		||||
  final _permissions = Map<String, bool>();
 | 
			
		||||
  bool _secure;
 | 
			
		||||
  bool _direct;
 | 
			
		||||
@ -26,6 +27,11 @@ class FfiModel with ChangeNotifier {
 | 
			
		||||
  get secure => _secure;
 | 
			
		||||
  get direct => _direct;
 | 
			
		||||
  get pi => _pi;
 | 
			
		||||
  get inputBlocked => _inputBlocked;
 | 
			
		||||
 | 
			
		||||
  set inputBlocked(v) {
 | 
			
		||||
    _inputBlocked = v;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FfiModel() {
 | 
			
		||||
    Translator.call = translate;
 | 
			
		||||
@ -54,6 +60,7 @@ class FfiModel with ChangeNotifier {
 | 
			
		||||
    _waitForImage = false;
 | 
			
		||||
    _secure = null;
 | 
			
		||||
    _direct = null;
 | 
			
		||||
    _inputBlocked = false;
 | 
			
		||||
    clearPermissions();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -79,6 +86,7 @@ class FfiModel with ChangeNotifier {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void clearPermissions() {
 | 
			
		||||
    _inputBlocked = false;
 | 
			
		||||
    _permissions.clear();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -266,48 +266,63 @@ class _RemotePageState extends State<RemotePage> {
 | 
			
		||||
                    mainAxisSize: MainAxisSize.max,
 | 
			
		||||
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                    children: <Widget>[
 | 
			
		||||
                      Row(children: [
 | 
			
		||||
                        IconButton(
 | 
			
		||||
                          color: Colors.white,
 | 
			
		||||
                          icon: Icon(Icons.clear),
 | 
			
		||||
                          onPressed: () {
 | 
			
		||||
                            close();
 | 
			
		||||
                          },
 | 
			
		||||
                        ),
 | 
			
		||||
                        IconButton(
 | 
			
		||||
                            color: Colors.white,
 | 
			
		||||
                            icon: Icon(Icons.keyboard),
 | 
			
		||||
                            onPressed: openKeyboard),
 | 
			
		||||
                        IconButton(
 | 
			
		||||
                          color: Colors.white,
 | 
			
		||||
                          icon: Icon(Icons.tv),
 | 
			
		||||
                          onPressed: () {
 | 
			
		||||
                            setState(() => _showEdit = false);
 | 
			
		||||
                            showOptions(context);
 | 
			
		||||
                          },
 | 
			
		||||
                        ),
 | 
			
		||||
                        Container(
 | 
			
		||||
                            color: _mouseTools ? Colors.blue[500] : null,
 | 
			
		||||
                            child: IconButton(
 | 
			
		||||
                              color: Colors.white,
 | 
			
		||||
                              icon: Icon(Icons.mouse),
 | 
			
		||||
                              onPressed: () {
 | 
			
		||||
                                setState(() {
 | 
			
		||||
                                  _mouseTools = !_mouseTools;
 | 
			
		||||
                                  resetTool();
 | 
			
		||||
                                  if (_mouseTools) _drag = true;
 | 
			
		||||
                                });
 | 
			
		||||
                              },
 | 
			
		||||
                            )),
 | 
			
		||||
                        IconButton(
 | 
			
		||||
                          color: Colors.white,
 | 
			
		||||
                          icon: Icon(Icons.more_vert),
 | 
			
		||||
                          onPressed: () {
 | 
			
		||||
                            setState(() => _showEdit = false);
 | 
			
		||||
                            showActions(context);
 | 
			
		||||
                          },
 | 
			
		||||
                        ),
 | 
			
		||||
                      ]),
 | 
			
		||||
                      Row(
 | 
			
		||||
                          children: <Widget>[
 | 
			
		||||
                                IconButton(
 | 
			
		||||
                                  color: Colors.white,
 | 
			
		||||
                                  icon: Icon(Icons.clear),
 | 
			
		||||
                                  onPressed: () {
 | 
			
		||||
                                    close();
 | 
			
		||||
                                  },
 | 
			
		||||
                                )
 | 
			
		||||
                              ] +
 | 
			
		||||
                              (isDesktop
 | 
			
		||||
                                  ? []
 | 
			
		||||
                                  : [
 | 
			
		||||
                                      IconButton(
 | 
			
		||||
                                          color: Colors.white,
 | 
			
		||||
                                          icon: Icon(Icons.keyboard),
 | 
			
		||||
                                          onPressed: openKeyboard)
 | 
			
		||||
                                    ]) +
 | 
			
		||||
                              <Widget>[
 | 
			
		||||
                                IconButton(
 | 
			
		||||
                                  color: Colors.white,
 | 
			
		||||
                                  icon: Icon(Icons.tv),
 | 
			
		||||
                                  onPressed: () {
 | 
			
		||||
                                    setState(() => _showEdit = false);
 | 
			
		||||
                                    showOptions(context);
 | 
			
		||||
                                  },
 | 
			
		||||
                                )
 | 
			
		||||
                              ] +
 | 
			
		||||
                              (isDesktop
 | 
			
		||||
                                  ? []
 | 
			
		||||
                                  : [
 | 
			
		||||
                                      Container(
 | 
			
		||||
                                          color: _mouseTools
 | 
			
		||||
                                              ? Colors.blue[500]
 | 
			
		||||
                                              : null,
 | 
			
		||||
                                          child: IconButton(
 | 
			
		||||
                                            color: Colors.white,
 | 
			
		||||
                                            icon: Icon(Icons.mouse),
 | 
			
		||||
                                            onPressed: () {
 | 
			
		||||
                                              setState(() {
 | 
			
		||||
                                                _mouseTools = !_mouseTools;
 | 
			
		||||
                                                resetTool();
 | 
			
		||||
                                                if (_mouseTools) _drag = true;
 | 
			
		||||
                                              });
 | 
			
		||||
                                            },
 | 
			
		||||
                                          ))
 | 
			
		||||
                                    ]) +
 | 
			
		||||
                              <Widget>[
 | 
			
		||||
                                IconButton(
 | 
			
		||||
                                  color: Colors.white,
 | 
			
		||||
                                  icon: Icon(Icons.more_vert),
 | 
			
		||||
                                  onPressed: () {
 | 
			
		||||
                                    setState(() => _showEdit = false);
 | 
			
		||||
                                    showActions(context);
 | 
			
		||||
                                  },
 | 
			
		||||
                                ),
 | 
			
		||||
                              ]),
 | 
			
		||||
                      IconButton(
 | 
			
		||||
                          color: Colors.white,
 | 
			
		||||
                          icon: Icon(Icons.expand_more),
 | 
			
		||||
@ -418,15 +433,12 @@ class _RemotePageState extends State<RemotePage> {
 | 
			
		||||
    final x = 120.0;
 | 
			
		||||
    final y = size.height;
 | 
			
		||||
    final more = <PopupMenuItem<String>>[];
 | 
			
		||||
    if (FFI.ffiModel.pi.version.isNotEmpty) {
 | 
			
		||||
    final pi = FFI.ffiModel.pi;
 | 
			
		||||
    final perms = FFI.ffiModel.permissions;
 | 
			
		||||
    if (pi.version.isNotEmpty) {
 | 
			
		||||
      more.add(PopupMenuItem<String>(
 | 
			
		||||
          child: Text(translate('Refresh')), value: 'refresh'));
 | 
			
		||||
    }
 | 
			
		||||
    if (FFI.ffiModel.permissions['keyboard'] != false &&
 | 
			
		||||
        FFI.ffiModel.permissions['clipboard'] != false) {
 | 
			
		||||
      more.add(PopupMenuItem<String>(
 | 
			
		||||
          child: Text(translate('Paste')), value: 'paste'));
 | 
			
		||||
    }
 | 
			
		||||
    more.add(PopupMenuItem<String>(
 | 
			
		||||
        child: Row(
 | 
			
		||||
            children: ([
 | 
			
		||||
@ -441,38 +453,57 @@ class _RemotePageState extends State<RemotePage> {
 | 
			
		||||
          )
 | 
			
		||||
        ])),
 | 
			
		||||
        value: 'enter_os_password'));
 | 
			
		||||
    more.add(PopupMenuItem<String>(
 | 
			
		||||
        child: Row(
 | 
			
		||||
            children: ([
 | 
			
		||||
          Container(width: 100.0, child: Text(translate('Touch mode'))),
 | 
			
		||||
          Padding(padding: EdgeInsets.symmetric(horizontal: 16.0)),
 | 
			
		||||
          Icon(
 | 
			
		||||
              _touchMode
 | 
			
		||||
                  ? Icons.check_box_outlined
 | 
			
		||||
                  : Icons.check_box_outline_blank,
 | 
			
		||||
              color: MyTheme.accent)
 | 
			
		||||
        ])),
 | 
			
		||||
        value: 'touch_mode'));
 | 
			
		||||
    more.add(PopupMenuItem<String>(
 | 
			
		||||
        child: Text(translate('Reset canvas')), value: 'reset_canvas'));
 | 
			
		||||
    if (!isDesktop) {
 | 
			
		||||
      if (perms['keyboard'] != false && perms['clipboard'] != false) {
 | 
			
		||||
        more.add(PopupMenuItem<String>(
 | 
			
		||||
            child: Text(translate('Paste')), value: 'paste'));
 | 
			
		||||
      }
 | 
			
		||||
      more.add(PopupMenuItem<String>(
 | 
			
		||||
          child: Row(
 | 
			
		||||
              children: ([
 | 
			
		||||
            Container(width: 100.0, child: Text(translate('Touch mode'))),
 | 
			
		||||
            Padding(padding: EdgeInsets.symmetric(horizontal: 16.0)),
 | 
			
		||||
            Icon(
 | 
			
		||||
                _touchMode
 | 
			
		||||
                    ? Icons.check_box_outlined
 | 
			
		||||
                    : Icons.check_box_outline_blank,
 | 
			
		||||
                color: MyTheme.accent)
 | 
			
		||||
          ])),
 | 
			
		||||
          value: 'touch_mode'));
 | 
			
		||||
      more.add(PopupMenuItem<String>(
 | 
			
		||||
          child: Text(translate('Reset canvas')), value: 'reset_canvas'));
 | 
			
		||||
    }
 | 
			
		||||
    if (perms['keyboard'] != false) {
 | 
			
		||||
      if (pi.platform == 'Linux' || pi.sasEnabled) {
 | 
			
		||||
        more.add(PopupMenuItem<String>(
 | 
			
		||||
            child: Text(translate('Insert') + ' Ctrl + Alt + Del'),
 | 
			
		||||
            value: 'cad'));
 | 
			
		||||
      }
 | 
			
		||||
      more.add(PopupMenuItem<String>(
 | 
			
		||||
          child: Text(translate('Insert Lock')), value: 'lock'));
 | 
			
		||||
      if (pi.platform == 'Windows' &&
 | 
			
		||||
          FFI.getByName('toggle_option', 'privacy-mode') != 'true') {
 | 
			
		||||
        more.add(PopupMenuItem<String>(
 | 
			
		||||
            child: Text(translate(
 | 
			
		||||
                (FFI.ffiModel.inputBlocked ? 'Unb' : 'B') + 'lock user input')),
 | 
			
		||||
            value: 'block-input'));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    () async {
 | 
			
		||||
      var value = await showMenu(
 | 
			
		||||
        context: context,
 | 
			
		||||
        position: RelativeRect.fromLTRB(x, y, x, y),
 | 
			
		||||
        items: [
 | 
			
		||||
              PopupMenuItem<String>(
 | 
			
		||||
                  child: Text(translate('Insert') + ' Ctrl + Alt + Del'),
 | 
			
		||||
                  value: 'cad'),
 | 
			
		||||
              PopupMenuItem<String>(
 | 
			
		||||
                  child: Text(translate('Insert Lock')), value: 'lock'),
 | 
			
		||||
            ] +
 | 
			
		||||
            more,
 | 
			
		||||
        items: more,
 | 
			
		||||
        elevation: 8,
 | 
			
		||||
      );
 | 
			
		||||
      if (value == 'cad') {
 | 
			
		||||
        FFI.setByName('ctrl_alt_del');
 | 
			
		||||
      } else if (value == 'lock') {
 | 
			
		||||
        FFI.setByName('lock_screen');
 | 
			
		||||
      } else if (value == 'block-input') {
 | 
			
		||||
        FFI.setByName('toggle_option',
 | 
			
		||||
            (FFI.ffiModel.inputBlocked ? 'un' : '') + 'block-inpu');
 | 
			
		||||
        FFI.ffiModel.inputBlocked = !FFI.ffiModel.inputBlocked;
 | 
			
		||||
      } else if (value == 'refresh') {
 | 
			
		||||
        FFI.setByName('refresh');
 | 
			
		||||
      } else if (value == 'paste') {
 | 
			
		||||
@ -796,9 +827,36 @@ void wrongPasswordDialog(String id, BuildContext context) {
 | 
			
		||||
          ]));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CheckboxListTile getToggle(
 | 
			
		||||
    void Function(void Function()) setState, option, name) {
 | 
			
		||||
  return CheckboxListTile(
 | 
			
		||||
      value: FFI.getByName('toggle_option', option) == 'true',
 | 
			
		||||
      onChanged: (v) {
 | 
			
		||||
        setState(() {
 | 
			
		||||
          FFI.setByName('toggle_option', option);
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
      dense: true,
 | 
			
		||||
      title: Text(translate(name)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RadioListTile<String> getRadio(String name, String toValue, String curValue,
 | 
			
		||||
    void Function(String) onChange) {
 | 
			
		||||
  return RadioListTile<String>(
 | 
			
		||||
    controlAffinity: ListTileControlAffinity.trailing,
 | 
			
		||||
    title: Text(translate(name)),
 | 
			
		||||
    value: toValue,
 | 
			
		||||
    groupValue: curValue,
 | 
			
		||||
    onChanged: onChange,
 | 
			
		||||
    dense: true,
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void showOptions(BuildContext context) {
 | 
			
		||||
  String quality = FFI.getByName('image_quality');
 | 
			
		||||
  if (quality == '') quality = 'balanced';
 | 
			
		||||
  String viewStyle = FFI.getByName('peer_option', 'view-style');
 | 
			
		||||
  if (viewStyle == '') viewStyle = 'original';
 | 
			
		||||
  var displays = <Widget>[];
 | 
			
		||||
  final pi = FFI.ffiModel.pi;
 | 
			
		||||
  final image = FFI.ffiModel.getConnectionImage();
 | 
			
		||||
@ -835,82 +893,56 @@ void showOptions(BuildContext context) {
 | 
			
		||||
  if (displays.isNotEmpty) {
 | 
			
		||||
    displays.add(Divider(color: MyTheme.border));
 | 
			
		||||
  }
 | 
			
		||||
  final perms = FFI.ffiModel.permissions;
 | 
			
		||||
  showAlertDialog(context, (setState) {
 | 
			
		||||
    final more = <Widget>[];
 | 
			
		||||
    if (FFI.ffiModel.permissions['audio'] != false) {
 | 
			
		||||
      more.add(CheckboxListTile(
 | 
			
		||||
          value: FFI.getByName('toggle_option', 'disable-audio') == 'true',
 | 
			
		||||
          onChanged: (v) {
 | 
			
		||||
            setState(() {
 | 
			
		||||
              FFI.setByName('toggle_option', 'disable-audio');
 | 
			
		||||
            });
 | 
			
		||||
          },
 | 
			
		||||
          title: Text(translate('Mute'))));
 | 
			
		||||
    if (perms['audio'] != false) {
 | 
			
		||||
      more.add(getToggle(setState, 'disable-audio', 'Mute'));
 | 
			
		||||
    }
 | 
			
		||||
    if (FFI.ffiModel.permissions['keyboard'] != false) {
 | 
			
		||||
      more.add(CheckboxListTile(
 | 
			
		||||
          value: FFI.getByName('toggle_option', 'lock-after-session-end') ==
 | 
			
		||||
              'true',
 | 
			
		||||
          onChanged: (v) {
 | 
			
		||||
            setState(() {
 | 
			
		||||
              FFI.setByName('toggle_option', 'lock-after-session-end');
 | 
			
		||||
            });
 | 
			
		||||
          },
 | 
			
		||||
          title: Text(translate('Lock after session end'))));
 | 
			
		||||
    if (perms['keyboard'] != false) {
 | 
			
		||||
      if (perms['clipboard'] != false)
 | 
			
		||||
        more.add(getToggle(setState, 'disable-clipboard', 'Disable clipboard'));
 | 
			
		||||
      more.add(getToggle(
 | 
			
		||||
          setState, 'lock-after-session-end', 'Lock after session end'));
 | 
			
		||||
      if (pi.platform == 'Windows') {
 | 
			
		||||
        more.add(getToggle(setState, 'privacy-mode', 'Privacy mode'));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    var setQuality = (String value) {
 | 
			
		||||
      setState(() {
 | 
			
		||||
        quality = value;
 | 
			
		||||
        FFI.setByName('image_quality', value);
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
    var setViewStyle = (String value) {
 | 
			
		||||
      setState(() {
 | 
			
		||||
        viewStyle = value;
 | 
			
		||||
        FFI.setByName(
 | 
			
		||||
            'peer_option', '{"name": "view-style", "value": "$value"}');
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
    return Tuple3(
 | 
			
		||||
        null,
 | 
			
		||||
        Column(
 | 
			
		||||
            mainAxisSize: MainAxisSize.min,
 | 
			
		||||
            children: displays +
 | 
			
		||||
                (isDesktop
 | 
			
		||||
                    ? <Widget>[
 | 
			
		||||
                        getRadio(
 | 
			
		||||
                            'Original', 'original', viewStyle, setViewStyle),
 | 
			
		||||
                        getRadio('Shrink', 'shrink', viewStyle, setViewStyle),
 | 
			
		||||
                        getRadio('Stretch', 'stretch', viewStyle, setViewStyle),
 | 
			
		||||
                        Divider(color: MyTheme.border),
 | 
			
		||||
                      ]
 | 
			
		||||
                    : {}) +
 | 
			
		||||
                <Widget>[
 | 
			
		||||
                  RadioListTile<String>(
 | 
			
		||||
                    controlAffinity: ListTileControlAffinity.trailing,
 | 
			
		||||
                    title: Text(translate('Good image quality')),
 | 
			
		||||
                    value: 'best',
 | 
			
		||||
                    groupValue: quality,
 | 
			
		||||
                    onChanged: (String value) {
 | 
			
		||||
                      setState(() {
 | 
			
		||||
                        quality = value;
 | 
			
		||||
                        FFI.setByName('image_quality', value);
 | 
			
		||||
                      });
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                  RadioListTile<String>(
 | 
			
		||||
                    controlAffinity: ListTileControlAffinity.trailing,
 | 
			
		||||
                    title: Text(translate('Balanced')),
 | 
			
		||||
                    value: 'balanced',
 | 
			
		||||
                    groupValue: quality,
 | 
			
		||||
                    onChanged: (String value) {
 | 
			
		||||
                      setState(() {
 | 
			
		||||
                        quality = value;
 | 
			
		||||
                        FFI.setByName('image_quality', value);
 | 
			
		||||
                      });
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                  RadioListTile<String>(
 | 
			
		||||
                    controlAffinity: ListTileControlAffinity.trailing,
 | 
			
		||||
                    title: Text(translate('Optimize reaction time')),
 | 
			
		||||
                    value: 'low',
 | 
			
		||||
                    groupValue: quality,
 | 
			
		||||
                    onChanged: (String value) {
 | 
			
		||||
                      setState(() {
 | 
			
		||||
                        quality = value;
 | 
			
		||||
                        FFI.setByName('image_quality', value);
 | 
			
		||||
                      });
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                  getRadio('Good image quality', 'best', quality, setQuality),
 | 
			
		||||
                  getRadio('Balanced', 'balanced', quality, setQuality),
 | 
			
		||||
                  getRadio(
 | 
			
		||||
                      'Optimize reaction time', 'low', quality, setQuality),
 | 
			
		||||
                  Divider(color: MyTheme.border),
 | 
			
		||||
                  CheckboxListTile(
 | 
			
		||||
                      value: FFI.getByName(
 | 
			
		||||
                              'toggle_option', 'show-remote-cursor') ==
 | 
			
		||||
                          'true',
 | 
			
		||||
                      onChanged: (v) {
 | 
			
		||||
                        setState(() {
 | 
			
		||||
                          FFI.setByName('toggle_option', 'show-remote-cursor');
 | 
			
		||||
                        });
 | 
			
		||||
                      },
 | 
			
		||||
                      title: Text(translate('Show remote cursor'))),
 | 
			
		||||
                  getToggle(
 | 
			
		||||
                      setState, 'show-remote-cursor', 'Show remote cursor'),
 | 
			
		||||
                ] +
 | 
			
		||||
                more),
 | 
			
		||||
        null);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user