diff --git a/flutter/android/app/build.gradle b/flutter/android/app/build.gradle index 326689e5e..f4dc69e41 100644 --- a/flutter/android/app/build.gradle +++ b/flutter/android/app/build.gradle @@ -46,7 +46,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.carriez.flutter_hbb" minSdkVersion 21 - targetSdkVersion 31 + targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/flutter/lib/common/widgets/overlay.dart b/flutter/lib/common/widgets/overlay.dart index f2f3b8fb0..b19034c68 100644 --- a/flutter/lib/common/widgets/overlay.dart +++ b/flutter/lib/common/widgets/overlay.dart @@ -48,6 +48,7 @@ class DraggableChatWindow extends StatelessWidget { position: position, width: width, height: height, + chatModel: chatModel, builder: (context, onPanUpdate) { final child = Scaffold( @@ -242,6 +243,7 @@ class Draggable extends StatefulWidget { this.position = Offset.zero, required this.width, required this.height, + this.chatModel, required this.builder}) : super(key: key); @@ -250,6 +252,7 @@ class Draggable extends StatefulWidget { final Offset position; final double width; final double height; + final ChatModel? chatModel; final Widget Function(BuildContext, GestureDragUpdateCallback) builder; @override @@ -258,6 +261,7 @@ class Draggable extends StatefulWidget { class _DraggableState extends State { late Offset _position; + late ChatModel? _chatModel; bool _keyboardVisible = false; double _saveHeight = 0; double _lastBottomHeight = 0; @@ -266,6 +270,7 @@ class _DraggableState extends State { void initState() { super.initState(); _position = widget.position; + _chatModel = widget.chatModel; } void onPanUpdate(DragUpdateDetails d) { @@ -292,6 +297,7 @@ class _DraggableState extends State { setState(() { _position = Offset(x, y); }); + _chatModel?.setChatWindowPosition(_position); } checkScreenSize() {} @@ -351,14 +357,14 @@ class IOSDraggable extends StatefulWidget { const IOSDraggable({ Key? key, this.position = Offset.zero, - required this.chatModel, + this.chatModel, required this.width, required this.height, required this.builder}) : super(key: key); final Offset position; - final ChatModel chatModel; + final ChatModel? chatModel; final double width; final double height; final Widget Function(BuildContext) builder; @@ -368,22 +374,58 @@ class IOSDraggable extends StatefulWidget { } class _IOSDraggableState extends State { -late Offset _position; -late ChatModel _chatModel; -late double _width; -late double _height; + late Offset _position; + late ChatModel? _chatModel; + late double _width; + late double _height; + bool _keyboardVisible = false; + double _saveHeight = 0; + double _lastBottomHeight = 0; -@override -void initState() { - super.initState(); - _position = widget.position; - _chatModel = widget.chatModel; - _width = widget.width; - _height = widget.height; -} + @override + void initState() { + super.initState(); + _position = widget.position; + _chatModel = widget.chatModel; + _width = widget.width; + _height = widget.height; + } + + checkKeyboard() { + final bottomHeight = MediaQuery.of(context).viewInsets.bottom; + final currentVisible = bottomHeight != 0; + + // save + if (!_keyboardVisible && currentVisible) { + _saveHeight = _position.dy; + } + + // reset + if (_lastBottomHeight > 0 && bottomHeight == 0) { + setState(() { + _position = Offset(_position.dx, _saveHeight); + }); + } + + // onKeyboardVisible + if (_keyboardVisible && currentVisible) { + final sumHeight = bottomHeight + _height; + final contextHeight = MediaQuery.of(context).size.height; + if (sumHeight + _position.dy > contextHeight) { + final y = contextHeight - sumHeight; + setState(() { + _position = Offset(_position.dx, y); + }); + } + } + + _keyboardVisible = currentVisible; + _lastBottomHeight = bottomHeight; + } @override Widget build(BuildContext context) { + checkKeyboard(); return Stack( children: [ Positioned( @@ -394,13 +436,15 @@ void initState() { setState(() { _position += details.delta; }); + _chatModel?.setChatWindowPosition(_position); }, child: Material( child: Container( width: _width, height: _height, - child: widget.builder(context), + decoration: BoxDecoration(border: Border.all(color: MyTheme.border)), + child: widget.builder(context), ), ), ), diff --git a/flutter/lib/models/chat_model.dart b/flutter/lib/models/chat_model.dart index 5ab0a6929..37766e54a 100644 --- a/flutter/lib/models/chat_model.dart +++ b/flutter/lib/models/chat_model.dart @@ -72,6 +72,13 @@ class ChatModel with ChangeNotifier { RxInt mobileUnreadSum = 0.obs; MessageKey? latestReceivedKey; + Offset chatWindowPosition = Offset(20, 80); + + void setChatWindowPosition(Offset position) { + chatWindowPosition = position; + notifyListeners(); + } + @override void dispose() { textController.dispose(); @@ -210,7 +217,7 @@ class ChatModel with ChangeNotifier { } }, child: DraggableChatWindow( - position: chatInitPos ?? Offset(20, 80), + position: chatInitPos ?? chatWindowPosition, width: 250, height: 350, chatModel: this)); diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 960e28338..b6aca5429 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -300,11 +300,12 @@ packages: dash_chat_2: dependency: "direct main" description: - name: dash_chat_2 - sha256: e9e08b2a030d340d60f7adbeb977d3d6481db1f172b51440bfa02488b92fa19c - url: "https://pub.dev" - source: hosted - version: "0.0.17" + path: "." + ref: HEAD + resolved-ref: bd6b5b41254e57c5bcece202ebfb234de63e6487 + url: "https://github.com/rustdesk-org/Dash-Chat-2" + source: git + version: "0.0.18" debounce_throttle: dependency: "direct main" description: @@ -1398,10 +1399,10 @@ packages: dependency: transitive description: name: video_player - sha256: "59f7f31c919c59cbedd37c617317045f5f650dc0eeb568b0b0de9a36472bdb28" + sha256: d3910a8cefc0de8a432a4411dcf85030e885d8fef3ddea291f162253a05dbf01 url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.7.1" video_player_android: dependency: transitive description: @@ -1422,10 +1423,10 @@ packages: dependency: transitive description: name: video_player_platform_interface - sha256: "42bb75de5e9b79e1f20f1d95f688fac0f95beac4d89c6eb2cd421724d4432dae" + sha256: be72301bf2c0150ab35a8c34d66e5a99de525f6de1e8d27c0672b836fe48f73a url: "https://pub.dev" source: hosted - version: "6.0.1" + version: "6.2.1" video_player_web: dependency: transitive description: diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 691f86066..ba90bef3c 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -39,7 +39,9 @@ dependencies: package_info_plus: ^3.1.2 url_launcher: ^6.0.9 toggle_switch: ^2.1.0 - dash_chat_2: ^0.0.17 + dash_chat_2: + git: + url: https://github.com/rustdesk-org/Dash-Chat-2 draggable_float_widget: ^0.0.2 settings_ui: ^2.0.2 flutter_breadcrumb: ^1.0.1 diff --git a/src/common.rs b/src/common.rs index 36ca972b2..8477c9e62 100644 --- a/src/common.rs +++ b/src/common.rs @@ -779,12 +779,18 @@ pub fn get_sysinfo() -> serde_json::Value { os = format!("{os} - {}", system.os_version().unwrap_or_default()); } let hostname = hostname(); // sys.hostname() return localhost on android in my test - serde_json::json!({ + use serde_json::json; + let mut out = json!({ "cpu": format!("{cpu}{num_cpus}/{num_pcpus} cores"), "memory": format!("{memory}GB"), "os": os, "hostname": hostname, - }) + }); + #[cfg(not(any(target_os = "android", target_os = "ios")))] + { + out["username"] = json!(crate::platform::get_active_username()); + } + out } #[inline] diff --git a/src/lang/es.rs b/src/lang/es.rs index 7bb24ac53..35d776f1a 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -538,8 +538,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("pull_ab_failed_tip", "No se ha podido refrescar el directorio"), ("push_ab_failed_tip", "No se ha podido sincronizar el directorio con el servidor"), ("synced_peer_readded_tip", "Los dispositivos presentes en sesiones recientes se sincronizarán con el directorio."), - ("Change Color", ""), - ("Primary Color", ""), - ("HSV Color", ""), + ("Change Color", "Cambiar Color"), + ("Primary Color", "Color Primario"), + ("HSV Color", "Color HSV"), ].iter().cloned().collect(); }