Merge pull request #3183 from Heap-Hop/opt_keytools
Opt keytools [mobile]
This commit is contained in:
commit
9f4437b9bd
@ -7,6 +7,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
import 'package:flutter_hbb/mobile/widgets/gesture_help.dart';
|
import 'package:flutter_hbb/mobile/widgets/gesture_help.dart';
|
||||||
import 'package:flutter_hbb/models/chat_model.dart';
|
import 'package:flutter_hbb/models/chat_model.dart';
|
||||||
|
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
||||||
import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
|
import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
@ -33,17 +34,16 @@ class RemotePage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RemotePageState extends State<RemotePage> {
|
class _RemotePageState extends State<RemotePage> {
|
||||||
Timer? _interval;
|
|
||||||
Timer? _timer;
|
Timer? _timer;
|
||||||
bool _showBar = !isWebDesktop;
|
bool _showBar = !isWebDesktop;
|
||||||
double _bottom = 0;
|
bool _showGestureHelp = false;
|
||||||
String _value = '';
|
String _value = '';
|
||||||
double _scale = 1;
|
double _scale = 1;
|
||||||
double _mouseScrollIntegral = 0; // mouse scroll speed controller
|
double _mouseScrollIntegral = 0; // mouse scroll speed controller
|
||||||
Orientation? _currentOrientation;
|
Orientation? _currentOrientation;
|
||||||
|
|
||||||
var _more = true;
|
final keyboardVisibilityController = KeyboardVisibilityController();
|
||||||
var _fn = false;
|
late final StreamSubscription<bool> keyboardSubscription;
|
||||||
final FocusNode _mobileFocusNode = FocusNode();
|
final FocusNode _mobileFocusNode = FocusNode();
|
||||||
final FocusNode _physicalFocusNode = FocusNode();
|
final FocusNode _physicalFocusNode = FocusNode();
|
||||||
var _showEdit = false; // use soft keyboard
|
var _showEdit = false; // use soft keyboard
|
||||||
@ -58,14 +58,14 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
|
||||||
gFFI.dialogManager
|
gFFI.dialogManager
|
||||||
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
||||||
_interval =
|
|
||||||
Timer.periodic(Duration(milliseconds: 30), (timer) => interval());
|
|
||||||
});
|
});
|
||||||
Wakelock.enable();
|
Wakelock.enable();
|
||||||
_physicalFocusNode.requestFocus();
|
_physicalFocusNode.requestFocus();
|
||||||
gFFI.ffiModel.updateEventListener(widget.id);
|
gFFI.ffiModel.updateEventListener(widget.id);
|
||||||
gFFI.inputModel.listenToMouse(true);
|
gFFI.inputModel.listenToMouse(true);
|
||||||
gFFI.qualityMonitorModel.checkShowQualityMonitor(widget.id);
|
gFFI.qualityMonitorModel.checkShowQualityMonitor(widget.id);
|
||||||
|
keyboardSubscription =
|
||||||
|
keyboardVisibilityController.onChange.listen(onSoftKeyboardChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -76,47 +76,26 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
_mobileFocusNode.dispose();
|
_mobileFocusNode.dispose();
|
||||||
_physicalFocusNode.dispose();
|
_physicalFocusNode.dispose();
|
||||||
gFFI.close();
|
gFFI.close();
|
||||||
_interval?.cancel();
|
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
gFFI.dialogManager.dismissAll();
|
gFFI.dialogManager.dismissAll();
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
overlays: SystemUiOverlay.values);
|
overlays: SystemUiOverlay.values);
|
||||||
Wakelock.disable();
|
Wakelock.disable();
|
||||||
|
keyboardSubscription.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetTool() {
|
void onSoftKeyboardChanged(bool visible) {
|
||||||
inputModel.resetModifiers();
|
if (!visible) {
|
||||||
}
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
|
||||||
|
// [pi.version.isNotEmpty] -> check ready or not, avoid login without soft-keyboard
|
||||||
bool isKeyboardShown() {
|
if (gFFI.chatModel.chatWindowOverlayEntry == null &&
|
||||||
return _bottom >= 100;
|
gFFI.ffiModel.pi.version.isNotEmpty) {
|
||||||
}
|
gFFI.invokeMethod("enable_soft_keyboard", false);
|
||||||
|
}
|
||||||
// crash on web before widget initiated.
|
|
||||||
void intervalUnsafe() {
|
|
||||||
var v = MediaQuery.of(context).viewInsets.bottom;
|
|
||||||
if (v != _bottom) {
|
|
||||||
resetTool();
|
|
||||||
setState(() {
|
|
||||||
_bottom = v;
|
|
||||||
if (v < 100) {
|
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
|
||||||
overlays: []);
|
|
||||||
// [pi.version.isNotEmpty] -> check ready or not, avoid login without soft-keyboard
|
|
||||||
if (gFFI.chatModel.chatWindowOverlayEntry == null &&
|
|
||||||
gFFI.ffiModel.pi.version.isNotEmpty) {
|
|
||||||
gFFI.invokeMethod("enable_soft_keyboard", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
// update for Scaffold
|
||||||
|
setState(() {});
|
||||||
void interval() {
|
|
||||||
try {
|
|
||||||
intervalUnsafe();
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle mobile virtual keyboard
|
// handle mobile virtual keyboard
|
||||||
@ -219,8 +198,9 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final pi = Provider.of<FfiModel>(context).pi;
|
final pi = Provider.of<FfiModel>(context).pi;
|
||||||
final hideKeyboard = isKeyboardShown() && _showEdit;
|
final keyboardIsVisible =
|
||||||
final showActionButton = !_showBar || hideKeyboard;
|
keyboardVisibilityController.isVisible && _showEdit;
|
||||||
|
final showActionButton = !_showBar || keyboardIsVisible || _showGestureHelp;
|
||||||
final keyboard = gFFI.ffiModel.permissions['keyboard'] != false;
|
final keyboard = gFFI.ffiModel.permissions['keyboard'] != false;
|
||||||
|
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
@ -230,33 +210,39 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
},
|
},
|
||||||
child: getRawPointerAndKeyBody(Scaffold(
|
child: getRawPointerAndKeyBody(Scaffold(
|
||||||
// workaround for https://github.com/rustdesk/rustdesk/issues/3131
|
// workaround for https://github.com/rustdesk/rustdesk/issues/3131
|
||||||
floatingActionButtonLocation: hideKeyboard
|
floatingActionButtonLocation: keyboardIsVisible
|
||||||
? FABLocation(FloatingActionButtonLocation.endFloat, 0, -35)
|
? FABLocation(FloatingActionButtonLocation.endFloat, 0, -35)
|
||||||
: null,
|
: null,
|
||||||
floatingActionButton: !showActionButton
|
floatingActionButton: !showActionButton
|
||||||
? null
|
? null
|
||||||
: FloatingActionButton(
|
: FloatingActionButton(
|
||||||
mini: !hideKeyboard,
|
mini: !keyboardIsVisible,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
hideKeyboard ? Icons.expand_more : Icons.expand_less,
|
(keyboardIsVisible || _showGestureHelp)
|
||||||
|
? Icons.expand_more
|
||||||
|
: Icons.expand_less,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
backgroundColor: MyTheme.accent,
|
backgroundColor: MyTheme.accent,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (hideKeyboard) {
|
if (keyboardIsVisible) {
|
||||||
_showEdit = false;
|
_showEdit = false;
|
||||||
gFFI.invokeMethod("enable_soft_keyboard", false);
|
gFFI.invokeMethod("enable_soft_keyboard", false);
|
||||||
_mobileFocusNode.unfocus();
|
_mobileFocusNode.unfocus();
|
||||||
_physicalFocusNode.requestFocus();
|
_physicalFocusNode.requestFocus();
|
||||||
|
} else if (_showGestureHelp) {
|
||||||
|
_showGestureHelp = false;
|
||||||
} else {
|
} else {
|
||||||
_showBar = !_showBar;
|
_showBar = !_showBar;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
bottomNavigationBar: _showBar && pi.displays.isNotEmpty
|
bottomNavigationBar: _showGestureHelp
|
||||||
? getBottomAppBar(keyboard)
|
? getGestureHelp()
|
||||||
: null,
|
: (_showBar && pi.displays.isNotEmpty
|
||||||
|
? getBottomAppBar(keyboard)
|
||||||
|
: null),
|
||||||
body: Overlay(
|
body: Overlay(
|
||||||
initialEntries: [
|
initialEntries: [
|
||||||
OverlayEntry(builder: (context) {
|
OverlayEntry(builder: (context) {
|
||||||
@ -346,7 +332,8 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
icon: Icon(gFFI.ffiModel.touchMode
|
icon: Icon(gFFI.ffiModel.touchMode
|
||||||
? Icons.touch_app
|
? Icons.touch_app
|
||||||
: Icons.mouse),
|
: Icons.mouse),
|
||||||
onPressed: changeTouchMode,
|
onPressed: () => setState(
|
||||||
|
() => _showGestureHelp = !_showGestureHelp),
|
||||||
),
|
),
|
||||||
]) +
|
]) +
|
||||||
(isWeb
|
(isWeb
|
||||||
@ -498,6 +485,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget getBodyForMobile() {
|
Widget getBodyForMobile() {
|
||||||
|
final keyboardIsVisible = keyboardVisibilityController.isVisible;
|
||||||
return Container(
|
return Container(
|
||||||
color: MyTheme.canvasColor,
|
color: MyTheme.canvasColor,
|
||||||
child: Stack(children: () {
|
child: Stack(children: () {
|
||||||
@ -508,7 +496,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
right: 10,
|
right: 10,
|
||||||
child: QualityMonitor(gFFI.qualityMonitorModel),
|
child: QualityMonitor(gFFI.qualityMonitorModel),
|
||||||
),
|
),
|
||||||
getHelpTools(),
|
KeyHelpTools(requestShow: (keyboardIsVisible || _showGestureHelp)),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
@ -678,29 +666,20 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeTouchMode() {
|
/// aka changeTouchMode
|
||||||
setState(() => _showEdit = false);
|
BottomAppBar getGestureHelp() {
|
||||||
showModalBottomSheet(
|
return BottomAppBar(
|
||||||
// backgroundColor: MyTheme.grayBg,
|
child: SingleChildScrollView(
|
||||||
isScrollControlled: true,
|
controller: ScrollController(),
|
||||||
context: context,
|
padding: EdgeInsets.symmetric(vertical: 10),
|
||||||
shape: const RoundedRectangleBorder(
|
child: GestureHelp(
|
||||||
borderRadius: BorderRadius.vertical(top: Radius.circular(5))),
|
touchMode: gFFI.ffiModel.touchMode,
|
||||||
builder: (context) => DraggableScrollableSheet(
|
onTouchModeChange: (t) {
|
||||||
expand: false,
|
gFFI.ffiModel.toggleTouchMode();
|
||||||
builder: (context, scrollController) {
|
final v = gFFI.ffiModel.touchMode ? 'Y' : '';
|
||||||
return SingleChildScrollView(
|
bind.sessionPeerOption(
|
||||||
controller: ScrollController(),
|
id: widget.id, name: "touch", value: v);
|
||||||
padding: EdgeInsets.symmetric(vertical: 10),
|
})));
|
||||||
child: GestureHelp(
|
|
||||||
touchMode: gFFI.ffiModel.touchMode,
|
|
||||||
onTouchModeChange: (t) {
|
|
||||||
gFFI.ffiModel.toggleTouchMode();
|
|
||||||
final v = gFFI.ffiModel.touchMode ? 'Y' : '';
|
|
||||||
bind.sessionPeerOption(
|
|
||||||
id: widget.id, name: "touch", value: v);
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// * Currently mobile does not enable map mode
|
// * Currently mobile does not enable map mode
|
||||||
@ -723,49 +702,74 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
// ]));
|
// ]));
|
||||||
// }, clickMaskDismiss: true);
|
// }, clickMaskDismiss: true);
|
||||||
// }
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
Widget getHelpTools() {
|
class KeyHelpTools extends StatefulWidget {
|
||||||
final keyboard = isKeyboardShown();
|
/// need to show by external request, etc [keyboardIsVisible] or [changeTouchMode]
|
||||||
if (!keyboard) {
|
final bool requestShow;
|
||||||
return SizedBox();
|
|
||||||
|
KeyHelpTools({required this.requestShow});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<KeyHelpTools> createState() => _KeyHelpToolsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _KeyHelpToolsState extends State<KeyHelpTools> {
|
||||||
|
var _more = true;
|
||||||
|
var _fn = false;
|
||||||
|
var _pin = false;
|
||||||
|
final _keyboardVisibilityController = KeyboardVisibilityController();
|
||||||
|
|
||||||
|
InputModel get inputModel => gFFI.inputModel;
|
||||||
|
|
||||||
|
Widget wrap(String text, void Function() onPressed,
|
||||||
|
{bool? active, IconData? icon}) {
|
||||||
|
return TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
minimumSize: Size(0, 0),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 9.75),
|
||||||
|
//adds padding inside the button
|
||||||
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
//limits the touch area to the button area
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
),
|
||||||
|
backgroundColor: active == true ? MyTheme.accent80 : null,
|
||||||
|
),
|
||||||
|
child: icon != null
|
||||||
|
? Icon(icon, size: 14, color: Colors.white)
|
||||||
|
: Text(translate(text),
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 11)),
|
||||||
|
onPressed: onPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final hasModifierOn = inputModel.ctrl ||
|
||||||
|
inputModel.alt ||
|
||||||
|
inputModel.shift ||
|
||||||
|
inputModel.command;
|
||||||
|
|
||||||
|
if (!_pin && !hasModifierOn && !widget.requestShow) {
|
||||||
|
return Offstage();
|
||||||
}
|
}
|
||||||
final size = MediaQuery.of(context).size;
|
final size = MediaQuery.of(context).size;
|
||||||
wrap(String text, void Function() onPressed,
|
|
||||||
[bool? active, IconData? icon]) {
|
|
||||||
return TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
minimumSize: Size(0, 0),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 9.75),
|
|
||||||
//adds padding inside the button
|
|
||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
//limits the touch area to the button area
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(5.0),
|
|
||||||
),
|
|
||||||
backgroundColor: active == true ? MyTheme.accent80 : null,
|
|
||||||
),
|
|
||||||
child: icon != null
|
|
||||||
? Icon(icon, size: 17, color: Colors.white)
|
|
||||||
: Text(translate(text),
|
|
||||||
style: TextStyle(color: Colors.white, fontSize: 11)),
|
|
||||||
onPressed: onPressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
final pi = gFFI.ffiModel.pi;
|
final pi = gFFI.ffiModel.pi;
|
||||||
final isMac = pi.platform == kPeerPlatformMacOS;
|
final isMac = pi.platform == kPeerPlatformMacOS;
|
||||||
final modifiers = <Widget>[
|
final modifiers = <Widget>[
|
||||||
wrap('Ctrl ', () {
|
wrap('Ctrl ', () {
|
||||||
setState(() => inputModel.ctrl = !inputModel.ctrl);
|
setState(() => inputModel.ctrl = !inputModel.ctrl);
|
||||||
}, inputModel.ctrl),
|
}, active: inputModel.ctrl),
|
||||||
wrap(' Alt ', () {
|
wrap(' Alt ', () {
|
||||||
setState(() => inputModel.alt = !inputModel.alt);
|
setState(() => inputModel.alt = !inputModel.alt);
|
||||||
}, inputModel.alt),
|
}, active: inputModel.alt),
|
||||||
wrap('Shift', () {
|
wrap('Shift', () {
|
||||||
setState(() => inputModel.shift = !inputModel.shift);
|
setState(() => inputModel.shift = !inputModel.shift);
|
||||||
}, inputModel.shift),
|
}, active: inputModel.shift),
|
||||||
wrap(isMac ? ' Cmd ' : ' Win ', () {
|
wrap(isMac ? ' Cmd ' : ' Win ', () {
|
||||||
setState(() => inputModel.command = !inputModel.command);
|
setState(() => inputModel.command = !inputModel.command);
|
||||||
}, inputModel.command),
|
}, active: inputModel.command),
|
||||||
];
|
];
|
||||||
final keys = <Widget>[
|
final keys = <Widget>[
|
||||||
wrap(
|
wrap(
|
||||||
@ -778,7 +782,14 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
_fn),
|
active: _fn),
|
||||||
|
wrap(
|
||||||
|
'',
|
||||||
|
() => setState(
|
||||||
|
() => _pin = !_pin,
|
||||||
|
),
|
||||||
|
active: _pin,
|
||||||
|
icon: Icons.push_pin),
|
||||||
wrap(
|
wrap(
|
||||||
' ... ',
|
' ... ',
|
||||||
() => setState(
|
() => setState(
|
||||||
@ -789,7 +800,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
_more),
|
active: _more),
|
||||||
];
|
];
|
||||||
final fn = <Widget>[
|
final fn = <Widget>[
|
||||||
SizedBox(width: 9999),
|
SizedBox(width: 9999),
|
||||||
@ -829,16 +840,16 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
SizedBox(width: 9999),
|
SizedBox(width: 9999),
|
||||||
wrap('', () {
|
wrap('', () {
|
||||||
inputModel.inputKey('VK_LEFT');
|
inputModel.inputKey('VK_LEFT');
|
||||||
}, false, Icons.keyboard_arrow_left),
|
}, icon: Icons.keyboard_arrow_left),
|
||||||
wrap('', () {
|
wrap('', () {
|
||||||
inputModel.inputKey('VK_UP');
|
inputModel.inputKey('VK_UP');
|
||||||
}, false, Icons.keyboard_arrow_up),
|
}, icon: Icons.keyboard_arrow_up),
|
||||||
wrap('', () {
|
wrap('', () {
|
||||||
inputModel.inputKey('VK_DOWN');
|
inputModel.inputKey('VK_DOWN');
|
||||||
}, false, Icons.keyboard_arrow_down),
|
}, icon: Icons.keyboard_arrow_down),
|
||||||
wrap('', () {
|
wrap('', () {
|
||||||
inputModel.inputKey('VK_RIGHT');
|
inputModel.inputKey('VK_RIGHT');
|
||||||
}, false, Icons.keyboard_arrow_right),
|
}, icon: Icons.keyboard_arrow_right),
|
||||||
wrap(isMac ? 'Cmd+C' : 'Ctrl+C', () {
|
wrap(isMac ? 'Cmd+C' : 'Ctrl+C', () {
|
||||||
sendPrompt(isMac, 'VK_C');
|
sendPrompt(isMac, 'VK_C');
|
||||||
}),
|
}),
|
||||||
@ -853,14 +864,15 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
return Container(
|
return Container(
|
||||||
color: Color(0xAA000000),
|
color: Color(0xAA000000),
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: keyboard ? 24 : 4, left: 0, right: 0, bottom: 8),
|
top: _keyboardVisibilityController.isVisible ? 24 : 4, bottom: 8),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: space,
|
spacing: space,
|
||||||
runSpacing: space,
|
runSpacing: space,
|
||||||
children: <Widget>[SizedBox(width: 9999)] +
|
children: <Widget>[SizedBox(width: 9999)] +
|
||||||
(keyboard
|
modifiers +
|
||||||
? modifiers + keys + (_fn ? fn : []) + (_more ? more : [])
|
keys +
|
||||||
: modifiers),
|
(_fn ? fn : []) +
|
||||||
|
(_more ? more : []),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,6 +488,54 @@ packages:
|
|||||||
url: "https://github.com/Kingtous/flutter_improved_scrolling"
|
url: "https://github.com/Kingtous/flutter_improved_scrolling"
|
||||||
source: git
|
source: git
|
||||||
version: "0.0.3"
|
version: "0.0.3"
|
||||||
|
flutter_keyboard_visibility:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility
|
||||||
|
sha256: "86b71bbaffa38e885f5c21b1182408b9be6951fd125432cf6652c636254cef2d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.4.0"
|
||||||
|
flutter_keyboard_visibility_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility_linux
|
||||||
|
sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
|
flutter_keyboard_visibility_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility_macos
|
||||||
|
sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
|
flutter_keyboard_visibility_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility_platform_interface
|
||||||
|
sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
flutter_keyboard_visibility_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility_web
|
||||||
|
sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
flutter_keyboard_visibility_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility_windows
|
||||||
|
sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -91,6 +91,7 @@ dependencies:
|
|||||||
win32: any
|
win32: any
|
||||||
password_strength: ^0.2.0
|
password_strength: ^0.2.0
|
||||||
flutter_launcher_icons: ^0.11.0
|
flutter_launcher_icons: ^0.11.0
|
||||||
|
flutter_keyboard_visibility: ^5.4.0
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user