fix:reconnect time,enter password focus,wrong gesture tap-up;ctrl soft keyboard

This commit is contained in:
csf 2022-04-26 21:21:08 +08:00
parent b30299cc12
commit c188a6f93f
6 changed files with 106 additions and 63 deletions

View File

@ -10,6 +10,7 @@ import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.provider.Settings import android.provider.Settings
import android.util.Log import android.util.Log
import android.view.WindowManager
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
@ -125,6 +126,18 @@ class MainActivity : FlutterActivity() {
result.success(true) result.success(true)
} }
} }
"enable_soft_keyboard" -> {
// https://blog.csdn.net/hanye2020/article/details/105553780
try {
if (call.arguments as Boolean) {
window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
}
} finally {
result.success(true)
}
}
else -> { else -> {
result.error("-1", "No such method", null) result.error("-1", "No such method", null)
} }

View File

@ -249,6 +249,7 @@ class FfiModel with ChangeNotifier {
if (displays.length > 0) { if (displays.length > 0) {
showLoading(translate('Connected, waiting for image...')); showLoading(translate('Connected, waiting for image...'));
_waitForImage = true; _waitForImage = true;
_reconnects = 1;
} }
} }
notifyListeners(); notifyListeners();

View File

@ -148,6 +148,7 @@ hideChatWindowOverlay() {
toggleChatOverlay() { toggleChatOverlay() {
if (iconOverlayEntry == null || windowOverlayEntry == null) { if (iconOverlayEntry == null || windowOverlayEntry == null) {
FFI.invokeMethod("enable_soft_keyboard", true);
showChatIconOverlay(); showChatIconOverlay();
showChatWindowOverlay(); showChatWindowOverlay();
} else { } else {

View File

@ -60,6 +60,7 @@ class _RemotePageState extends State<RemotePage> {
@override @override
void dispose() { void dispose() {
FFI.listenToMouse(false); FFI.listenToMouse(false);
FFI.invokeMethod("enable_soft_keyboard", true);
_mobileFocusNode.dispose(); _mobileFocusNode.dispose();
_physicalFocusNode.dispose(); _physicalFocusNode.dispose();
FFI.close(); FFI.close();
@ -90,6 +91,7 @@ class _RemotePageState extends State<RemotePage> {
if (v < 100) { if (v < 100) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: []); overlays: []);
FFI.invokeMethod("enable_soft_keyboard", false);
} }
}); });
} }
@ -181,6 +183,7 @@ class _RemotePageState extends State<RemotePage> {
} }
void openKeyboard() { void openKeyboard() {
FFI.invokeMethod("enable_soft_keyboard", true);
// destroy first, so that our _value trick can work // destroy first, so that our _value trick can work
_value = initText; _value = initText;
setState(() => _showEdit = false); setState(() => _showEdit = false);
@ -193,7 +196,6 @@ class _RemotePageState extends State<RemotePage> {
_timer = Timer(Duration(milliseconds: 30), () { _timer = Timer(Duration(milliseconds: 30), () {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values); overlays: SystemUiOverlay.values);
SystemChannels.textInput.invokeMethod('TextInput.show');
_mobileFocusNode.requestFocus(); _mobileFocusNode.requestFocus();
}); });
}); });
@ -211,48 +213,59 @@ class _RemotePageState extends State<RemotePage> {
final pi = Provider.of<FfiModel>(context).pi; final pi = Provider.of<FfiModel>(context).pi;
final hideKeyboard = isKeyboardShown() && _showEdit; final hideKeyboard = isKeyboardShown() && _showEdit;
final showActionButton = !_showBar || hideKeyboard; final showActionButton = !_showBar || hideKeyboard;
final keyboard = FFI.ffiModel.permissions['keyboard'] != false;
return WillPopScope( return WillPopScope(
onWillPop: () async { onWillPop: () async {
clientClose(); clientClose();
return false; return false;
}, },
child: Scaffold( child: getRawPointerAndKeyBody(
// resizeToAvoidBottomInset: true, keyboard,
floatingActionButton: !showActionButton Scaffold(
? null // resizeToAvoidBottomInset: true,
: FloatingActionButton( floatingActionButton: !showActionButton
mini: !hideKeyboard, ? null
child: Icon( : FloatingActionButton(
hideKeyboard ? Icons.expand_more : Icons.expand_less), mini: !hideKeyboard,
backgroundColor: MyTheme.accent, child: Icon(
onPressed: () { hideKeyboard ? Icons.expand_more : Icons.expand_less),
setState(() { backgroundColor: MyTheme.accent,
if (hideKeyboard) { onPressed: () {
_showEdit = false; setState(() {
_mobileFocusNode.unfocus(); if (hideKeyboard) {
SystemChannels.textInput.invokeMethod('TextInput.hide'); _showEdit = false;
_physicalFocusNode.requestFocus(); FFI.invokeMethod("enable_soft_keyboard", false);
} else { _mobileFocusNode.unfocus();
_showBar = !_showBar; _physicalFocusNode.requestFocus();
} } else {
}); _showBar = !_showBar;
}), }
bottomNavigationBar: });
_showBar && pi.displays != null ? getBottomAppBar() : null, }),
body: Overlay( bottomNavigationBar:
initialEntries: [ _showBar && pi.displays != null ? getBottomAppBar() : null,
OverlayEntry(builder: (context) { body: Overlay(
final keyboard = FFI.ffiModel.permissions['keyboard'] != false; initialEntries: [
return Container( OverlayEntry(builder: (context) {
color: Colors.black, return Container(
child: getRawPointerAndKeyBody(keyboard)); color: Colors.black,
}) // child: getRawPointerAndKeyBody(keyboard));
], child: isDesktop
)), ? getBodyForDesktopWithListener(keyboard)
: SafeArea(
child: Container(
color: MyTheme.canvasColor,
child: _isPhysicalKeyboard
? getBodyForMobile()
: getBodyForMobileWithGesture())));
})
],
))),
); );
} }
Widget getRawPointerAndKeyBody(bool keyboard) { Widget getRawPointerAndKeyBody(bool keyboard, Widget child) {
return Listener( return Listener(
onPointerHover: (e) { onPointerHover: (e) {
if (e.kind != ui.PointerDeviceKind.mouse) return; if (e.kind != ui.PointerDeviceKind.mouse) return;
@ -351,14 +364,7 @@ class _RemotePageState extends State<RemotePage> {
} }
return KeyEventResult.handled; return KeyEventResult.handled;
}, },
child: isDesktop child: child))));
? getBodyForDesktopWithListener(keyboard)
: SafeArea(
child: Container(
color: MyTheme.canvasColor,
child: _isPhysicalKeyboard
? getBodyForMobile()
: getBodyForMobileWithGesture()))))));
} }
Widget getBottomAppBar() { Widget getBottomAppBar() {
@ -490,7 +496,7 @@ class _RemotePageState extends State<RemotePage> {
FFI.cursorModel.updatePan(d.delta.dx, d.delta.dy, _touchMode); FFI.cursorModel.updatePan(d.delta.dx, d.delta.dy, _touchMode);
} }
}, },
onHoldDragCancel: () { onHoldDragEnd: (_) {
if (!_touchMode) { if (!_touchMode) {
FFI.sendMouse('up', MouseButtons.left); FFI.sendMouse('up', MouseButtons.left);
} }
@ -499,8 +505,6 @@ class _RemotePageState extends State<RemotePage> {
if (_touchMode) { if (_touchMode) {
FFI.cursorModel.move(d.localPosition.dx, d.localPosition.dy); FFI.cursorModel.move(d.localPosition.dx, d.localPosition.dy);
FFI.sendMouse('down', MouseButtons.left); FFI.sendMouse('down', MouseButtons.left);
} else {
FFI.sendMouse('up', MouseButtons.left);
} }
}, },
onOneFingerPanUpdate: (d) { onOneFingerPanUpdate: (d) {
@ -543,6 +547,7 @@ class _RemotePageState extends State<RemotePage> {
textInputAction: TextInputAction.newline, textInputAction: TextInputAction.newline,
autocorrect: false, autocorrect: false,
enableSuggestions: false, enableSuggestions: false,
autofocus: true,
focusNode: _mobileFocusNode, focusNode: _mobileFocusNode,
maxLines: null, maxLines: null,
initialValue: _value, initialValue: _value,

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import '../common.dart'; import '../common.dart';
@ -10,15 +12,15 @@ void clientClose() {
const SEC1 = Duration(seconds: 1); const SEC1 = Duration(seconds: 1);
void showSuccess({Duration duration = SEC1}) { void showSuccess({Duration duration = SEC1}) {
SmartDialog.dismiss(); SmartDialog.dismiss();
showToast(translate("Successful"),duration:SEC1); showToast(translate("Successful"), duration: SEC1);
} }
void showError({Duration duration = SEC1}){ void showError({Duration duration = SEC1}) {
SmartDialog.dismiss(); SmartDialog.dismiss();
showToast(translate("Error"),duration:SEC1); showToast(translate("Error"), duration: SEC1);
} }
void updatePasswordDialog(){ void updatePasswordDialog() {
final p0 = TextEditingController(); final p0 = TextEditingController();
final p1 = TextEditingController(); final p1 = TextEditingController();
var validateLength = false; var validateLength = false;
@ -43,7 +45,7 @@ void updatePasswordDialog(){
if (validateLength != val) { if (validateLength != val) {
// use delay to make setState success // use delay to make setState success
Future.delayed(Duration(microseconds: 1), Future.delayed(Duration(microseconds: 1),
() => setState(() => validateLength = val)); () => setState(() => validateLength = val));
} }
return val return val
? null ? null
@ -62,7 +64,7 @@ void updatePasswordDialog(){
final val = p0.text == v; final val = p0.text == v;
if (validateSame != val) { if (validateSame != val) {
Future.delayed(Duration(microseconds: 1), Future.delayed(Duration(microseconds: 1),
() => setState(() => validateSame = val)); () => setState(() => validateSame = val));
} }
return val return val
? null ? null
@ -82,14 +84,14 @@ void updatePasswordDialog(){
style: flatButtonStyle, style: flatButtonStyle,
onPressed: (validateLength && validateSame) onPressed: (validateLength && validateSame)
? () async { ? () async {
close(); close();
showLoading(translate("Waiting")); showLoading(translate("Waiting"));
if(await FFI.serverModel.updatePassword(p0.text)){ if (await FFI.serverModel.updatePassword(p0.text)) {
showSuccess(); showSuccess();
}else{ } else {
showError(); showError();
} }
} }
: null, : null,
child: Text(translate('OK')), child: Text(translate('OK')),
), ),
@ -115,7 +117,6 @@ void enterPasswordDialog(String id) {
), ),
value: remember, value: remember,
onChanged: (v) { onChanged: (v) {
debugPrint("onChanged");
if (v != null) { if (v != null) {
setState(() => remember = v); setState(() => remember = v);
} }
@ -181,11 +182,25 @@ class PasswordWidget extends StatefulWidget {
class _PasswordWidgetState extends State<PasswordWidget> { class _PasswordWidgetState extends State<PasswordWidget> {
bool _passwordVisible = false; bool _passwordVisible = false;
final _focusNode = FocusNode();
@override
void initState() {
super.initState();
Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus());
}
@override
void dispose() {
_focusNode.unfocus();
_focusNode.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return TextField( return TextField(
autofocus: true, focusNode: _focusNode,
controller: widget.controller, controller: widget.controller,
obscureText: !_passwordVisible, obscureText: !_passwordVisible,
//This will obscure text dynamically //This will obscure text dynamically

View File

@ -236,6 +236,7 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
GestureDragUpdateCallback? onHoldDragUpdate; GestureDragUpdateCallback? onHoldDragUpdate;
GestureDragDownCallback? onHoldDragDown; GestureDragDownCallback? onHoldDragDown;
GestureDragCancelCallback? onHoldDragCancel; GestureDragCancelCallback? onHoldDragCancel;
GestureDragEndCallback? onHoldDragEnd;
bool _isStart = false; bool _isStart = false;
@ -253,7 +254,8 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
case kPrimaryButton: case kPrimaryButton:
if (onHoldDragStart == null && if (onHoldDragStart == null &&
onHoldDragUpdate == null && onHoldDragUpdate == null &&
onHoldDragCancel == null) { onHoldDragCancel == null &&
onHoldDragEnd == null) {
return false; return false;
} }
break; break;
@ -305,6 +307,10 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
if (event is PointerUpEvent) { if (event is PointerUpEvent) {
if (_firstTap == null && _secondTap == null) { if (_firstTap == null && _secondTap == null) {
_registerFirstTap(tracker); _registerFirstTap(tracker);
} else if (_secondTap != null) {
if (event.pointer == _secondTap!.pointer) {
if (onHoldDragEnd != null) onHoldDragEnd!(DragEndDetails());
}
} else { } else {
_reject(tracker); _reject(tracker);
} }
@ -739,6 +745,7 @@ RawGestureDetector getMixinGestureDetector({
GestureDragStartCallback? onHoldDragStart, GestureDragStartCallback? onHoldDragStart,
GestureDragUpdateCallback? onHoldDragUpdate, GestureDragUpdateCallback? onHoldDragUpdate,
GestureDragCancelCallback? onHoldDragCancel, GestureDragCancelCallback? onHoldDragCancel,
GestureDragEndCallback? onHoldDragEnd,
GestureTapDownCallback? onDoubleFinerTap, GestureTapDownCallback? onDoubleFinerTap,
GestureDragStartCallback? onOneFingerPanStart, GestureDragStartCallback? onOneFingerPanStart,
GestureDragUpdateCallback? onOneFingerPanUpdate, GestureDragUpdateCallback? onOneFingerPanUpdate,
@ -782,6 +789,7 @@ RawGestureDetector getMixinGestureDetector({
..onHoldDragStart = onHoldDragStart ..onHoldDragStart = onHoldDragStart
..onHoldDragUpdate = onHoldDragUpdate ..onHoldDragUpdate = onHoldDragUpdate
..onHoldDragCancel = onHoldDragCancel ..onHoldDragCancel = onHoldDragCancel
..onHoldDragEnd = onHoldDragEnd
}), }),
DoubleFinerTapGestureRecognizer: GestureRecognizerFactoryWithHandlers< DoubleFinerTapGestureRecognizer: GestureRecognizerFactoryWithHandlers<
DoubleFinerTapGestureRecognizer>( DoubleFinerTapGestureRecognizer>(