mirror of
https://github.com/rustdesk/rustdesk.git
synced 2025-06-07 18:02:48 +08:00
use uuid as session id
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
71838ad821
commit
2ececed0c1
2
.github/workflows/bridge.yml
vendored
2
.github/workflows/bridge.yml
vendored
@ -61,7 +61,7 @@ jobs:
|
|||||||
- name: Install flutter rust bridge deps
|
- name: Install flutter rust bridge deps
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }}
|
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid"
|
||||||
pushd flutter && flutter pub get && popd
|
pushd flutter && flutter pub get && popd
|
||||||
|
|
||||||
- name: Run flutter rust bridge
|
- name: Run flutter rust bridge
|
||||||
|
4
.github/workflows/flutter-build.yml
vendored
4
.github/workflows/flutter-build.yml
vendored
@ -79,7 +79,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install flutter rust bridge deps
|
- name: Install flutter rust bridge deps
|
||||||
run: |
|
run: |
|
||||||
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }}
|
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid"
|
||||||
Push-Location flutter ; flutter pub get ; Pop-Location
|
Push-Location flutter ; flutter pub get ; Pop-Location
|
||||||
~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart
|
~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart
|
||||||
|
|
||||||
@ -312,7 +312,7 @@ jobs:
|
|||||||
- name: Install flutter rust bridge deps
|
- name: Install flutter rust bridge deps
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }}
|
cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid"
|
||||||
pushd flutter && flutter pub get && popd
|
pushd flutter && flutter pub get && popd
|
||||||
~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart
|
~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart
|
||||||
|
|
||||||
|
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -58,6 +58,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"atomic",
|
"atomic",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2103,6 +2104,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"threadpool",
|
"threadpool",
|
||||||
|
"uuid",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
@ -2878,6 +2880,7 @@ dependencies = [
|
|||||||
"tokio-socks",
|
"tokio-socks",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml 0.7.3",
|
"toml 0.7.3",
|
||||||
|
"uuid",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
"zstd 0.12.3+zstd.1.5.2",
|
"zstd 0.12.3+zstd.1.5.2",
|
||||||
]
|
]
|
||||||
|
@ -62,7 +62,7 @@ num_cpus = "1.15"
|
|||||||
bytes = { version = "1.4", features = ["serde"] }
|
bytes = { version = "1.4", features = ["serde"] }
|
||||||
default-net = "0.14"
|
default-net = "0.14"
|
||||||
wol-rs = "1.0"
|
wol-rs = "1.0"
|
||||||
flutter_rust_bridge = { version = "1.75", optional = true }
|
flutter_rust_bridge = { version = "1.75", features = ["uuid"], optional = true}
|
||||||
errno = "0.3"
|
errno = "0.3"
|
||||||
rdev = { git = "https://github.com/fufesou/rdev" }
|
rdev = { git = "https://github.com/fufesou/rdev" }
|
||||||
url = { version = "2.3", features = ["serde"] }
|
url = { version = "2.3", features = ["serde"] }
|
||||||
|
@ -23,6 +23,7 @@ import 'package:texture_rgba_renderer/texture_rgba_renderer.dart';
|
|||||||
import 'package:uni_links/uni_links.dart';
|
import 'package:uni_links/uni_links.dart';
|
||||||
import 'package:uni_links_desktop/uni_links_desktop.dart';
|
import 'package:uni_links_desktop/uni_links_desktop.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
import 'package:win32/win32.dart' as win32;
|
import 'package:win32/win32.dart' as win32;
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
import 'package:window_size/window_size.dart' as window_size;
|
import 'package:window_size/window_size.dart' as window_size;
|
||||||
@ -68,6 +69,7 @@ typedef F = String Function(String);
|
|||||||
typedef FMethod = String Function(String, dynamic);
|
typedef FMethod = String Function(String, dynamic);
|
||||||
|
|
||||||
typedef StreamEventHandler = Future<void> Function(Map<String, dynamic>);
|
typedef StreamEventHandler = Future<void> Function(Map<String, dynamic>);
|
||||||
|
typedef SessionID = UuidValue;
|
||||||
final iconHardDrive = MemoryImage(Uint8List.fromList(base64Decode(
|
final iconHardDrive = MemoryImage(Uint8List.fromList(base64Decode(
|
||||||
'iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAmVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjHWqVAAAAMnRSTlMAv0BmzLJNXlhiUu2fxXDgu7WuSUUe29LJvpqUjX53VTstD7ilNujCqTEk5IYH+vEoFjKvAagAAAPpSURBVHja7d0JbhpBEIXhB3jYzb5vBgzYgO04df/DJXGUKMwU9ECmZ6pQfSfw028LCXW3YYwxxhhjjDHGGGOM0eZ9VV1MckdKWLM1bRQ/35GW/WxHHu1me6ShuyHvNl34VhlTKsYVeDWj1EzgUZ1S1DrAk/UDparZgxd9Sl0BHnxSBhpI3jfKQG2FpLUpE69I2ILikv1nsvygjBwPSNKYMlNHggqUoSKS80AZCnwHqQ1zCRvW+CRegwRFeFAMKKrtM8gTPJlzSfwFgT9dJom3IDN4VGaSeAryAK8m0SSeghTg1ZYiql6CjBDhO8mzlyAVhKhIwgXxrh5NojGIhyRckEdwpCdhgpSQgiWTRGMQNonGIGySp0SDvMDBX5KWxiB8Eo1BgE00SYJBykhNnkmSWJAcLpGaJNMgfJKyxiDAK4WNEwryhMtkJsk8CJtEYxA+icYgQIfCcgkEqcJNXhIRQdgkGoPwSTQG+e8khdu/7JOVREwQIKCwF41B2CQljUH4JLcH6SI+OUlEBQHa0SQag/BJNAbhkjxqDMIn0RgEeI4muSlID9eSkERgEKAVTaIxCJ9EYxA2ydVB8hCASVLRGAQYR5NoDMIn0RgEyFHYSGMQPonGII4kziCNvBgNJonEk4u3GAk8Sprk6eYaqbMDY0oKvUm5jfC/viGiSypV7+M3i2iDsAGpNEDYjlTa3W8RdR/r544g50ilnA0RxoZIE2NIXqQbhkAkGyKNDZHGhkhjQ6SxIdLYEGlsiDQ2JGTVeD0264U9zipPh7XOooffpA6pfNCXjxl4/c3pUzlChwzor53zwYYVfpI5pOV6LWFF/2jiJ5FDSs5jdY/0rwUAkUMeXWdBqnSqD0DikBqdqCHsjTvELm9In0IOri/0pwAEDtlSyNaRjAIAAoesKWTtuusxByBwCJp0oomwBXcYUuCQgE50ENajE4OvZAKHLB1/68Br5NqiyCGYOY8YRd77kTkEb64n7lZN+mOIX4QOwb5FX0ZVx3uOxwW+SB0CbBubemWP8/rlaaeRX+M3uUOuZENsiA25zIbYkPsZElBIHwL13U/PTjJ/cyOOEoVM3I+hziDQlELm7pPxw3eI8/7gPh1fpLA6xGnEeDDgO0UcIAzzM35HxLPIq5SXe9BLzOsj9eUaQqyXzxS1QFSfWM2cCANiHcAISJ0AnCKpUwTuIkkA3EeSInAXSQKcs1V18e24wlllUmQp9v9zXKeHi+akRAMOPVKhAqdPBZeUmnnEsO6QcJ0+4qmOSbBxFfGVRiTUqITrdKcCbyYO3/K4wX4+aQ+FfNjXhu3JfAVjjDHGGGOMMcYYY4xIPwCgfqT6TbhCLAAAAABJRU5ErkJggg==')));
|
'iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAmVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjHWqVAAAAMnRSTlMAv0BmzLJNXlhiUu2fxXDgu7WuSUUe29LJvpqUjX53VTstD7ilNujCqTEk5IYH+vEoFjKvAagAAAPpSURBVHja7d0JbhpBEIXhB3jYzb5vBgzYgO04df/DJXGUKMwU9ECmZ6pQfSfw028LCXW3YYwxxhhjjDHGGGOM0eZ9VV1MckdKWLM1bRQ/35GW/WxHHu1me6ShuyHvNl34VhlTKsYVeDWj1EzgUZ1S1DrAk/UDparZgxd9Sl0BHnxSBhpI3jfKQG2FpLUpE69I2ILikv1nsvygjBwPSNKYMlNHggqUoSKS80AZCnwHqQ1zCRvW+CRegwRFeFAMKKrtM8gTPJlzSfwFgT9dJom3IDN4VGaSeAryAK8m0SSeghTg1ZYiql6CjBDhO8mzlyAVhKhIwgXxrh5NojGIhyRckEdwpCdhgpSQgiWTRGMQNonGIGySp0SDvMDBX5KWxiB8Eo1BgE00SYJBykhNnkmSWJAcLpGaJNMgfJKyxiDAK4WNEwryhMtkJsk8CJtEYxA+icYgQIfCcgkEqcJNXhIRQdgkGoPwSTQG+e8khdu/7JOVREwQIKCwF41B2CQljUH4JLcH6SI+OUlEBQHa0SQag/BJNAbhkjxqDMIn0RgEeI4muSlID9eSkERgEKAVTaIxCJ9EYxA2ydVB8hCASVLRGAQYR5NoDMIn0RgEyFHYSGMQPonGII4kziCNvBgNJonEk4u3GAk8Sprk6eYaqbMDY0oKvUm5jfC/viGiSypV7+M3i2iDsAGpNEDYjlTa3W8RdR/r544g50ilnA0RxoZIE2NIXqQbhkAkGyKNDZHGhkhjQ6SxIdLYEGlsiDQ2JGTVeD0264U9zipPh7XOooffpA6pfNCXjxl4/c3pUzlChwzor53zwYYVfpI5pOV6LWFF/2jiJ5FDSs5jdY/0rwUAkUMeXWdBqnSqD0DikBqdqCHsjTvELm9In0IOri/0pwAEDtlSyNaRjAIAAoesKWTtuusxByBwCJp0oomwBXcYUuCQgE50ENajE4OvZAKHLB1/68Br5NqiyCGYOY8YRd77kTkEb64n7lZN+mOIX4QOwb5FX0ZVx3uOxwW+SB0CbBubemWP8/rlaaeRX+M3uUOuZENsiA25zIbYkPsZElBIHwL13U/PTjJ/cyOOEoVM3I+hziDQlELm7pPxw3eI8/7gPh1fpLA6xGnEeDDgO0UcIAzzM35HxLPIq5SXe9BLzOsj9eUaQqyXzxS1QFSfWM2cCANiHcAISJ0AnCKpUwTuIkkA3EeSInAXSQKcs1V18e24wlllUmQp9v9zXKeHi+akRAMOPVKhAqdPBZeUmnnEsO6QcJ0+4qmOSbBxFfGVRiTUqITrdKcCbyYO3/K4wX4+aQ+FfNjXhu3JfAVjjDHGGGOMMcYYY4xIPwCgfqT6TbhCLAAAAABJRU5ErkJggg==')));
|
||||||
|
|
||||||
@ -890,8 +892,8 @@ class CustomAlertDialog extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void msgBox(String id, String type, String title, String text, String link,
|
void msgBox(SessionID sessionId, String type, String title, String text,
|
||||||
OverlayDialogManager dialogManager,
|
String link, OverlayDialogManager dialogManager,
|
||||||
{bool? hasCancel, ReconnectHandle? reconnect}) {
|
{bool? hasCancel, ReconnectHandle? reconnect}) {
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
List<Widget> buttons = [];
|
List<Widget> buttons = [];
|
||||||
@ -936,7 +938,7 @@ void msgBox(String id, String type, String title, String text, String link,
|
|||||||
buttons.insert(
|
buttons.insert(
|
||||||
0,
|
0,
|
||||||
dialogButton('Reconnect', isOutline: true, onPressed: () {
|
dialogButton('Reconnect', isOutline: true, onPressed: () {
|
||||||
reconnect(dialogManager, id, false);
|
reconnect(dialogManager, sessionId, false);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (link.isNotEmpty) {
|
if (link.isNotEmpty) {
|
||||||
@ -950,7 +952,7 @@ void msgBox(String id, String type, String title, String text, String link,
|
|||||||
onSubmit: hasOk ? submit : null,
|
onSubmit: hasOk ? submit : null,
|
||||||
onCancel: hasCancel == true ? cancel : null,
|
onCancel: hasCancel == true ? cancel : null,
|
||||||
),
|
),
|
||||||
tag: '$id-$type-$title-$text-$link',
|
tag: '$sessionId-$type-$title-$text-$link',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,9 @@ import '../../common.dart';
|
|||||||
import '../../models/model.dart';
|
import '../../models/model.dart';
|
||||||
import '../../models/platform_model.dart';
|
import '../../models/platform_model.dart';
|
||||||
|
|
||||||
void clientClose(String id, OverlayDialogManager dialogManager) {
|
void clientClose(SessionID sessionId, OverlayDialogManager dialogManager) {
|
||||||
msgBox(id, 'info', 'Close', 'Are you sure to close the connection?', '',
|
msgBox(sessionId, 'info', 'Close', 'Are you sure to close the connection?',
|
||||||
dialogManager);
|
'', dialogManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ValidationRule {
|
abstract class ValidationRule {
|
||||||
@ -423,8 +423,8 @@ class _PasswordWidgetState extends State<PasswordWidget> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrongPasswordDialog(
|
void wrongPasswordDialog(SessionID sessionId,
|
||||||
String id, OverlayDialogManager dialogManager, type, title, text) {
|
OverlayDialogManager dialogManager, type, title, text) {
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show((setState, close, context) {
|
dialogManager.show((setState, close, context) {
|
||||||
cancel() {
|
cancel() {
|
||||||
@ -433,7 +433,7 @@ void wrongPasswordDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
enterPasswordDialog(id, dialogManager);
|
enterPasswordDialog(sessionId, dialogManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
@ -455,17 +455,19 @@ void wrongPasswordDialog(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async {
|
void enterPasswordDialog(
|
||||||
|
SessionID sessionId, OverlayDialogManager dialogManager) async {
|
||||||
await _connectDialog(
|
await _connectDialog(
|
||||||
id,
|
sessionId,
|
||||||
dialogManager,
|
dialogManager,
|
||||||
passwordController: TextEditingController(),
|
passwordController: TextEditingController(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enterUserLoginDialog(String id, OverlayDialogManager dialogManager) async {
|
void enterUserLoginDialog(
|
||||||
|
SessionID sessionId, OverlayDialogManager dialogManager) async {
|
||||||
await _connectDialog(
|
await _connectDialog(
|
||||||
id,
|
sessionId,
|
||||||
dialogManager,
|
dialogManager,
|
||||||
osUsernameController: TextEditingController(),
|
osUsernameController: TextEditingController(),
|
||||||
osPasswordController: TextEditingController(),
|
osPasswordController: TextEditingController(),
|
||||||
@ -473,9 +475,9 @@ void enterUserLoginDialog(String id, OverlayDialogManager dialogManager) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void enterUserLoginAndPasswordDialog(
|
void enterUserLoginAndPasswordDialog(
|
||||||
String id, OverlayDialogManager dialogManager) async {
|
SessionID sessionId, OverlayDialogManager dialogManager) async {
|
||||||
await _connectDialog(
|
await _connectDialog(
|
||||||
id,
|
sessionId,
|
||||||
dialogManager,
|
dialogManager,
|
||||||
osUsernameController: TextEditingController(),
|
osUsernameController: TextEditingController(),
|
||||||
osPasswordController: TextEditingController(),
|
osPasswordController: TextEditingController(),
|
||||||
@ -484,7 +486,7 @@ void enterUserLoginAndPasswordDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
_connectDialog(
|
_connectDialog(
|
||||||
String id,
|
SessionID sessionId,
|
||||||
OverlayDialogManager dialogManager, {
|
OverlayDialogManager dialogManager, {
|
||||||
TextEditingController? osUsernameController,
|
TextEditingController? osUsernameController,
|
||||||
TextEditingController? osPasswordController,
|
TextEditingController? osPasswordController,
|
||||||
@ -492,11 +494,13 @@ _connectDialog(
|
|||||||
}) async {
|
}) async {
|
||||||
var rememberPassword = false;
|
var rememberPassword = false;
|
||||||
if (passwordController != null) {
|
if (passwordController != null) {
|
||||||
rememberPassword = await bind.sessionGetRemember(id: id) ?? false;
|
rememberPassword =
|
||||||
|
await bind.sessionGetRemember(sessionId: sessionId) ?? false;
|
||||||
}
|
}
|
||||||
var rememberAccount = false;
|
var rememberAccount = false;
|
||||||
if (osUsernameController != null) {
|
if (osUsernameController != null) {
|
||||||
rememberAccount = await bind.sessionGetRemember(id: id) ?? false;
|
rememberAccount =
|
||||||
|
await bind.sessionGetRemember(sessionId: sessionId) ?? false;
|
||||||
}
|
}
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show((setState, close, context) {
|
dialogManager.show((setState, close, context) {
|
||||||
@ -511,13 +515,15 @@ _connectDialog(
|
|||||||
final password = passwordController?.text.trim() ?? '';
|
final password = passwordController?.text.trim() ?? '';
|
||||||
if (passwordController != null && password.isEmpty) return;
|
if (passwordController != null && password.isEmpty) return;
|
||||||
if (rememberAccount) {
|
if (rememberAccount) {
|
||||||
bind.sessionPeerOption(id: id, name: 'os-username', value: osUsername);
|
bind.sessionPeerOption(
|
||||||
bind.sessionPeerOption(id: id, name: 'os-password', value: osPassword);
|
sessionId: sessionId, name: 'os-username', value: osUsername);
|
||||||
|
bind.sessionPeerOption(
|
||||||
|
sessionId: sessionId, name: 'os-password', value: osPassword);
|
||||||
}
|
}
|
||||||
gFFI.login(
|
gFFI.login(
|
||||||
osUsername,
|
osUsername,
|
||||||
osPassword,
|
osPassword,
|
||||||
id,
|
sessionId,
|
||||||
password,
|
password,
|
||||||
rememberPassword,
|
rememberPassword,
|
||||||
);
|
);
|
||||||
@ -650,10 +656,10 @@ _connectDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showWaitUacDialog(
|
void showWaitUacDialog(
|
||||||
String id, OverlayDialogManager dialogManager, String type) {
|
SessionID sessionId, OverlayDialogManager dialogManager, String type) {
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show(
|
dialogManager.show(
|
||||||
tag: '$id-wait-uac',
|
tag: '$sessionId-wait-uac',
|
||||||
(setState, close, context) => CustomAlertDialog(
|
(setState, close, context) => CustomAlertDialog(
|
||||||
title: null,
|
title: null,
|
||||||
content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip'),
|
content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip'),
|
||||||
@ -661,7 +667,8 @@ void showWaitUacDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Another username && password dialog?
|
// Another username && password dialog?
|
||||||
void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) {
|
void showRequestElevationDialog(
|
||||||
|
SessionID sessionId, OverlayDialogManager dialogManager) {
|
||||||
RxString groupValue = ''.obs;
|
RxString groupValue = ''.obs;
|
||||||
RxString errUser = ''.obs;
|
RxString errUser = ''.obs;
|
||||||
RxString errPwd = ''.obs;
|
RxString errPwd = ''.obs;
|
||||||
@ -785,7 +792,8 @@ void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show(tag: '$id-request-elevation', (setState, close, context) {
|
dialogManager.show(tag: '$sessionId-request-elevation',
|
||||||
|
(setState, close, context) {
|
||||||
void submit() {
|
void submit() {
|
||||||
if (groupValue.value == 'logon') {
|
if (groupValue.value == 'logon') {
|
||||||
if (userController.text.isEmpty) {
|
if (userController.text.isEmpty) {
|
||||||
@ -797,11 +805,11 @@ void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bind.sessionElevateWithLogon(
|
bind.sessionElevateWithLogon(
|
||||||
id: id,
|
sessionId: sessionId,
|
||||||
username: userController.text,
|
username: userController.text,
|
||||||
password: pwdController.text);
|
password: pwdController.text);
|
||||||
} else {
|
} else {
|
||||||
bind.sessionElevateDirect(id: id);
|
bind.sessionElevateDirect(sessionId: sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -828,20 +836,20 @@ void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showOnBlockDialog(
|
void showOnBlockDialog(
|
||||||
String id,
|
SessionID sessionId,
|
||||||
String type,
|
String type,
|
||||||
String title,
|
String title,
|
||||||
String text,
|
String text,
|
||||||
OverlayDialogManager dialogManager,
|
OverlayDialogManager dialogManager,
|
||||||
) {
|
) {
|
||||||
if (dialogManager.existing('$id-wait-uac') ||
|
if (dialogManager.existing('$sessionId-wait-uac') ||
|
||||||
dialogManager.existing('$id-request-elevation')) {
|
dialogManager.existing('$sessionId-request-elevation')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dialogManager.show(tag: '$id-$type', (setState, close, context) {
|
dialogManager.show(tag: '$sessionId-$type', (setState, close, context) {
|
||||||
void submit() {
|
void submit() {
|
||||||
close();
|
close();
|
||||||
showRequestElevationDialog(id, dialogManager);
|
showRequestElevationDialog(sessionId, dialogManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
@ -858,12 +866,12 @@ void showOnBlockDialog(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void showElevationError(String id, String type, String title, String text,
|
void showElevationError(SessionID sessionId, String type, String title,
|
||||||
OverlayDialogManager dialogManager) {
|
String text, OverlayDialogManager dialogManager) {
|
||||||
dialogManager.show(tag: '$id-$type', (setState, close, context) {
|
dialogManager.show(tag: '$sessionId-$type', (setState, close, context) {
|
||||||
void submit() {
|
void submit() {
|
||||||
close();
|
close();
|
||||||
showRequestElevationDialog(id, dialogManager);
|
showRequestElevationDialog(sessionId, dialogManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
@ -881,8 +889,8 @@ void showElevationError(String id, String type, String title, String text,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void showWaitAcceptDialog(String id, String type, String title, String text,
|
void showWaitAcceptDialog(SessionID sessionId, String type, String title,
|
||||||
OverlayDialogManager dialogManager) {
|
String text, OverlayDialogManager dialogManager) {
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show((setState, close, context) {
|
dialogManager.show((setState, close, context) {
|
||||||
onCancel() {
|
onCancel() {
|
||||||
@ -900,8 +908,8 @@ void showWaitAcceptDialog(String id, String type, String title, String text,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void showRestartRemoteDevice(
|
void showRestartRemoteDevice(PeerInfo pi, String id, SessionID sessionId,
|
||||||
PeerInfo pi, String id, OverlayDialogManager dialogManager) async {
|
OverlayDialogManager dialogManager) async {
|
||||||
final res = await dialogManager
|
final res = await dialogManager
|
||||||
.show<bool>((setState, close, context) => CustomAlertDialog(
|
.show<bool>((setState, close, context) => CustomAlertDialog(
|
||||||
title: Row(children: [
|
title: Row(children: [
|
||||||
@ -928,26 +936,33 @@ void showRestartRemoteDevice(
|
|||||||
onCancel: close,
|
onCancel: close,
|
||||||
onSubmit: () => close(true),
|
onSubmit: () => close(true),
|
||||||
));
|
));
|
||||||
if (res == true) bind.sessionRestartRemoteDevice(id: id);
|
if (res == true) bind.sessionRestartRemoteDevice(sessionId: sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
showSetOSPassword(
|
showSetOSPassword(
|
||||||
String id,
|
SessionID sessionId,
|
||||||
bool login,
|
bool login,
|
||||||
OverlayDialogManager dialogManager,
|
OverlayDialogManager dialogManager,
|
||||||
) async {
|
) async {
|
||||||
final controller = TextEditingController();
|
final controller = TextEditingController();
|
||||||
var password = await bind.sessionGetOption(id: id, arg: 'os-password') ?? '';
|
var password =
|
||||||
var autoLogin = await bind.sessionGetOption(id: id, arg: 'auto-login') != '';
|
await bind.sessionGetOption(sessionId: sessionId, arg: 'os-password') ??
|
||||||
|
'';
|
||||||
|
var autoLogin =
|
||||||
|
await bind.sessionGetOption(sessionId: sessionId, arg: 'auto-login') !=
|
||||||
|
'';
|
||||||
controller.text = password;
|
controller.text = password;
|
||||||
dialogManager.show((setState, close, context) {
|
dialogManager.show((setState, close, context) {
|
||||||
submit() {
|
submit() {
|
||||||
var text = controller.text.trim();
|
var text = controller.text.trim();
|
||||||
bind.sessionPeerOption(id: id, name: 'os-password', value: text);
|
|
||||||
bind.sessionPeerOption(
|
bind.sessionPeerOption(
|
||||||
id: id, name: 'auto-login', value: autoLogin ? 'Y' : '');
|
sessionId: sessionId, name: 'os-password', value: text);
|
||||||
|
bind.sessionPeerOption(
|
||||||
|
sessionId: sessionId,
|
||||||
|
name: 'auto-login',
|
||||||
|
value: autoLogin ? 'Y' : '');
|
||||||
if (text != '' && login) {
|
if (text != '' && login) {
|
||||||
bind.sessionInputOsPassword(id: id, value: text);
|
bind.sessionInputOsPassword(sessionId: sessionId, value: text);
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
@ -999,21 +1014,27 @@ showSetOSPassword(
|
|||||||
}
|
}
|
||||||
|
|
||||||
showSetOSAccount(
|
showSetOSAccount(
|
||||||
String id,
|
SessionID sessionId,
|
||||||
OverlayDialogManager dialogManager,
|
OverlayDialogManager dialogManager,
|
||||||
) async {
|
) async {
|
||||||
final usernameController = TextEditingController();
|
final usernameController = TextEditingController();
|
||||||
final passwdController = TextEditingController();
|
final passwdController = TextEditingController();
|
||||||
var username = await bind.sessionGetOption(id: id, arg: 'os-username') ?? '';
|
var username =
|
||||||
var password = await bind.sessionGetOption(id: id, arg: 'os-password') ?? '';
|
await bind.sessionGetOption(sessionId: sessionId, arg: 'os-username') ??
|
||||||
|
'';
|
||||||
|
var password =
|
||||||
|
await bind.sessionGetOption(sessionId: sessionId, arg: 'os-password') ??
|
||||||
|
'';
|
||||||
usernameController.text = username;
|
usernameController.text = username;
|
||||||
passwdController.text = password;
|
passwdController.text = password;
|
||||||
dialogManager.show((setState, close, context) {
|
dialogManager.show((setState, close, context) {
|
||||||
submit() {
|
submit() {
|
||||||
final username = usernameController.text.trim();
|
final username = usernameController.text.trim();
|
||||||
final password = usernameController.text.trim();
|
final password = usernameController.text.trim();
|
||||||
bind.sessionPeerOption(id: id, name: 'os-username', value: username);
|
bind.sessionPeerOption(
|
||||||
bind.sessionPeerOption(id: id, name: 'os-password', value: password);
|
sessionId: sessionId, name: 'os-username', value: username);
|
||||||
|
bind.sessionPeerOption(
|
||||||
|
sessionId: sessionId, name: 'os-password', value: password);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1077,13 +1098,13 @@ showSetOSAccount(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
showAuditDialog(String id, dialogManager) async {
|
showAuditDialog(SessionID sessionId, dialogManager) async {
|
||||||
final controller = TextEditingController();
|
final controller = TextEditingController();
|
||||||
dialogManager.show((setState, close) {
|
dialogManager.show((setState, close) {
|
||||||
submit() {
|
submit() {
|
||||||
var text = controller.text.trim();
|
var text = controller.text.trim();
|
||||||
if (text != '') {
|
if (text != '') {
|
||||||
bind.sessionSendNote(id: id, note: text);
|
bind.sessionSendNote(sessionId: sessionId, note: text);
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
@ -1139,10 +1160,10 @@ showAuditDialog(String id, dialogManager) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showConfirmSwitchSidesDialog(
|
void showConfirmSwitchSidesDialog(
|
||||||
String id, OverlayDialogManager dialogManager) async {
|
SessionID sessionId, String id, OverlayDialogManager dialogManager) async {
|
||||||
dialogManager.show((setState, close, context) {
|
dialogManager.show((setState, close, context) {
|
||||||
submit() async {
|
submit() async {
|
||||||
await bind.sessionSwitchSides(id: id);
|
await bind.sessionSwitchSides(sessionId: sessionId);
|
||||||
closeConnection(id: id);
|
closeConnection(id: id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1159,7 +1180,7 @@ void showConfirmSwitchSidesDialog(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
customImageQualityDialog(String id, FFI ffi) async {
|
customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async {
|
||||||
double qualityInitValue = 50;
|
double qualityInitValue = 50;
|
||||||
double fpsInitValue = 30;
|
double fpsInitValue = 30;
|
||||||
bool qualitySet = false;
|
bool qualitySet = false;
|
||||||
@ -1167,20 +1188,22 @@ customImageQualityDialog(String id, FFI ffi) async {
|
|||||||
setCustomValues({double? quality, double? fps}) async {
|
setCustomValues({double? quality, double? fps}) async {
|
||||||
if (quality != null) {
|
if (quality != null) {
|
||||||
qualitySet = true;
|
qualitySet = true;
|
||||||
await bind.sessionSetCustomImageQuality(id: id, value: quality.toInt());
|
await bind.sessionSetCustomImageQuality(
|
||||||
|
sessionId: sessionId, value: quality.toInt());
|
||||||
}
|
}
|
||||||
if (fps != null) {
|
if (fps != null) {
|
||||||
fpsSet = true;
|
fpsSet = true;
|
||||||
await bind.sessionSetCustomFps(id: id, fps: fps.toInt());
|
await bind.sessionSetCustomFps(sessionId: sessionId, fps: fps.toInt());
|
||||||
}
|
}
|
||||||
if (!qualitySet) {
|
if (!qualitySet) {
|
||||||
qualitySet = true;
|
qualitySet = true;
|
||||||
await bind.sessionSetCustomImageQuality(
|
await bind.sessionSetCustomImageQuality(
|
||||||
id: id, value: qualityInitValue.toInt());
|
sessionId: sessionId, value: qualityInitValue.toInt());
|
||||||
}
|
}
|
||||||
if (!fpsSet) {
|
if (!fpsSet) {
|
||||||
fpsSet = true;
|
fpsSet = true;
|
||||||
await bind.sessionSetCustomFps(id: id, fps: fpsInitValue.toInt());
|
await bind.sessionSetCustomFps(
|
||||||
|
sessionId: sessionId, fps: fpsInitValue.toInt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,7 +1213,7 @@ customImageQualityDialog(String id, FFI ffi) async {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// quality
|
// quality
|
||||||
final quality = await bind.sessionGetCustomImageQuality(id: id);
|
final quality = await bind.sessionGetCustomImageQuality(sessionId: sessionId);
|
||||||
qualityInitValue =
|
qualityInitValue =
|
||||||
quality != null && quality.isNotEmpty ? quality[0].toDouble() : 50.0;
|
quality != null && quality.isNotEmpty ? quality[0].toDouble() : 50.0;
|
||||||
const qualityMinValue = 10.0;
|
const qualityMinValue = 10.0;
|
||||||
@ -1238,7 +1261,8 @@ customImageQualityDialog(String id, FFI ffi) async {
|
|||||||
],
|
],
|
||||||
));
|
));
|
||||||
// fps
|
// fps
|
||||||
final fpsOption = await bind.sessionGetOption(id: id, arg: 'custom-fps');
|
final fpsOption =
|
||||||
|
await bind.sessionGetOption(sessionId: sessionId, arg: 'custom-fps');
|
||||||
fpsInitValue = fpsOption == null ? 30 : double.tryParse(fpsOption) ?? 30;
|
fpsInitValue = fpsOption == null ? 30 : double.tryParse(fpsOption) ?? 30;
|
||||||
if (fpsInitValue < 5 || fpsInitValue > 120) {
|
if (fpsInitValue < 5 || fpsInitValue > 120) {
|
||||||
fpsInitValue = 30;
|
fpsInitValue = 30;
|
||||||
|
@ -735,7 +735,6 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
await bind.mainRemovePeer(id: id);
|
await bind.mainRemovePeer(id: id);
|
||||||
}
|
}
|
||||||
removePreference(id);
|
|
||||||
await reloadFunc();
|
await reloadFunc();
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
final ffiModel = ffi.ffiModel;
|
final ffiModel = ffi.ffiModel;
|
||||||
final pi = ffiModel.pi;
|
final pi = ffiModel.pi;
|
||||||
final perms = ffiModel.permissions;
|
final perms = ffiModel.permissions;
|
||||||
|
final sessionId = ffi.sessionId;
|
||||||
|
|
||||||
List<TTextMenu> v = [];
|
List<TTextMenu> v = [];
|
||||||
// elevation
|
// elevation
|
||||||
@ -55,7 +56,8 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
v.add(
|
v.add(
|
||||||
TTextMenu(
|
TTextMenu(
|
||||||
child: Text(translate('Request Elevation')),
|
child: Text(translate('Request Elevation')),
|
||||||
onPressed: () => showRequestElevationDialog(id, ffi.dialogManager)),
|
onPressed: () =>
|
||||||
|
showRequestElevationDialog(sessionId, ffi.dialogManager)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// osAccount / osPassword
|
// osAccount / osPassword
|
||||||
@ -70,8 +72,8 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
]),
|
]),
|
||||||
trailingIcon: Transform.scale(scale: 0.8, child: Icon(Icons.edit)),
|
trailingIcon: Transform.scale(scale: 0.8, child: Icon(Icons.edit)),
|
||||||
onPressed: () => pi.is_headless
|
onPressed: () => pi.is_headless
|
||||||
? showSetOSAccount(id, ffi.dialogManager)
|
? showSetOSAccount(sessionId, ffi.dialogManager)
|
||||||
: showSetOSPassword(id, false, ffi.dialogManager)),
|
: showSetOSPassword(sessionId, false, ffi.dialogManager)),
|
||||||
);
|
);
|
||||||
// paste
|
// paste
|
||||||
if (isMobile && perms['keyboard'] != false && perms['clipboard'] != false) {
|
if (isMobile && perms['keyboard'] != false && perms['clipboard'] != false) {
|
||||||
@ -80,7 +82,8 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
|
ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
|
||||||
if (data != null && data.text != null) {
|
if (data != null && data.text != null) {
|
||||||
bind.sessionInputString(id: id, value: data.text ?? "");
|
bind.sessionInputString(
|
||||||
|
sessionId: sessionId, value: data.text ?? "");
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -107,11 +110,13 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
// note
|
// note
|
||||||
if (bind.sessionGetAuditServerSync(id: id, typ: "conn").isNotEmpty) {
|
if (bind
|
||||||
|
.sessionGetAuditServerSync(sessionId: sessionId, typ: "conn")
|
||||||
|
.isNotEmpty) {
|
||||||
v.add(
|
v.add(
|
||||||
TTextMenu(
|
TTextMenu(
|
||||||
child: Text(translate('Note')),
|
child: Text(translate('Note')),
|
||||||
onPressed: () => showAuditDialog(id, ffi.dialogManager)),
|
onPressed: () => showAuditDialog(sessionId, ffi.dialogManager)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// divider
|
// divider
|
||||||
@ -125,7 +130,7 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
v.add(
|
v.add(
|
||||||
TTextMenu(
|
TTextMenu(
|
||||||
child: Text('${translate("Insert")} Ctrl + Alt + Del'),
|
child: Text('${translate("Insert")} Ctrl + Alt + Del'),
|
||||||
onPressed: () => bind.sessionCtrlAltDel(id: id)),
|
onPressed: () => bind.sessionCtrlAltDel(sessionId: sessionId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// restart
|
// restart
|
||||||
@ -136,7 +141,8 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
v.add(
|
v.add(
|
||||||
TTextMenu(
|
TTextMenu(
|
||||||
child: Text(translate('Restart Remote Device')),
|
child: Text(translate('Restart Remote Device')),
|
||||||
onPressed: () => showRestartRemoteDevice(pi, id, ffi.dialogManager)),
|
onPressed: () =>
|
||||||
|
showRestartRemoteDevice(pi, id, sessionId, ffi.dialogManager)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// insertLock
|
// insertLock
|
||||||
@ -144,7 +150,7 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
v.add(
|
v.add(
|
||||||
TTextMenu(
|
TTextMenu(
|
||||||
child: Text(translate('Insert Lock')),
|
child: Text(translate('Insert Lock')),
|
||||||
onPressed: () => bind.sessionLockScreen(id: id)),
|
onPressed: () => bind.sessionLockScreen(sessionId: sessionId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// blockUserInput
|
// blockUserInput
|
||||||
@ -157,7 +163,8 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
RxBool blockInput = BlockInputState.find(id);
|
RxBool blockInput = BlockInputState.find(id);
|
||||||
bind.sessionToggleOption(
|
bind.sessionToggleOption(
|
||||||
id: id, value: '${blockInput.value ? 'un' : ''}block-input');
|
sessionId: sessionId,
|
||||||
|
value: '${blockInput.value ? 'un' : ''}block-input');
|
||||||
blockInput.value = !blockInput.value;
|
blockInput.value = !blockInput.value;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -169,13 +176,14 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
version_cmp(pi.version, '1.2.0') >= 0) {
|
version_cmp(pi.version, '1.2.0') >= 0) {
|
||||||
v.add(TTextMenu(
|
v.add(TTextMenu(
|
||||||
child: Text(translate('Switch Sides')),
|
child: Text(translate('Switch Sides')),
|
||||||
onPressed: () => showConfirmSwitchSidesDialog(id, ffi.dialogManager)));
|
onPressed: () =>
|
||||||
|
showConfirmSwitchSidesDialog(sessionId, id, ffi.dialogManager)));
|
||||||
}
|
}
|
||||||
// refresh
|
// refresh
|
||||||
if (pi.version.isNotEmpty) {
|
if (pi.version.isNotEmpty) {
|
||||||
v.add(TTextMenu(
|
v.add(TTextMenu(
|
||||||
child: Text(translate('Refresh')),
|
child: Text(translate('Refresh')),
|
||||||
onPressed: () => bind.sessionRefresh(id: id)));
|
onPressed: () => bind.sessionRefresh(sessionId: sessionId)));
|
||||||
}
|
}
|
||||||
// record
|
// record
|
||||||
var codecFormat = ffi.qualityMonitorModel.data.codecFormat;
|
var codecFormat = ffi.qualityMonitorModel.data.codecFormat;
|
||||||
@ -213,11 +221,12 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
|
|||||||
|
|
||||||
Future<List<TRadioMenu<String>>> toolbarViewStyle(
|
Future<List<TRadioMenu<String>>> toolbarViewStyle(
|
||||||
BuildContext context, String id, FFI ffi) async {
|
BuildContext context, String id, FFI ffi) async {
|
||||||
final groupValue = await bind.sessionGetViewStyle(id: id) ?? '';
|
final groupValue =
|
||||||
|
await bind.sessionGetViewStyle(sessionId: ffi.sessionId) ?? '';
|
||||||
void onChanged(String? value) async {
|
void onChanged(String? value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
bind
|
bind
|
||||||
.sessionSetViewStyle(id: id, value: value)
|
.sessionSetViewStyle(sessionId: ffi.sessionId, value: value)
|
||||||
.then((_) => ffi.canvasModel.updateViewStyle());
|
.then((_) => ffi.canvasModel.updateViewStyle());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,10 +246,11 @@ Future<List<TRadioMenu<String>>> toolbarViewStyle(
|
|||||||
|
|
||||||
Future<List<TRadioMenu<String>>> toolbarImageQuality(
|
Future<List<TRadioMenu<String>>> toolbarImageQuality(
|
||||||
BuildContext context, String id, FFI ffi) async {
|
BuildContext context, String id, FFI ffi) async {
|
||||||
final groupValue = await bind.sessionGetImageQuality(id: id) ?? '';
|
final groupValue =
|
||||||
|
await bind.sessionGetImageQuality(sessionId: ffi.sessionId) ?? '';
|
||||||
onChanged(String? value) async {
|
onChanged(String? value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
await bind.sessionSetImageQuality(id: id, value: value);
|
await bind.sessionSetImageQuality(sessionId: ffi.sessionId, value: value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -265,7 +275,7 @@ Future<List<TRadioMenu<String>>> toolbarImageQuality(
|
|||||||
groupValue: groupValue,
|
groupValue: groupValue,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
onChanged(value);
|
onChanged(value);
|
||||||
customImageQualityDialog(id, ffi);
|
customImageQualityDialog(ffi.sessionId, id, ffi);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -273,9 +283,12 @@ Future<List<TRadioMenu<String>>> toolbarImageQuality(
|
|||||||
|
|
||||||
Future<List<TRadioMenu<String>>> toolbarCodec(
|
Future<List<TRadioMenu<String>>> toolbarCodec(
|
||||||
BuildContext context, String id, FFI ffi) async {
|
BuildContext context, String id, FFI ffi) async {
|
||||||
final alternativeCodecs = await bind.sessionAlternativeCodecs(id: id);
|
final sessionId = ffi.sessionId;
|
||||||
final groupValue =
|
final alternativeCodecs =
|
||||||
await bind.sessionGetOption(id: id, arg: 'codec-preference') ?? '';
|
await bind.sessionAlternativeCodecs(sessionId: sessionId);
|
||||||
|
final groupValue = await bind.sessionGetOption(
|
||||||
|
sessionId: sessionId, arg: 'codec-preference') ??
|
||||||
|
'';
|
||||||
final List<bool> codecs = [];
|
final List<bool> codecs = [];
|
||||||
try {
|
try {
|
||||||
final Map codecsJson = jsonDecode(alternativeCodecs);
|
final Map codecsJson = jsonDecode(alternativeCodecs);
|
||||||
@ -296,8 +309,8 @@ Future<List<TRadioMenu<String>>> toolbarCodec(
|
|||||||
onChanged(String? value) async {
|
onChanged(String? value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
await bind.sessionPeerOption(
|
await bind.sessionPeerOption(
|
||||||
id: id, name: 'codec-preference', value: value);
|
sessionId: sessionId, name: 'codec-preference', value: value);
|
||||||
bind.sessionChangePreferCodec(id: id);
|
bind.sessionChangePreferCodec(sessionId: sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRadioMenu<String> radio(String label, String value, bool enabled) {
|
TRadioMenu<String> radio(String label, String value, bool enabled) {
|
||||||
@ -324,6 +337,7 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
final ffiModel = ffi.ffiModel;
|
final ffiModel = ffi.ffiModel;
|
||||||
final pi = ffiModel.pi;
|
final pi = ffiModel.pi;
|
||||||
final perms = ffiModel.permissions;
|
final perms = ffiModel.permissions;
|
||||||
|
final sessionId = ffi.sessionId;
|
||||||
|
|
||||||
// show remote cursor
|
// show remote cursor
|
||||||
if (pi.platform != kPeerPlatformAndroid &&
|
if (pi.platform != kPeerPlatformAndroid &&
|
||||||
@ -338,14 +352,15 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
onChanged: enabled
|
onChanged: enabled
|
||||||
? (value) async {
|
? (value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
await bind.sessionToggleOption(id: id, value: option);
|
await bind.sessionToggleOption(
|
||||||
state.value =
|
sessionId: sessionId, value: option);
|
||||||
bind.sessionGetToggleOptionSync(id: id, arg: option);
|
state.value = bind.sessionGetToggleOptionSync(
|
||||||
|
sessionId: sessionId, arg: option);
|
||||||
}
|
}
|
||||||
: null));
|
: null));
|
||||||
}
|
}
|
||||||
// zoom cursor
|
// zoom cursor
|
||||||
final viewStyle = await bind.sessionGetViewStyle(id: id) ?? '';
|
final viewStyle = await bind.sessionGetViewStyle(sessionId: sessionId) ?? '';
|
||||||
if (!isMobile &&
|
if (!isMobile &&
|
||||||
pi.platform != kPeerPlatformAndroid &&
|
pi.platform != kPeerPlatformAndroid &&
|
||||||
viewStyle != kRemoteViewStyleOriginal) {
|
viewStyle != kRemoteViewStyleOriginal) {
|
||||||
@ -356,30 +371,32 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
value: peerState.value,
|
value: peerState.value,
|
||||||
onChanged: (value) async {
|
onChanged: (value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
await bind.sessionToggleOption(id: id, value: option);
|
await bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
peerState.value = bind.sessionGetToggleOptionSync(id: id, arg: option);
|
peerState.value =
|
||||||
|
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option);
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// show quality monitor
|
// show quality monitor
|
||||||
final option = 'show-quality-monitor';
|
final option = 'show-quality-monitor';
|
||||||
v.add(TToggleMenu(
|
v.add(TToggleMenu(
|
||||||
value: bind.sessionGetToggleOptionSync(id: id, arg: option),
|
value: bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option),
|
||||||
onChanged: (value) async {
|
onChanged: (value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
await bind.sessionToggleOption(id: id, value: option);
|
await bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
ffi.qualityMonitorModel.checkShowQualityMonitor(id);
|
ffi.qualityMonitorModel.checkShowQualityMonitor(sessionId);
|
||||||
},
|
},
|
||||||
child: Text(translate('Show quality monitor'))));
|
child: Text(translate('Show quality monitor'))));
|
||||||
// mute
|
// mute
|
||||||
if (perms['audio'] != false) {
|
if (perms['audio'] != false) {
|
||||||
final option = 'disable-audio';
|
final option = 'disable-audio';
|
||||||
final value = bind.sessionGetToggleOptionSync(id: id, arg: option);
|
final value =
|
||||||
|
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option);
|
||||||
v.add(TToggleMenu(
|
v.add(TToggleMenu(
|
||||||
value: value,
|
value: value,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
bind.sessionToggleOption(id: id, value: option);
|
bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
},
|
},
|
||||||
child: Text(translate('Mute'))));
|
child: Text(translate('Mute'))));
|
||||||
}
|
}
|
||||||
@ -388,12 +405,13 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
pi.platform == kPeerPlatformWindows &&
|
pi.platform == kPeerPlatformWindows &&
|
||||||
perms['file'] != false) {
|
perms['file'] != false) {
|
||||||
final option = 'enable-file-transfer';
|
final option = 'enable-file-transfer';
|
||||||
final value = bind.sessionGetToggleOptionSync(id: id, arg: option);
|
final value =
|
||||||
|
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option);
|
||||||
v.add(TToggleMenu(
|
v.add(TToggleMenu(
|
||||||
value: value,
|
value: value,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
bind.sessionToggleOption(id: id, value: option);
|
bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
},
|
},
|
||||||
child: Text(translate('Allow file copy and paste'))));
|
child: Text(translate('Allow file copy and paste'))));
|
||||||
}
|
}
|
||||||
@ -401,14 +419,15 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
if (ffiModel.keyboard && perms['clipboard'] != false) {
|
if (ffiModel.keyboard && perms['clipboard'] != false) {
|
||||||
final enabled = !ffiModel.viewOnly;
|
final enabled = !ffiModel.viewOnly;
|
||||||
final option = 'disable-clipboard';
|
final option = 'disable-clipboard';
|
||||||
var value = bind.sessionGetToggleOptionSync(id: id, arg: option);
|
var value =
|
||||||
|
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option);
|
||||||
if (ffiModel.viewOnly) value = true;
|
if (ffiModel.viewOnly) value = true;
|
||||||
v.add(TToggleMenu(
|
v.add(TToggleMenu(
|
||||||
value: value,
|
value: value,
|
||||||
onChanged: enabled
|
onChanged: enabled
|
||||||
? (value) {
|
? (value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
bind.sessionToggleOption(id: id, value: option);
|
bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: Text(translate('Disable clipboard'))));
|
child: Text(translate('Disable clipboard'))));
|
||||||
@ -416,12 +435,13 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
// lock after session end
|
// lock after session end
|
||||||
if (ffiModel.keyboard) {
|
if (ffiModel.keyboard) {
|
||||||
final option = 'lock-after-session-end';
|
final option = 'lock-after-session-end';
|
||||||
final value = bind.sessionGetToggleOptionSync(id: id, arg: option);
|
final value =
|
||||||
|
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option);
|
||||||
v.add(TToggleMenu(
|
v.add(TToggleMenu(
|
||||||
value: value,
|
value: value,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
bind.sessionToggleOption(id: id, value: option);
|
bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
},
|
},
|
||||||
child: Text(translate('Lock after session end'))));
|
child: Text(translate('Lock after session end'))));
|
||||||
}
|
}
|
||||||
@ -434,11 +454,11 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
if (ffiModel.pi.currentDisplay != 0) {
|
if (ffiModel.pi.currentDisplay != 0) {
|
||||||
msgBox(id, 'custom-nook-nocancel-hasclose', 'info',
|
msgBox(sessionId, 'custom-nook-nocancel-hasclose', 'info',
|
||||||
'Please switch to Display 1 first', '', ffi.dialogManager);
|
'Please switch to Display 1 first', '', ffi.dialogManager);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bind.sessionToggleOption(id: id, value: option);
|
bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
},
|
},
|
||||||
child: Text(translate('Privacy mode'))));
|
child: Text(translate('Privacy mode'))));
|
||||||
}
|
}
|
||||||
@ -447,12 +467,13 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
|||||||
((Platform.isMacOS && pi.platform != kPeerPlatformMacOS) ||
|
((Platform.isMacOS && pi.platform != kPeerPlatformMacOS) ||
|
||||||
(!Platform.isMacOS && pi.platform == kPeerPlatformMacOS))) {
|
(!Platform.isMacOS && pi.platform == kPeerPlatformMacOS))) {
|
||||||
final option = 'allow_swap_key';
|
final option = 'allow_swap_key';
|
||||||
final value = bind.sessionGetToggleOptionSync(id: id, arg: option);
|
final value =
|
||||||
|
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option);
|
||||||
v.add(TToggleMenu(
|
v.add(TToggleMenu(
|
||||||
value: value,
|
value: value,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
bind.sessionToggleOption(id: id, value: option);
|
bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
},
|
},
|
||||||
child: Text(translate('Swap control-command key'))));
|
child: Text(translate('Swap control-command key'))));
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,8 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
child: FutureBuilder<String>(
|
child: FutureBuilder<String>(
|
||||||
future: bind.sessionGetPlatform(
|
future: bind.sessionGetPlatform(
|
||||||
id: _ffi.id, isRemote: !isLocal),
|
sessionId: _ffi.sessionId,
|
||||||
|
isRemote: !isLocal),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData &&
|
if (snapshot.hasData &&
|
||||||
snapshot.data!.isNotEmpty) {
|
snapshot.data!.isNotEmpty) {
|
||||||
|
@ -194,7 +194,7 @@ class _PortForwardPageState extends State<PortForwardPage>
|
|||||||
(remoteHostController.text.isEmpty ||
|
(remoteHostController.text.isEmpty ||
|
||||||
remoteHostController.text.trim().isNotEmpty)) {
|
remoteHostController.text.trim().isNotEmpty)) {
|
||||||
await bind.sessionAddPortForward(
|
await bind.sessionAddPortForward(
|
||||||
id: 'pf_${widget.id}',
|
sessionId: _ffi.sessionId,
|
||||||
localPort: localPort,
|
localPort: localPort,
|
||||||
remoteHost: remoteHostController.text.trim().isEmpty
|
remoteHost: remoteHostController.text.trim().isEmpty
|
||||||
? 'localhost'
|
? 'localhost'
|
||||||
@ -254,7 +254,7 @@ class _PortForwardPageState extends State<PortForwardPage>
|
|||||||
icon: const Icon(Icons.close),
|
icon: const Icon(Icons.close),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await bind.sessionRemovePortForward(
|
await bind.sessionRemovePortForward(
|
||||||
id: 'pf_${widget.id}', localPort: pf.localPort);
|
sessionId: _ffi.sessionId, localPort: pf.localPort);
|
||||||
refreshTunnelConfig();
|
refreshTunnelConfig();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -313,7 +313,7 @@ class _PortForwardPageState extends State<PortForwardPage>
|
|||||||
width: 120,
|
width: 120,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
bind.sessionNewRdp(id: "pf_${widget.id}"),
|
bind.sessionNewRdp(sessionId: _ffi.sessionId),
|
||||||
child: Text(
|
child: Text(
|
||||||
translate('New RDP'),
|
translate('New RDP'),
|
||||||
),
|
),
|
||||||
|
@ -110,12 +110,12 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
|
|||||||
return Platform.isMacOS || kUseCompatibleUiMode
|
return Platform.isMacOS || kUseCompatibleUiMode
|
||||||
? tabWidget
|
? tabWidget
|
||||||
: Obx(
|
: Obx(
|
||||||
() => SubWindowDragToResizeArea(
|
() => SubWindowDragToResizeArea(
|
||||||
child: tabWidget,
|
child: tabWidget,
|
||||||
resizeEdgeSize: stateGlobal.resizeEdgeSize.value,
|
resizeEdgeSize: stateGlobal.resizeEdgeSize.value,
|
||||||
windowId: stateGlobal.windowId,
|
windowId: stateGlobal.windowId,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRemoveId(String id) {
|
void onRemoveId(String id) {
|
||||||
|
@ -76,6 +76,8 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
|
|
||||||
late FFI _ffi;
|
late FFI _ffi;
|
||||||
|
|
||||||
|
SessionID get sessionId => _ffi.sessionId;
|
||||||
|
|
||||||
void _initStates(String id) {
|
void _initStates(String id) {
|
||||||
initSharedStates(id);
|
initSharedStates(id);
|
||||||
_zoomCursor = PeerBoolOption.find(id, 'zoom-cursor');
|
_zoomCursor = PeerBoolOption.find(id, 'zoom-cursor');
|
||||||
@ -117,19 +119,19 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
debugPrint("id: $id, texture_key: $_textureKey");
|
debugPrint("id: $id, texture_key: $_textureKey");
|
||||||
if (id != -1) {
|
if (id != -1) {
|
||||||
final ptr = await textureRenderer.getTexturePtr(_textureKey);
|
final ptr = await textureRenderer.getTexturePtr(_textureKey);
|
||||||
platformFFI.registerTexture(widget.id, ptr);
|
platformFFI.registerTexture(sessionId, ptr);
|
||||||
_textureId.value = id;
|
_textureId.value = id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ffi.ffiModel.updateEventListener(widget.id);
|
_ffi.ffiModel.updateEventListener(sessionId, widget.id);
|
||||||
bind.pluginSyncUi(syncTo: kAppTypeDesktopRemote);
|
bind.pluginSyncUi(syncTo: kAppTypeDesktopRemote);
|
||||||
_ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id);
|
_ffi.qualityMonitorModel.checkShowQualityMonitor(sessionId);
|
||||||
// Session option should be set after models.dart/FFI.start
|
// Session option should be set after models.dart/FFI.start
|
||||||
_showRemoteCursor.value = bind.sessionGetToggleOptionSync(
|
_showRemoteCursor.value = bind.sessionGetToggleOptionSync(
|
||||||
id: widget.id, arg: 'show-remote-cursor');
|
sessionId: sessionId, arg: 'show-remote-cursor');
|
||||||
_zoomCursor.value =
|
_zoomCursor.value = bind.sessionGetToggleOptionSync(
|
||||||
bind.sessionGetToggleOptionSync(id: widget.id, arg: 'zoom-cursor');
|
sessionId: sessionId, arg: 'zoom-cursor');
|
||||||
DesktopMultiWindow.addListener(this);
|
DesktopMultiWindow.addListener(this);
|
||||||
// if (!_isCustomCursorInited) {
|
// if (!_isCustomCursorInited) {
|
||||||
// customCursorController.registerNeedUpdateCursorCallback(
|
// customCursorController.registerNeedUpdateCursorCallback(
|
||||||
@ -203,11 +205,11 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
debugPrint("REMOTE PAGE dispose ${widget.id}");
|
debugPrint("REMOTE PAGE dispose ${widget.id}");
|
||||||
if (useTextureRender) {
|
if (useTextureRender) {
|
||||||
platformFFI.registerTexture(widget.id, 0);
|
platformFFI.registerTexture(sessionId, 0);
|
||||||
textureRenderer.closeTexture(_textureKey);
|
textureRenderer.closeTexture(_textureKey);
|
||||||
}
|
}
|
||||||
// ensure we leave this session, this is a double check
|
// ensure we leave this session, this is a double check
|
||||||
bind.sessionEnterOrLeave(id: widget.id, enter: false);
|
bind.sessionEnterOrLeave(sessionId: sessionId, enter: false);
|
||||||
DesktopMultiWindow.removeListener(this);
|
DesktopMultiWindow.removeListener(this);
|
||||||
_ffi.dialogManager.hideMobileActionsOverlay();
|
_ffi.dialogManager.hideMobileActionsOverlay();
|
||||||
_ffi.recordingModel.onClose();
|
_ffi.recordingModel.onClose();
|
||||||
@ -278,7 +280,7 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
super.build(context);
|
super.build(context);
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
clientClose(widget.id, _ffi.dialogManager);
|
clientClose(sessionId, _ffi.dialogManager);
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
child: MultiProvider(providers: [
|
child: MultiProvider(providers: [
|
||||||
@ -305,7 +307,7 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
if (!_rawKeyFocusNode.hasFocus) {
|
if (!_rawKeyFocusNode.hasFocus) {
|
||||||
_rawKeyFocusNode.requestFocus();
|
_rawKeyFocusNode.requestFocus();
|
||||||
}
|
}
|
||||||
bind.sessionEnterOrLeave(id: widget.id, enter: true);
|
bind.sessionEnterOrLeave(sessionId: sessionId, enter: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +327,7 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
}
|
}
|
||||||
// See [onWindowBlur].
|
// See [onWindowBlur].
|
||||||
if (!Platform.isWindows) {
|
if (!Platform.isWindows) {
|
||||||
bind.sessionEnterOrLeave(id: widget.id, enter: false);
|
bind.sessionEnterOrLeave(sessionId: sessionId, enter: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,11 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
|||||||
if (peerId != null) {
|
if (peerId != null) {
|
||||||
ConnectionTypeState.init(peerId);
|
ConnectionTypeState.init(peerId);
|
||||||
tabController.onSelected = (_, id) {
|
tabController.onSelected = (_, id) {
|
||||||
bind.setCurSessionId(id: id);
|
final remotePage = tabController.state.value.tabs
|
||||||
|
.firstWhere((tab) => tab.key == id)
|
||||||
|
.page as RemotePage;
|
||||||
|
final ffi = remotePage.ffi;
|
||||||
|
bind.setCurSessionId(sessionId: ffi.sessionId);
|
||||||
WindowController.fromWindowId(windowId())
|
WindowController.fromWindowId(windowId())
|
||||||
.setTitle(getWindowNameWithId(id));
|
.setTitle(getWindowNameWithId(id));
|
||||||
};
|
};
|
||||||
@ -243,6 +247,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
|||||||
final ffi = remotePage.ffi;
|
final ffi = remotePage.ffi;
|
||||||
final pi = ffi.ffiModel.pi;
|
final pi = ffi.ffiModel.pi;
|
||||||
final perms = ffi.ffiModel.permissions;
|
final perms = ffi.ffiModel.permissions;
|
||||||
|
final sessionId = ffi.sessionId;
|
||||||
menu.addAll([
|
menu.addAll([
|
||||||
MenuEntryButton<String>(
|
MenuEntryButton<String>(
|
||||||
childBuilder: (TextStyle? style) => Text(
|
childBuilder: (TextStyle? style) => Text(
|
||||||
@ -282,6 +287,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
|||||||
menu.add(MenuEntryDivider<String>());
|
menu.add(MenuEntryDivider<String>());
|
||||||
menu.add(RemoteMenuEntry.showRemoteCursor(
|
menu.add(RemoteMenuEntry.showRemoteCursor(
|
||||||
key,
|
key,
|
||||||
|
sessionId,
|
||||||
padding,
|
padding,
|
||||||
dismissFunc: cancelFunc,
|
dismissFunc: cancelFunc,
|
||||||
));
|
));
|
||||||
@ -289,15 +295,15 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
|||||||
|
|
||||||
if (perms['keyboard'] != false && !ffi.ffiModel.viewOnly) {
|
if (perms['keyboard'] != false && !ffi.ffiModel.viewOnly) {
|
||||||
if (perms['clipboard'] != false) {
|
if (perms['clipboard'] != false) {
|
||||||
menu.add(RemoteMenuEntry.disableClipboard(key, padding,
|
menu.add(RemoteMenuEntry.disableClipboard(sessionId, padding,
|
||||||
dismissFunc: cancelFunc));
|
dismissFunc: cancelFunc));
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.add(
|
menu.add(RemoteMenuEntry.insertLock(sessionId, padding,
|
||||||
RemoteMenuEntry.insertLock(key, padding, dismissFunc: cancelFunc));
|
dismissFunc: cancelFunc));
|
||||||
|
|
||||||
if (pi.platform == kPeerPlatformLinux || pi.sasEnabled) {
|
if (pi.platform == kPeerPlatformLinux || pi.sasEnabled) {
|
||||||
menu.add(RemoteMenuEntry.insertCtrlAltDel(key, padding,
|
menu.add(RemoteMenuEntry.insertCtrlAltDel(sessionId, padding,
|
||||||
dismissFunc: cancelFunc));
|
dismissFunc: cancelFunc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ class _DesktopServerPageState extends State<DesktopServerPage>
|
|||||||
final tabController = gFFI.serverModel.tabController;
|
final tabController = gFFI.serverModel.tabController;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
gFFI.ffiModel.updateEventListener("");
|
gFFI.ffiModel.updateEventListener(gFFI.sessionId, "");
|
||||||
windowManager.addListener(this);
|
windowManager.addListener(this);
|
||||||
tabController.onRemoved = (_, id) {
|
tabController.onRemoved = (_, id) {
|
||||||
onRemoveId(id);
|
onRemoveId(id);
|
||||||
|
@ -141,14 +141,16 @@ class RemoteMenuEntry {
|
|||||||
],
|
],
|
||||||
curOptionGetter: () async {
|
curOptionGetter: () async {
|
||||||
// null means peer id is not found, which there's no need to care about
|
// null means peer id is not found, which there's no need to care about
|
||||||
final viewStyle = await bind.sessionGetViewStyle(id: remoteId) ?? '';
|
final viewStyle =
|
||||||
|
await bind.sessionGetViewStyle(sessionId: ffi.sessionId) ?? '';
|
||||||
if (rxViewStyle != null) {
|
if (rxViewStyle != null) {
|
||||||
rxViewStyle.value = viewStyle;
|
rxViewStyle.value = viewStyle;
|
||||||
}
|
}
|
||||||
return viewStyle;
|
return viewStyle;
|
||||||
},
|
},
|
||||||
optionSetter: (String oldValue, String newValue) async {
|
optionSetter: (String oldValue, String newValue) async {
|
||||||
await bind.sessionSetViewStyle(id: remoteId, value: newValue);
|
await bind.sessionSetViewStyle(
|
||||||
|
sessionId: ffi.sessionId, value: newValue);
|
||||||
if (rxViewStyle != null) {
|
if (rxViewStyle != null) {
|
||||||
rxViewStyle.value = newValue;
|
rxViewStyle.value = newValue;
|
||||||
}
|
}
|
||||||
@ -165,6 +167,7 @@ class RemoteMenuEntry {
|
|||||||
|
|
||||||
static MenuEntrySwitch2<String> showRemoteCursor(
|
static MenuEntrySwitch2<String> showRemoteCursor(
|
||||||
String remoteId,
|
String remoteId,
|
||||||
|
SessionID sessionId,
|
||||||
EdgeInsets padding, {
|
EdgeInsets padding, {
|
||||||
DismissFunc? dismissFunc,
|
DismissFunc? dismissFunc,
|
||||||
DismissCallback? dismissCallback,
|
DismissCallback? dismissCallback,
|
||||||
@ -178,9 +181,9 @@ class RemoteMenuEntry {
|
|||||||
return state;
|
return state;
|
||||||
},
|
},
|
||||||
setter: (bool v) async {
|
setter: (bool v) async {
|
||||||
await bind.sessionToggleOption(id: remoteId, value: optKey);
|
await bind.sessionToggleOption(sessionId: sessionId, value: optKey);
|
||||||
state.value =
|
state.value =
|
||||||
bind.sessionGetToggleOptionSync(id: remoteId, arg: optKey);
|
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: optKey);
|
||||||
if (dismissFunc != null) {
|
if (dismissFunc != null) {
|
||||||
dismissFunc();
|
dismissFunc();
|
||||||
}
|
}
|
||||||
@ -192,13 +195,13 @@ class RemoteMenuEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static MenuEntrySwitch<String> disableClipboard(
|
static MenuEntrySwitch<String> disableClipboard(
|
||||||
String remoteId,
|
SessionID sessionId,
|
||||||
EdgeInsets? padding, {
|
EdgeInsets? padding, {
|
||||||
DismissFunc? dismissFunc,
|
DismissFunc? dismissFunc,
|
||||||
DismissCallback? dismissCallback,
|
DismissCallback? dismissCallback,
|
||||||
}) {
|
}) {
|
||||||
return createSwitchMenuEntry(
|
return createSwitchMenuEntry(
|
||||||
remoteId,
|
sessionId,
|
||||||
'Disable clipboard',
|
'Disable clipboard',
|
||||||
'disable-clipboard',
|
'disable-clipboard',
|
||||||
padding,
|
padding,
|
||||||
@ -208,7 +211,7 @@ class RemoteMenuEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static MenuEntrySwitch<String> createSwitchMenuEntry(
|
static MenuEntrySwitch<String> createSwitchMenuEntry(
|
||||||
String remoteId,
|
SessionID sessionId,
|
||||||
String text,
|
String text,
|
||||||
String option,
|
String option,
|
||||||
EdgeInsets? padding,
|
EdgeInsets? padding,
|
||||||
@ -220,10 +223,11 @@ class RemoteMenuEntry {
|
|||||||
switchType: SwitchType.scheckbox,
|
switchType: SwitchType.scheckbox,
|
||||||
text: translate(text),
|
text: translate(text),
|
||||||
getter: () async {
|
getter: () async {
|
||||||
return bind.sessionGetToggleOptionSync(id: remoteId, arg: option);
|
return bind.sessionGetToggleOptionSync(
|
||||||
|
sessionId: sessionId, arg: option);
|
||||||
},
|
},
|
||||||
setter: (bool v) async {
|
setter: (bool v) async {
|
||||||
await bind.sessionToggleOption(id: remoteId, value: option);
|
await bind.sessionToggleOption(sessionId: sessionId, value: option);
|
||||||
if (dismissFunc != null) {
|
if (dismissFunc != null) {
|
||||||
dismissFunc();
|
dismissFunc();
|
||||||
}
|
}
|
||||||
@ -235,7 +239,7 @@ class RemoteMenuEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static MenuEntryButton<String> insertLock(
|
static MenuEntryButton<String> insertLock(
|
||||||
String remoteId,
|
SessionID sessionId,
|
||||||
EdgeInsets? padding, {
|
EdgeInsets? padding, {
|
||||||
DismissFunc? dismissFunc,
|
DismissFunc? dismissFunc,
|
||||||
DismissCallback? dismissCallback,
|
DismissCallback? dismissCallback,
|
||||||
@ -246,7 +250,7 @@ class RemoteMenuEntry {
|
|||||||
style: style,
|
style: style,
|
||||||
),
|
),
|
||||||
proc: () {
|
proc: () {
|
||||||
bind.sessionLockScreen(id: remoteId);
|
bind.sessionLockScreen(sessionId: sessionId);
|
||||||
if (dismissFunc != null) {
|
if (dismissFunc != null) {
|
||||||
dismissFunc();
|
dismissFunc();
|
||||||
}
|
}
|
||||||
@ -258,7 +262,7 @@ class RemoteMenuEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static insertCtrlAltDel(
|
static insertCtrlAltDel(
|
||||||
String remoteId,
|
SessionID sessionId,
|
||||||
EdgeInsets? padding, {
|
EdgeInsets? padding, {
|
||||||
DismissFunc? dismissFunc,
|
DismissFunc? dismissFunc,
|
||||||
DismissCallback? dismissCallback,
|
DismissCallback? dismissCallback,
|
||||||
@ -269,7 +273,7 @@ class RemoteMenuEntry {
|
|||||||
style: style,
|
style: style,
|
||||||
),
|
),
|
||||||
proc: () {
|
proc: () {
|
||||||
bind.sessionCtrlAltDel(id: remoteId);
|
bind.sessionCtrlAltDel(sessionId: sessionId);
|
||||||
if (dismissFunc != null) {
|
if (dismissFunc != null) {
|
||||||
dismissFunc();
|
dismissFunc();
|
||||||
}
|
}
|
||||||
@ -329,7 +333,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
|
|
||||||
Future.delayed(Duration.zero, () async {
|
Future.delayed(Duration.zero, () async {
|
||||||
_fractionX.value = double.tryParse(await bind.sessionGetOption(
|
_fractionX.value = double.tryParse(await bind.sessionGetOption(
|
||||||
id: widget.id, arg: 'remote-menubar-drag-x') ??
|
sessionId: widget.ffi.sessionId,
|
||||||
|
arg: 'remote-menubar-drag-x') ??
|
||||||
'0.5') ??
|
'0.5') ??
|
||||||
0.5;
|
0.5;
|
||||||
});
|
});
|
||||||
@ -387,7 +392,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
|
|||||||
elevation: _MenubarTheme.elevation,
|
elevation: _MenubarTheme.elevation,
|
||||||
shadowColor: MyTheme.color(context).shadow,
|
shadowColor: MyTheme.color(context).shadow,
|
||||||
child: _DraggableShowHide(
|
child: _DraggableShowHide(
|
||||||
id: widget.id,
|
sessionId: widget.ffi.sessionId,
|
||||||
dragging: _dragging,
|
dragging: _dragging,
|
||||||
fractionX: _fractionX,
|
fractionX: _fractionX,
|
||||||
show: show,
|
show: show,
|
||||||
@ -621,7 +626,7 @@ class _MonitorMenu extends StatelessWidget {
|
|||||||
_menuDismissCallback(ffi);
|
_menuDismissCallback(ffi);
|
||||||
RxInt display = CurrentDisplayState.find(id);
|
RxInt display = CurrentDisplayState.find(id);
|
||||||
if (display.value != i) {
|
if (display.value != i) {
|
||||||
bind.sessionSwitchDisplay(id: id, value: i);
|
bind.sessionSwitchDisplay(sessionId: ffi.sessionId, value: i);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@ -763,7 +768,8 @@ class ScreenAdjustor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> isWindowCanBeAdjusted() async {
|
Future<bool> isWindowCanBeAdjusted() async {
|
||||||
final viewStyle = await bind.sessionGetViewStyle(id: id) ?? '';
|
final viewStyle =
|
||||||
|
await bind.sessionGetViewStyle(sessionId: ffi.sessionId) ?? '';
|
||||||
if (viewStyle != kRemoteViewStyleOriginal) {
|
if (viewStyle != kRemoteViewStyleOriginal) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -885,9 +891,11 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
|||||||
|
|
||||||
scrollStyle() {
|
scrollStyle() {
|
||||||
return futureBuilder(future: () async {
|
return futureBuilder(future: () async {
|
||||||
final viewStyle = await bind.sessionGetViewStyle(id: id) ?? '';
|
final viewStyle =
|
||||||
|
await bind.sessionGetViewStyle(sessionId: ffi.sessionId) ?? '';
|
||||||
final visible = viewStyle == kRemoteViewStyleOriginal;
|
final visible = viewStyle == kRemoteViewStyleOriginal;
|
||||||
final scrollStyle = await bind.sessionGetScrollStyle(id: widget.id) ?? '';
|
final scrollStyle =
|
||||||
|
await bind.sessionGetScrollStyle(sessionId: ffi.sessionId) ?? '';
|
||||||
return {'visible': visible, 'scrollStyle': scrollStyle};
|
return {'visible': visible, 'scrollStyle': scrollStyle};
|
||||||
}(), hasData: (data) {
|
}(), hasData: (data) {
|
||||||
final visible = data['visible'] as bool;
|
final visible = data['visible'] as bool;
|
||||||
@ -895,7 +903,8 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
|||||||
final groupValue = data['scrollStyle'] as String;
|
final groupValue = data['scrollStyle'] as String;
|
||||||
onChange(String? value) async {
|
onChange(String? value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
await bind.sessionSetScrollStyle(id: widget.id, value: value);
|
await bind.sessionSetScrollStyle(
|
||||||
|
sessionId: ffi.sessionId, value: value);
|
||||||
widget.ffi.canvasModel.updateScrollStyle();
|
widget.ffi.canvasModel.updateScrollStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1007,6 +1016,7 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> {
|
|||||||
late final TextEditingController _customHeight =
|
late final TextEditingController _customHeight =
|
||||||
TextEditingController(text: display.height.toString());
|
TextEditingController(text: display.height.toString());
|
||||||
|
|
||||||
|
FFI get ffi => widget.ffi;
|
||||||
PeerInfo get pi => widget.ffi.ffiModel.pi;
|
PeerInfo get pi => widget.ffi.ffiModel.pi;
|
||||||
FfiModel get ffiModel => widget.ffi.ffiModel;
|
FfiModel get ffiModel => widget.ffi.ffiModel;
|
||||||
Display get display => ffiModel.display;
|
Display get display => ffiModel.display;
|
||||||
@ -1101,7 +1111,7 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> {
|
|||||||
|
|
||||||
_changeResolution(int w, int h) async {
|
_changeResolution(int w, int h) async {
|
||||||
await bind.sessionChangeResolution(
|
await bind.sessionChangeResolution(
|
||||||
id: widget.id,
|
sessionId: ffi.sessionId,
|
||||||
display: pi.currentDisplay,
|
display: pi.currentDisplay,
|
||||||
width: w,
|
width: w,
|
||||||
height: h,
|
height: h,
|
||||||
@ -1254,12 +1264,15 @@ class _KeyboardMenu extends StatelessWidget {
|
|||||||
if (!ffiModel.keyboard) return Offstage();
|
if (!ffiModel.keyboard) return Offstage();
|
||||||
String? modeOnly;
|
String? modeOnly;
|
||||||
if (stateGlobal.grabKeyboard) {
|
if (stateGlobal.grabKeyboard) {
|
||||||
if (bind.sessionIsKeyboardModeSupported(id: id, mode: _kKeyMapMode)) {
|
if (bind.sessionIsKeyboardModeSupported(
|
||||||
bind.sessionSetKeyboardMode(id: id, value: _kKeyMapMode);
|
sessionId: ffi.sessionId, mode: _kKeyMapMode)) {
|
||||||
|
bind.sessionSetKeyboardMode(
|
||||||
|
sessionId: ffi.sessionId, value: _kKeyMapMode);
|
||||||
modeOnly = _kKeyMapMode;
|
modeOnly = _kKeyMapMode;
|
||||||
} else if (bind.sessionIsKeyboardModeSupported(
|
} else if (bind.sessionIsKeyboardModeSupported(
|
||||||
id: id, mode: _kKeyLegacyMode)) {
|
sessionId: ffi.sessionId, mode: _kKeyLegacyMode)) {
|
||||||
bind.sessionSetKeyboardMode(id: id, value: _kKeyLegacyMode);
|
bind.sessionSetKeyboardMode(
|
||||||
|
sessionId: ffi.sessionId, value: _kKeyLegacyMode);
|
||||||
modeOnly = _kKeyLegacyMode;
|
modeOnly = _kKeyLegacyMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1279,7 +1292,8 @@ class _KeyboardMenu extends StatelessWidget {
|
|||||||
|
|
||||||
mode(String? modeOnly) {
|
mode(String? modeOnly) {
|
||||||
return futureBuilder(future: () async {
|
return futureBuilder(future: () async {
|
||||||
return await bind.sessionGetKeyboardMode(id: id) ?? _kKeyLegacyMode;
|
return await bind.sessionGetKeyboardMode(sessionId: ffi.sessionId) ??
|
||||||
|
_kKeyLegacyMode;
|
||||||
}(), hasData: (data) {
|
}(), hasData: (data) {
|
||||||
final groupValue = data as String;
|
final groupValue = data as String;
|
||||||
List<KeyboardModeMenu> modes = [
|
List<KeyboardModeMenu> modes = [
|
||||||
@ -1291,14 +1305,15 @@ class _KeyboardMenu extends StatelessWidget {
|
|||||||
final enabled = !ffi.ffiModel.viewOnly;
|
final enabled = !ffi.ffiModel.viewOnly;
|
||||||
onChanged(String? value) async {
|
onChanged(String? value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
await bind.sessionSetKeyboardMode(id: id, value: value);
|
await bind.sessionSetKeyboardMode(
|
||||||
|
sessionId: ffi.sessionId, value: value);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (KeyboardModeMenu mode in modes) {
|
for (KeyboardModeMenu mode in modes) {
|
||||||
if (modeOnly != null && mode.key != modeOnly) {
|
if (modeOnly != null && mode.key != modeOnly) {
|
||||||
continue;
|
continue;
|
||||||
} else if (!bind.sessionIsKeyboardModeSupported(
|
} else if (!bind.sessionIsKeyboardModeSupported(
|
||||||
id: id, mode: mode.key)) {
|
sessionId: ffi.sessionId, mode: mode.key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1351,7 +1366,8 @@ class _KeyboardMenu extends StatelessWidget {
|
|||||||
onChanged: enabled
|
onChanged: enabled
|
||||||
? (value) async {
|
? (value) async {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
await bind.sessionToggleOption(id: id, value: 'view-only');
|
await bind.sessionToggleOption(
|
||||||
|
sessionId: ffi.sessionId, value: 'view-only');
|
||||||
ffiModel.setViewOnly(id, value);
|
ffiModel.setViewOnly(id, value);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@ -1412,7 +1428,8 @@ class _ChatMenuState extends State<_ChatMenu> {
|
|||||||
return MenuButton(
|
return MenuButton(
|
||||||
child: Text(translate('Voice call')),
|
child: Text(translate('Voice call')),
|
||||||
ffi: widget.ffi,
|
ffi: widget.ffi,
|
||||||
onPressed: () => bind.sessionRequestVoiceCall(id: widget.id),
|
onPressed: () =>
|
||||||
|
bind.sessionRequestVoiceCall(sessionId: widget.ffi.sessionId),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1447,7 +1464,8 @@ class _VoiceCallMenu extends StatelessWidget {
|
|||||||
return _IconMenuButton(
|
return _IconMenuButton(
|
||||||
assetName: icon,
|
assetName: icon,
|
||||||
tooltip: tooltip,
|
tooltip: tooltip,
|
||||||
onPressed: () => bind.sessionCloseVoiceCall(id: id),
|
onPressed: () =>
|
||||||
|
bind.sessionCloseVoiceCall(sessionId: ffi.sessionId),
|
||||||
color: _MenubarTheme.redColor,
|
color: _MenubarTheme.redColor,
|
||||||
hoverColor: _MenubarTheme.hoverRedColor);
|
hoverColor: _MenubarTheme.hoverRedColor);
|
||||||
},
|
},
|
||||||
@ -1492,7 +1510,7 @@ class _CloseMenu extends StatelessWidget {
|
|||||||
return _IconMenuButton(
|
return _IconMenuButton(
|
||||||
assetName: 'assets/close.svg',
|
assetName: 'assets/close.svg',
|
||||||
tooltip: 'Close',
|
tooltip: 'Close',
|
||||||
onPressed: () => clientClose(id, ffi.dialogManager),
|
onPressed: () => clientClose(ffi.sessionId, ffi.dialogManager),
|
||||||
color: _MenubarTheme.redColor,
|
color: _MenubarTheme.redColor,
|
||||||
hoverColor: _MenubarTheme.hoverRedColor,
|
hoverColor: _MenubarTheme.hoverRedColor,
|
||||||
);
|
);
|
||||||
@ -1753,13 +1771,13 @@ class RdoMenuButton<T> extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DraggableShowHide extends StatefulWidget {
|
class _DraggableShowHide extends StatefulWidget {
|
||||||
final String id;
|
final SessionID sessionId;
|
||||||
final RxDouble fractionX;
|
final RxDouble fractionX;
|
||||||
final RxBool dragging;
|
final RxBool dragging;
|
||||||
final RxBool show;
|
final RxBool show;
|
||||||
const _DraggableShowHide({
|
const _DraggableShowHide({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.id,
|
required this.sessionId,
|
||||||
required this.fractionX,
|
required this.fractionX,
|
||||||
required this.dragging,
|
required this.dragging,
|
||||||
required this.show,
|
required this.show,
|
||||||
@ -1826,7 +1844,7 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
|
|||||||
widget.fractionX.value = right;
|
widget.fractionX.value = right;
|
||||||
}
|
}
|
||||||
bind.sessionPeerOption(
|
bind.sessionPeerOption(
|
||||||
id: widget.id,
|
sessionId: widget.sessionId,
|
||||||
name: 'remote-menubar-drag-x',
|
name: 'remote-menubar-drag-x',
|
||||||
value: widget.fractionX.value.toString(),
|
value: widget.fractionX.value.toString(),
|
||||||
);
|
);
|
||||||
@ -1952,7 +1970,7 @@ class _MultiMonitorMenu extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (display.value != i) {
|
if (display.value != i) {
|
||||||
bind.sessionSwitchDisplay(id: id, value: i);
|
bind.sessionSwitchDisplay(sessionId: ffi.sessionId, value: i);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart';
|
import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart';
|
||||||
import 'package:scroll_pos/scroll_pos.dart';
|
import 'package:scroll_pos/scroll_pos.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
import '../../utils/multi_window_manager.dart';
|
import '../../utils/multi_window_manager.dart';
|
||||||
|
@ -73,7 +73,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
gFFI.dialogManager
|
gFFI.dialogManager
|
||||||
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
||||||
});
|
});
|
||||||
gFFI.ffiModel.updateEventListener(widget.id);
|
gFFI.ffiModel.updateEventListener(gFFI.sessionId, widget.id);
|
||||||
Wakelock.enable();
|
Wakelock.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,8 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
leading: Row(children: [
|
leading: Row(children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.close),
|
icon: Icon(Icons.close),
|
||||||
onPressed: () => clientClose(widget.id, gFFI.dialogManager)),
|
onPressed: () =>
|
||||||
|
clientClose(gFFI.sessionId, gFFI.dialogManager)),
|
||||||
]),
|
]),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: ToggleSwitch(
|
title: ToggleSwitch(
|
||||||
|
@ -54,6 +54,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
var _showEdit = false; // use soft keyboard
|
var _showEdit = false; // use soft keyboard
|
||||||
|
|
||||||
InputModel get inputModel => gFFI.inputModel;
|
InputModel get inputModel => gFFI.inputModel;
|
||||||
|
SessionID get sessionId => gFFI.sessionId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -66,9 +67,9 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
});
|
});
|
||||||
Wakelock.enable();
|
Wakelock.enable();
|
||||||
_physicalFocusNode.requestFocus();
|
_physicalFocusNode.requestFocus();
|
||||||
gFFI.ffiModel.updateEventListener(widget.id);
|
gFFI.ffiModel.updateEventListener(sessionId, widget.id);
|
||||||
gFFI.inputModel.listenToMouse(true);
|
gFFI.inputModel.listenToMouse(true);
|
||||||
gFFI.qualityMonitorModel.checkShowQualityMonitor(widget.id);
|
gFFI.qualityMonitorModel.checkShowQualityMonitor(sessionId);
|
||||||
keyboardSubscription =
|
keyboardSubscription =
|
||||||
keyboardVisibilityController.onChange.listen(onSoftKeyboardChanged);
|
keyboardVisibilityController.onChange.listen(onSoftKeyboardChanged);
|
||||||
_blockableOverlayState.applyFfi(gFFI);
|
_blockableOverlayState.applyFfi(gFFI);
|
||||||
@ -130,7 +131,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
if (newValue.length > common) {
|
if (newValue.length > common) {
|
||||||
var s = newValue.substring(common);
|
var s = newValue.substring(common);
|
||||||
if (s.length > 1) {
|
if (s.length > 1) {
|
||||||
bind.sessionInputString(id: widget.id, value: s);
|
bind.sessionInputString(sessionId: sessionId, value: s);
|
||||||
} else {
|
} else {
|
||||||
inputChar(s);
|
inputChar(s);
|
||||||
}
|
}
|
||||||
@ -164,11 +165,11 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
content == '()' ||
|
content == '()' ||
|
||||||
content == '【】')) {
|
content == '【】')) {
|
||||||
// can not only input content[0], because when input ], [ are also auo insert, which cause ] never be input
|
// can not only input content[0], because when input ], [ are also auo insert, which cause ] never be input
|
||||||
bind.sessionInputString(id: widget.id, value: content);
|
bind.sessionInputString(sessionId: sessionId, value: content);
|
||||||
openKeyboard();
|
openKeyboard();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bind.sessionInputString(id: widget.id, value: content);
|
bind.sessionInputString(sessionId: sessionId, value: content);
|
||||||
} else {
|
} else {
|
||||||
inputChar(content);
|
inputChar(content);
|
||||||
}
|
}
|
||||||
@ -213,7 +214,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
|
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
clientClose(widget.id, gFFI.dialogManager);
|
clientClose(sessionId, gFFI.dialogManager);
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
child: getRawPointerAndKeyBody(Scaffold(
|
child: getRawPointerAndKeyBody(Scaffold(
|
||||||
@ -305,7 +306,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
icon: Icon(Icons.clear),
|
icon: Icon(Icons.clear),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
clientClose(widget.id, gFFI.dialogManager);
|
clientClose(sessionId, gFFI.dialogManager);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
] +
|
] +
|
||||||
@ -476,7 +477,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
},
|
},
|
||||||
onTwoFingerScaleEnd: (d) {
|
onTwoFingerScaleEnd: (d) {
|
||||||
_scale = 1;
|
_scale = 1;
|
||||||
bind.sessionSetViewStyle(id: widget.id, value: "");
|
bind.sessionSetViewStyle(sessionId: sessionId, value: "");
|
||||||
},
|
},
|
||||||
onThreeFingerVerticalDragUpdate: gFFI.ffiModel.isPeerAndroid
|
onThreeFingerVerticalDragUpdate: gFFI.ffiModel.isPeerAndroid
|
||||||
? null
|
? null
|
||||||
@ -535,7 +536,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
var paints = <Widget>[ImagePaint()];
|
var paints = <Widget>[ImagePaint()];
|
||||||
if (!gFFI.canvasModel.cursorEmbedded) {
|
if (!gFFI.canvasModel.cursorEmbedded) {
|
||||||
final cursor = bind.sessionGetToggleOptionSync(
|
final cursor = bind.sessionGetToggleOptionSync(
|
||||||
id: widget.id, arg: 'show-remote-cursor');
|
sessionId: sessionId, arg: 'show-remote-cursor');
|
||||||
if (keyboard || cursor) {
|
if (keyboard || cursor) {
|
||||||
paints.add(CursorPaint());
|
paints.add(CursorPaint());
|
||||||
}
|
}
|
||||||
@ -579,7 +580,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
gFFI.ffiModel.toggleTouchMode();
|
gFFI.ffiModel.toggleTouchMode();
|
||||||
final v = gFFI.ffiModel.touchMode ? 'Y' : '';
|
final v = gFFI.ffiModel.touchMode ? 'Y' : '';
|
||||||
bind.sessionPeerOption(
|
bind.sessionPeerOption(
|
||||||
id: widget.id, name: "touch", value: v);
|
sessionId: sessionId, name: "touch", value: v);
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -830,7 +831,7 @@ void showOptions(
|
|||||||
children.add(InkWell(
|
children.add(InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (i == cur) return;
|
if (i == cur) return;
|
||||||
bind.sessionSwitchDisplay(id: id, value: i);
|
bind.sessionSwitchDisplay(sessionId: gFFI.sessionId, value: i);
|
||||||
gFFI.dialogManager.dismissAll();
|
gFFI.dialogManager.dismissAll();
|
||||||
},
|
},
|
||||||
child: Ink(
|
child: Ink(
|
||||||
|
@ -74,7 +74,11 @@ class ChatModel with ChangeNotifier {
|
|||||||
|
|
||||||
final WeakReference<FFI> parent;
|
final WeakReference<FFI> parent;
|
||||||
|
|
||||||
ChatModel(this.parent);
|
late final SessionID sessionId;
|
||||||
|
|
||||||
|
ChatModel(this.parent) {
|
||||||
|
sessionId = parent.target!.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
FocusNode inputNode = FocusNode();
|
FocusNode inputNode = FocusNode();
|
||||||
|
|
||||||
@ -302,7 +306,7 @@ class ChatModel with ChangeNotifier {
|
|||||||
_messages[_currentID]?.insert(message);
|
_messages[_currentID]?.insert(message);
|
||||||
if (_currentID == clientModeID) {
|
if (_currentID == clientModeID) {
|
||||||
if (parent.target != null) {
|
if (parent.target != null) {
|
||||||
bind.sessionSendChat(id: parent.target!.id, text: message.text);
|
bind.sessionSendChat(sessionId: sessionId, text: message.text);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bind.cmSendChat(connId: _currentID, msg: message.text);
|
bind.cmSendChat(connId: _currentID, msg: message.text);
|
||||||
@ -347,8 +351,8 @@ class ChatModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeVoiceCall(String id) {
|
void closeVoiceCall() {
|
||||||
bind.sessionCloseVoiceCall(id: id);
|
bind.sessionCloseVoiceCall(sessionId: sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +33,11 @@ class JobID {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef GetSessionID = String Function();
|
typedef GetSessionID = SessionID Function();
|
||||||
|
|
||||||
class FileModel {
|
class FileModel {
|
||||||
final WeakReference<FFI> parent;
|
final WeakReference<FFI> parent;
|
||||||
// late final String sessionID;
|
// late final String sessionId;
|
||||||
late final FileFetcher fileFetcher;
|
late final FileFetcher fileFetcher;
|
||||||
late final JobController jobController;
|
late final JobController jobController;
|
||||||
|
|
||||||
@ -45,11 +45,11 @@ class FileModel {
|
|||||||
late final FileController remoteController;
|
late final FileController remoteController;
|
||||||
|
|
||||||
late final GetSessionID getSessionID;
|
late final GetSessionID getSessionID;
|
||||||
String get sessionID => getSessionID();
|
SessionID get sessionId => getSessionID();
|
||||||
late final FileDialogEventLoop evtLoop;
|
late final FileDialogEventLoop evtLoop;
|
||||||
|
|
||||||
FileModel(this.parent) {
|
FileModel(this.parent) {
|
||||||
getSessionID = () => parent.target?.id ?? "";
|
getSessionID = () => parent.target!.sessionId;
|
||||||
fileFetcher = FileFetcher(getSessionID);
|
fileFetcher = FileFetcher(getSessionID);
|
||||||
jobController = JobController(getSessionID);
|
jobController = JobController(getSessionID);
|
||||||
localController = FileController(
|
localController = FileController(
|
||||||
@ -133,7 +133,7 @@ class FileModel {
|
|||||||
evtLoop.setSkip(!need_override);
|
evtLoop.setSkip(!need_override);
|
||||||
}
|
}
|
||||||
await bind.sessionSetConfirmOverrideFile(
|
await bind.sessionSetConfirmOverrideFile(
|
||||||
id: sessionID,
|
sessionId: sessionId,
|
||||||
actId: id,
|
actId: id,
|
||||||
fileNum: int.parse(evt['file_num']),
|
fileNum: int.parse(evt['file_num']),
|
||||||
needOverride: need_override,
|
needOverride: need_override,
|
||||||
@ -236,7 +236,7 @@ class DirectoryData {
|
|||||||
class FileController {
|
class FileController {
|
||||||
final bool isLocal;
|
final bool isLocal;
|
||||||
final GetSessionID getSessionID;
|
final GetSessionID getSessionID;
|
||||||
String get sessionID => getSessionID();
|
SessionID get sessionId => getSessionID();
|
||||||
|
|
||||||
final FileFetcher fileFetcher;
|
final FileFetcher fileFetcher;
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ class FileController {
|
|||||||
options.value.home = await bind.mainGetHomeDir();
|
options.value.home = await bind.mainGetHomeDir();
|
||||||
}
|
}
|
||||||
options.value.showHidden = (await bind.sessionGetPeerOption(
|
options.value.showHidden = (await bind.sessionGetPeerOption(
|
||||||
id: sessionID,
|
sessionId: sessionId,
|
||||||
name: isLocal ? "local_show_hidden" : "remote_show_hidden"))
|
name: isLocal ? "local_show_hidden" : "remote_show_hidden"))
|
||||||
.isNotEmpty;
|
.isNotEmpty;
|
||||||
options.value.isWindows = isLocal
|
options.value.isWindows = isLocal
|
||||||
@ -297,7 +297,7 @@ class FileController {
|
|||||||
await Future.delayed(Duration(milliseconds: 100));
|
await Future.delayed(Duration(milliseconds: 100));
|
||||||
|
|
||||||
final dir = (await bind.sessionGetPeerOption(
|
final dir = (await bind.sessionGetPeerOption(
|
||||||
id: sessionID, name: isLocal ? "local_dir" : "remote_dir"));
|
sessionId: sessionId, name: isLocal ? "local_dir" : "remote_dir"));
|
||||||
openDirectory(dir.isEmpty ? options.value.home : dir);
|
openDirectory(dir.isEmpty ? options.value.home : dir);
|
||||||
|
|
||||||
await Future.delayed(Duration(seconds: 1));
|
await Future.delayed(Duration(seconds: 1));
|
||||||
@ -315,7 +315,7 @@ class FileController {
|
|||||||
options.value.showHidden ? "Y" : "";
|
options.value.showHidden ? "Y" : "";
|
||||||
for (final msg in msgMap.entries) {
|
for (final msg in msgMap.entries) {
|
||||||
await bind.sessionPeerOption(
|
await bind.sessionPeerOption(
|
||||||
id: sessionID, name: msg.key, value: msg.value);
|
sessionId: sessionId, name: msg.key, value: msg.value);
|
||||||
}
|
}
|
||||||
directory.value.clear();
|
directory.value.clear();
|
||||||
options.value.clear();
|
options.value.clear();
|
||||||
@ -447,7 +447,7 @@ class FileController {
|
|||||||
for (var from in items.items) {
|
for (var from in items.items) {
|
||||||
final jobID = jobController.add(from, isRemoteToLocal);
|
final jobID = jobController.add(from, isRemoteToLocal);
|
||||||
bind.sessionSendFiles(
|
bind.sessionSendFiles(
|
||||||
id: sessionID,
|
sessionId: sessionId,
|
||||||
actId: jobID,
|
actId: jobID,
|
||||||
path: from.path,
|
path: from.path,
|
||||||
to: PathUtil.join(toPath, from.name, isWindows),
|
to: PathUtil.join(toPath, from.name, isWindows),
|
||||||
@ -547,7 +547,8 @@ class FileController {
|
|||||||
|
|
||||||
Future<bool?> showRemoveDialog(
|
Future<bool?> showRemoveDialog(
|
||||||
String title, String content, bool showCheckbox) async {
|
String title, String content, bool showCheckbox) async {
|
||||||
return await dialogManager?.show<bool>((setState, Function(bool v) close, context) {
|
return await dialogManager?.show<bool>(
|
||||||
|
(setState, Function(bool v) close, context) {
|
||||||
cancel() => close(false);
|
cancel() => close(false);
|
||||||
submit() => close(true);
|
submit() => close(true);
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
@ -611,7 +612,7 @@ class FileController {
|
|||||||
|
|
||||||
void sendRemoveFile(String path, int fileNum) {
|
void sendRemoveFile(String path, int fileNum) {
|
||||||
bind.sessionRemoveFile(
|
bind.sessionRemoveFile(
|
||||||
id: sessionID,
|
sessionId: sessionId,
|
||||||
actId: JobController.jobID.next(),
|
actId: JobController.jobID.next(),
|
||||||
path: path,
|
path: path,
|
||||||
isRemote: !isLocal,
|
isRemote: !isLocal,
|
||||||
@ -621,7 +622,7 @@ class FileController {
|
|||||||
void sendRemoveEmptyDir(String path, int fileNum) {
|
void sendRemoveEmptyDir(String path, int fileNum) {
|
||||||
history.removeWhere((element) => element.contains(path));
|
history.removeWhere((element) => element.contains(path));
|
||||||
bind.sessionRemoveAllEmptyDirs(
|
bind.sessionRemoveAllEmptyDirs(
|
||||||
id: sessionID,
|
sessionId: sessionId,
|
||||||
actId: JobController.jobID.next(),
|
actId: JobController.jobID.next(),
|
||||||
path: path,
|
path: path,
|
||||||
isRemote: !isLocal);
|
isRemote: !isLocal);
|
||||||
@ -629,7 +630,7 @@ class FileController {
|
|||||||
|
|
||||||
Future<void> createDir(String path) async {
|
Future<void> createDir(String path) async {
|
||||||
bind.sessionCreateDir(
|
bind.sessionCreateDir(
|
||||||
id: sessionID,
|
sessionId: sessionId,
|
||||||
actId: JobController.jobID.next(),
|
actId: JobController.jobID.next(),
|
||||||
path: path,
|
path: path,
|
||||||
isRemote: !isLocal);
|
isRemote: !isLocal);
|
||||||
@ -641,7 +642,7 @@ class JobController {
|
|||||||
final jobTable = List<JobProgress>.empty(growable: true).obs;
|
final jobTable = List<JobProgress>.empty(growable: true).obs;
|
||||||
final jobResultListener = JobResultListener<Map<String, dynamic>>();
|
final jobResultListener = JobResultListener<Map<String, dynamic>>();
|
||||||
final GetSessionID getSessionID;
|
final GetSessionID getSessionID;
|
||||||
String get sessionID => getSessionID();
|
SessionID get sessionId => getSessionID();
|
||||||
|
|
||||||
JobController(this.getSessionID);
|
JobController(this.getSessionID);
|
||||||
|
|
||||||
@ -719,7 +720,7 @@ class JobController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> cancelJob(int id) async {
|
Future<void> cancelJob(int id) async {
|
||||||
await bind.sessionCancelJob(id: sessionID, actId: id);
|
await bind.sessionCancelJob(sessionId: sessionId, actId: id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadLastJob(Map<String, dynamic> evt) {
|
void loadLastJob(Map<String, dynamic> evt) {
|
||||||
@ -745,7 +746,7 @@ class JobController {
|
|||||||
..state = JobState.paused;
|
..state = JobState.paused;
|
||||||
jobTable.add(jobProgress);
|
jobTable.add(jobProgress);
|
||||||
bind.sessionAddJob(
|
bind.sessionAddJob(
|
||||||
id: sessionID,
|
sessionId: sessionId,
|
||||||
isRemote: isRemote,
|
isRemote: isRemote,
|
||||||
includeHidden: showHidden,
|
includeHidden: showHidden,
|
||||||
actId: currJobId,
|
actId: currJobId,
|
||||||
@ -760,7 +761,7 @@ class JobController {
|
|||||||
if (jobIndex != -1) {
|
if (jobIndex != -1) {
|
||||||
final job = jobTable[jobIndex];
|
final job = jobTable[jobIndex];
|
||||||
bind.sessionResumeJob(
|
bind.sessionResumeJob(
|
||||||
id: sessionID, actId: job.id, isRemote: job.isRemoteToLocal);
|
sessionId: sessionId, actId: job.id, isRemote: job.isRemoteToLocal);
|
||||||
job.state = JobState.inProgress;
|
job.state = JobState.inProgress;
|
||||||
jobTable.refresh();
|
jobTable.refresh();
|
||||||
} else {
|
} else {
|
||||||
@ -831,7 +832,7 @@ class FileFetcher {
|
|||||||
Map<int, Completer<FileDirectory>> readRecursiveTasks = {};
|
Map<int, Completer<FileDirectory>> readRecursiveTasks = {};
|
||||||
|
|
||||||
final GetSessionID getSessionID;
|
final GetSessionID getSessionID;
|
||||||
String get sessionID => getSessionID();
|
SessionID get sessionId => getSessionID();
|
||||||
|
|
||||||
FileFetcher(this.getSessionID);
|
FileFetcher(this.getSessionID);
|
||||||
|
|
||||||
@ -896,12 +897,12 @@ class FileFetcher {
|
|||||||
try {
|
try {
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
final res = await bind.sessionReadLocalDirSync(
|
final res = await bind.sessionReadLocalDirSync(
|
||||||
id: sessionID, path: path, showHidden: showHidden);
|
sessionId: sessionId, path: path, showHidden: showHidden);
|
||||||
final fd = FileDirectory.fromJson(jsonDecode(res));
|
final fd = FileDirectory.fromJson(jsonDecode(res));
|
||||||
return fd;
|
return fd;
|
||||||
} else {
|
} else {
|
||||||
await bind.sessionReadRemoteDir(
|
await bind.sessionReadRemoteDir(
|
||||||
id: sessionID, path: path, includeHidden: showHidden);
|
sessionId: sessionId, path: path, includeHidden: showHidden);
|
||||||
return registerReadTask(isLocal, path);
|
return registerReadTask(isLocal, path);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -914,7 +915,7 @@ class FileFetcher {
|
|||||||
// TODO test Recursive is show hidden default?
|
// TODO test Recursive is show hidden default?
|
||||||
try {
|
try {
|
||||||
await bind.sessionReadDirRecursive(
|
await bind.sessionReadDirRecursive(
|
||||||
id: sessionID,
|
sessionId: sessionId,
|
||||||
actId: actID,
|
actId: actID,
|
||||||
path: path,
|
path: path,
|
||||||
isRemote: !isLocal,
|
isRemote: !isLocal,
|
||||||
|
@ -59,9 +59,13 @@ class InputModel {
|
|||||||
|
|
||||||
get id => parent.target?.id ?? "";
|
get id => parent.target?.id ?? "";
|
||||||
|
|
||||||
|
late final SessionID sessionId;
|
||||||
|
|
||||||
bool get keyboardPerm => parent.target!.ffiModel.keyboard;
|
bool get keyboardPerm => parent.target!.ffiModel.keyboard;
|
||||||
|
|
||||||
InputModel(this.parent);
|
InputModel(this.parent) {
|
||||||
|
sessionId = parent.target!.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
KeyEventResult handleRawKeyEvent(FocusNode data, RawKeyEvent e) {
|
KeyEventResult handleRawKeyEvent(FocusNode data, RawKeyEvent e) {
|
||||||
if (isDesktop && !stateGlobal.grabKeyboard) {
|
if (isDesktop && !stateGlobal.grabKeyboard) {
|
||||||
@ -70,7 +74,7 @@ class InputModel {
|
|||||||
|
|
||||||
// * Currently mobile does not enable map mode
|
// * Currently mobile does not enable map mode
|
||||||
if (isDesktop) {
|
if (isDesktop) {
|
||||||
bind.sessionGetKeyboardMode(id: id).then((result) {
|
bind.sessionGetKeyboardMode(sessionId: sessionId).then((result) {
|
||||||
keyboardMode = result.toString();
|
keyboardMode = result.toString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -169,7 +173,7 @@ class InputModel {
|
|||||||
lockModes |= (1 << scrolllock);
|
lockModes |= (1 << scrolllock);
|
||||||
}
|
}
|
||||||
bind.sessionHandleFlutterKeyEvent(
|
bind.sessionHandleFlutterKeyEvent(
|
||||||
id: id,
|
sessionId: sessionId,
|
||||||
name: name,
|
name: name,
|
||||||
platformCode: platformCode,
|
platformCode: platformCode,
|
||||||
positionCode: positionCode,
|
positionCode: positionCode,
|
||||||
@ -204,7 +208,7 @@ class InputModel {
|
|||||||
void inputKey(String name, {bool? down, bool? press}) {
|
void inputKey(String name, {bool? down, bool? press}) {
|
||||||
if (!keyboardPerm) return;
|
if (!keyboardPerm) return;
|
||||||
bind.sessionInputKey(
|
bind.sessionInputKey(
|
||||||
id: id,
|
sessionId: sessionId,
|
||||||
name: name,
|
name: name,
|
||||||
down: down ?? false,
|
down: down ?? false,
|
||||||
press: press ?? true,
|
press: press ?? true,
|
||||||
@ -264,7 +268,7 @@ class InputModel {
|
|||||||
/// Send scroll event with scroll distance [y].
|
/// Send scroll event with scroll distance [y].
|
||||||
void scroll(int y) {
|
void scroll(int y) {
|
||||||
bind.sessionSendMouse(
|
bind.sessionSendMouse(
|
||||||
id: id,
|
sessionId: sessionId,
|
||||||
msg: json
|
msg: json
|
||||||
.encode(modify({'id': id, 'type': 'wheel', 'y': y.toString()})));
|
.encode(modify({'id': id, 'type': 'wheel', 'y': y.toString()})));
|
||||||
}
|
}
|
||||||
@ -287,7 +291,7 @@ class InputModel {
|
|||||||
void sendMouse(String type, MouseButtons button) {
|
void sendMouse(String type, MouseButtons button) {
|
||||||
if (!keyboardPerm) return;
|
if (!keyboardPerm) return;
|
||||||
bind.sessionSendMouse(
|
bind.sessionSendMouse(
|
||||||
id: id,
|
sessionId: sessionId,
|
||||||
msg: json.encode(modify({'type': type, 'buttons': button.value})));
|
msg: json.encode(modify({'type': type, 'buttons': button.value})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +301,7 @@ class InputModel {
|
|||||||
resetModifiers();
|
resetModifiers();
|
||||||
}
|
}
|
||||||
_flingTimer?.cancel();
|
_flingTimer?.cancel();
|
||||||
bind.sessionEnterOrLeave(id: id, enter: enter);
|
bind.sessionEnterOrLeave(sessionId: sessionId, enter: enter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send mouse movement event with distance in [x] and [y].
|
/// Send mouse movement event with distance in [x] and [y].
|
||||||
@ -306,7 +310,8 @@ class InputModel {
|
|||||||
var x2 = x.toInt();
|
var x2 = x.toInt();
|
||||||
var y2 = y.toInt();
|
var y2 = y.toInt();
|
||||||
bind.sessionSendMouse(
|
bind.sessionSendMouse(
|
||||||
id: id, msg: json.encode(modify({'x': '$x2', 'y': '$y2'})));
|
sessionId: sessionId,
|
||||||
|
msg: json.encode(modify({'x': '$x2', 'y': '$y2'})));
|
||||||
}
|
}
|
||||||
|
|
||||||
void onPointHoverImage(PointerHoverEvent e) {
|
void onPointHoverImage(PointerHoverEvent e) {
|
||||||
@ -333,7 +338,8 @@ class InputModel {
|
|||||||
var y = delta.dy.toInt();
|
var y = delta.dy.toInt();
|
||||||
if (x != 0 || y != 0) {
|
if (x != 0 || y != 0) {
|
||||||
bind.sessionSendMouse(
|
bind.sessionSendMouse(
|
||||||
id: id, msg: '{"type": "trackpad", "x": "$x", "y": "$y"}');
|
sessionId: sessionId,
|
||||||
|
msg: '{"type": "trackpad", "x": "$x", "y": "$y"}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +370,8 @@ class InputModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bind.sessionSendMouse(
|
bind.sessionSendMouse(
|
||||||
id: id, msg: '{"type": "trackpad", "x": "$dx", "y": "$dy"}');
|
sessionId: sessionId,
|
||||||
|
msg: '{"type": "trackpad", "x": "$dx", "y": "$dy"}');
|
||||||
_scheduleFling(x, y, delay);
|
_scheduleFling(x, y, delay);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -439,7 +446,8 @@ class InputModel {
|
|||||||
dy = 1;
|
dy = 1;
|
||||||
}
|
}
|
||||||
bind.sessionSendMouse(
|
bind.sessionSendMouse(
|
||||||
id: id, msg: '{"type": "wheel", "x": "$dx", "y": "$dy"}');
|
sessionId: sessionId,
|
||||||
|
msg: '{"type": "wheel", "x": "$dx", "y": "$dy"}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,7 +640,7 @@ class InputModel {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
evt['buttons'] = buttons;
|
evt['buttons'] = buttons;
|
||||||
bind.sessionSendMouse(id: id, msg: json.encode(evt));
|
bind.sessionSendMouse(sessionId: sessionId, msg: json.encode(evt));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Web only
|
/// Web only
|
||||||
|
@ -27,6 +27,7 @@ import 'package:image/image.dart' as img2;
|
|||||||
import 'package:flutter_custom_cursor/cursor_manager.dart';
|
import 'package:flutter_custom_cursor/cursor_manager.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
@ -36,7 +37,7 @@ import 'input_model.dart';
|
|||||||
import 'platform_model.dart';
|
import 'platform_model.dart';
|
||||||
|
|
||||||
typedef HandleMsgBox = Function(Map<String, dynamic> evt, String id);
|
typedef HandleMsgBox = Function(Map<String, dynamic> evt, String id);
|
||||||
typedef ReconnectHandle = Function(OverlayDialogManager, String, bool);
|
typedef ReconnectHandle = Function(OverlayDialogManager, SessionID, bool);
|
||||||
final _waitForImage = <String, bool>{};
|
final _waitForImage = <String, bool>{};
|
||||||
|
|
||||||
class FfiModel with ChangeNotifier {
|
class FfiModel with ChangeNotifier {
|
||||||
@ -52,6 +53,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
var _reconnects = 1;
|
var _reconnects = 1;
|
||||||
bool _viewOnly = false;
|
bool _viewOnly = false;
|
||||||
WeakReference<FFI> parent;
|
WeakReference<FFI> parent;
|
||||||
|
late final SessionID sessionId;
|
||||||
|
|
||||||
Map<String, bool> get permissions => _permissions;
|
Map<String, bool> get permissions => _permissions;
|
||||||
|
|
||||||
@ -77,6 +79,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
|
|
||||||
FfiModel(this.parent) {
|
FfiModel(this.parent) {
|
||||||
clear();
|
clear();
|
||||||
|
sessionId = parent.target!.sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleTouchMode() {
|
toggleTouchMode() {
|
||||||
@ -139,20 +142,21 @@ class FfiModel with ChangeNotifier {
|
|||||||
_permissions.clear();
|
_permissions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamEventHandler startEventListener(String peerId) {
|
// todo: why called by two position
|
||||||
|
StreamEventHandler startEventListener(SessionID sessionId, String peerId) {
|
||||||
return (evt) async {
|
return (evt) async {
|
||||||
var name = evt['name'];
|
var name = evt['name'];
|
||||||
if (name == 'msgbox') {
|
if (name == 'msgbox') {
|
||||||
handleMsgBox(evt, peerId);
|
handleMsgBox(evt, sessionId, peerId);
|
||||||
} else if (name == 'peer_info') {
|
} else if (name == 'peer_info') {
|
||||||
handlePeerInfo(evt, peerId);
|
handlePeerInfo(evt, peerId);
|
||||||
} else if (name == 'sync_peer_info') {
|
} else if (name == 'sync_peer_info') {
|
||||||
handleSyncPeerInfo(evt, peerId);
|
handleSyncPeerInfo(evt, sessionId);
|
||||||
} else if (name == 'connection_ready') {
|
} else if (name == 'connection_ready') {
|
||||||
setConnectionType(
|
setConnectionType(
|
||||||
peerId, evt['secure'] == 'true', evt['direct'] == 'true');
|
peerId, evt['secure'] == 'true', evt['direct'] == 'true');
|
||||||
} else if (name == 'switch_display') {
|
} else if (name == 'switch_display') {
|
||||||
handleSwitchDisplay(evt, peerId);
|
handleSwitchDisplay(evt, sessionId, peerId);
|
||||||
} else if (name == 'cursor_data') {
|
} else if (name == 'cursor_data') {
|
||||||
await parent.target?.cursorModel.updateCursorData(evt);
|
await parent.target?.cursorModel.updateCursorData(evt);
|
||||||
} else if (name == 'cursor_id') {
|
} else if (name == 'cursor_id') {
|
||||||
@ -193,7 +197,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
} else if (name == 'update_block_input_state') {
|
} else if (name == 'update_block_input_state') {
|
||||||
updateBlockInputState(evt, peerId);
|
updateBlockInputState(evt, peerId);
|
||||||
} else if (name == 'update_privacy_mode') {
|
} else if (name == 'update_privacy_mode') {
|
||||||
updatePrivacyMode(evt, peerId);
|
updatePrivacyMode(evt, sessionId, peerId);
|
||||||
} else if (name == 'new_connection') {
|
} else if (name == 'new_connection') {
|
||||||
var uni_links = evt['uni_links'].toString();
|
var uni_links = evt['uni_links'].toString();
|
||||||
if (uni_links.startsWith(kUniLinksPrefix)) {
|
if (uni_links.startsWith(kUniLinksPrefix)) {
|
||||||
@ -205,10 +209,10 @@ class FfiModel with ChangeNotifier {
|
|||||||
final show = evt['show'].toString() == 'true';
|
final show = evt['show'].toString() == 'true';
|
||||||
parent.target?.serverModel.setShowElevation(show);
|
parent.target?.serverModel.setShowElevation(show);
|
||||||
} else if (name == 'cancel_msgbox') {
|
} else if (name == 'cancel_msgbox') {
|
||||||
cancelMsgBox(evt, peerId);
|
cancelMsgBox(evt, sessionId);
|
||||||
} else if (name == 'switch_back') {
|
} else if (name == 'switch_back') {
|
||||||
final peer_id = evt['peer_id'].toString();
|
final peer_id = evt['peer_id'].toString();
|
||||||
await bind.sessionSwitchSides(id: peer_id);
|
await bind.sessionSwitchSides(sessionId: sessionId);
|
||||||
closeConnection(id: peer_id);
|
closeConnection(id: peer_id);
|
||||||
} else if (name == 'portable_service_running') {
|
} else if (name == 'portable_service_running') {
|
||||||
parent.target?.elevationModel.onPortableServiceRunning(evt);
|
parent.target?.elevationModel.onPortableServiceRunning(evt);
|
||||||
@ -234,12 +238,12 @@ class FfiModel with ChangeNotifier {
|
|||||||
} else if (name == 'plugin_manager') {
|
} else if (name == 'plugin_manager') {
|
||||||
pluginManager.handleEvent(evt);
|
pluginManager.handleEvent(evt);
|
||||||
} else if (name == 'plugin_event') {
|
} else if (name == 'plugin_event') {
|
||||||
handlePluginEvent(
|
handlePluginEvent(evt,
|
||||||
evt, peerId, (Map<String, dynamic> e) => handleMsgBox(e, peerId));
|
(Map<String, dynamic> e) => handleMsgBox(e, sessionId, peerId));
|
||||||
} else if (name == 'plugin_reload') {
|
} else if (name == 'plugin_reload') {
|
||||||
handleReloading(evt, peerId);
|
handleReloading(evt);
|
||||||
} else if (name == 'plugin_option') {
|
} else if (name == 'plugin_option') {
|
||||||
handleOption(evt, peerId);
|
handleOption(evt);
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Unknown event name: $name');
|
debugPrint('Unknown event name: $name');
|
||||||
}
|
}
|
||||||
@ -271,8 +275,8 @@ class FfiModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Bind the event listener to receive events from the Rust core.
|
/// Bind the event listener to receive events from the Rust core.
|
||||||
updateEventListener(String peerId) {
|
updateEventListener(SessionID sessionId, String peerId) {
|
||||||
platformFFI.setEventCallback(startEventListener(peerId));
|
platformFFI.setEventCallback(startEventListener(sessionId, peerId));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAliasChanged(Map<String, dynamic> evt) {
|
handleAliasChanged(Map<String, dynamic> evt) {
|
||||||
@ -282,18 +286,19 @@ class FfiModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateCurDisplay(String peerId, Display newDisplay) {
|
_updateCurDisplay(SessionID sessionId, Display newDisplay) {
|
||||||
if (newDisplay != _display) {
|
if (newDisplay != _display) {
|
||||||
if (newDisplay.x != _display.x || newDisplay.y != _display.y) {
|
if (newDisplay.x != _display.x || newDisplay.y != _display.y) {
|
||||||
parent.target?.cursorModel
|
parent.target?.cursorModel
|
||||||
.updateDisplayOrigin(newDisplay.x, newDisplay.y);
|
.updateDisplayOrigin(newDisplay.x, newDisplay.y);
|
||||||
}
|
}
|
||||||
_display = newDisplay;
|
_display = newDisplay;
|
||||||
_updateSessionWidthHeight(peerId);
|
_updateSessionWidthHeight(sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSwitchDisplay(Map<String, dynamic> evt, String peerId) {
|
handleSwitchDisplay(
|
||||||
|
Map<String, dynamic> evt, SessionID sessionId, String peerId) {
|
||||||
_pi.currentDisplay = int.parse(evt['display']);
|
_pi.currentDisplay = int.parse(evt['display']);
|
||||||
var newDisplay = Display();
|
var newDisplay = Display();
|
||||||
newDisplay.x = double.tryParse(evt['x']) ?? newDisplay.x;
|
newDisplay.x = double.tryParse(evt['x']) ?? newDisplay.x;
|
||||||
@ -306,7 +311,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
newDisplay.originalHeight =
|
newDisplay.originalHeight =
|
||||||
int.tryParse(evt['original_height']) ?? kInvalidResolutionValue;
|
int.tryParse(evt['original_height']) ?? kInvalidResolutionValue;
|
||||||
|
|
||||||
_updateCurDisplay(peerId, newDisplay);
|
_updateCurDisplay(sessionId, newDisplay);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CurrentDisplayState.find(peerId).value = _pi.currentDisplay;
|
CurrentDisplayState.find(peerId).value = _pi.currentDisplay;
|
||||||
@ -318,15 +323,15 @@ class FfiModel with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelMsgBox(Map<String, dynamic> evt, String id) {
|
cancelMsgBox(Map<String, dynamic> evt, SessionID sessionId) {
|
||||||
if (parent.target == null) return;
|
if (parent.target == null) return;
|
||||||
final dialogManager = parent.target!.dialogManager;
|
final dialogManager = parent.target!.dialogManager;
|
||||||
final tag = '$id-${evt['tag']}';
|
final tag = '$sessionId-${evt['tag']}';
|
||||||
dialogManager.dismissByTag(tag);
|
dialogManager.dismissByTag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle the message box event based on [evt] and [id].
|
/// Handle the message box event based on [evt] and [id].
|
||||||
handleMsgBox(Map<String, dynamic> evt, String id) {
|
handleMsgBox(Map<String, dynamic> evt, SessionID sessionId, String peerId) {
|
||||||
if (parent.target == null) return;
|
if (parent.target == null) return;
|
||||||
final dialogManager = parent.target!.dialogManager;
|
final dialogManager = parent.target!.dialogManager;
|
||||||
final type = evt['type'];
|
final type = evt['type'];
|
||||||
@ -334,43 +339,43 @@ class FfiModel with ChangeNotifier {
|
|||||||
final text = evt['text'];
|
final text = evt['text'];
|
||||||
final link = evt['link'];
|
final link = evt['link'];
|
||||||
if (type == 're-input-password') {
|
if (type == 're-input-password') {
|
||||||
wrongPasswordDialog(id, dialogManager, type, title, text);
|
wrongPasswordDialog(sessionId, dialogManager, type, title, text);
|
||||||
} else if (type == 'input-password') {
|
} else if (type == 'input-password') {
|
||||||
enterPasswordDialog(id, dialogManager);
|
enterPasswordDialog(sessionId, dialogManager);
|
||||||
} else if (type == 'session-login' || type == 'session-re-login') {
|
} else if (type == 'session-login' || type == 'session-re-login') {
|
||||||
enterUserLoginDialog(id, dialogManager);
|
enterUserLoginDialog(sessionId, dialogManager);
|
||||||
} else if (type == 'session-login-password' ||
|
} else if (type == 'session-login-password' ||
|
||||||
type == 'session-login-password') {
|
type == 'session-login-password') {
|
||||||
enterUserLoginAndPasswordDialog(id, dialogManager);
|
enterUserLoginAndPasswordDialog(sessionId, dialogManager);
|
||||||
} else if (type == 'restarting') {
|
} else if (type == 'restarting') {
|
||||||
showMsgBox(id, type, title, text, link, false, dialogManager,
|
showMsgBox(sessionId, type, title, text, link, false, dialogManager,
|
||||||
hasCancel: false);
|
hasCancel: false);
|
||||||
} else if (type == 'wait-remote-accept-nook') {
|
} else if (type == 'wait-remote-accept-nook') {
|
||||||
showWaitAcceptDialog(id, type, title, text, dialogManager);
|
showWaitAcceptDialog(sessionId, type, title, text, dialogManager);
|
||||||
} else if (type == 'on-uac' || type == 'on-foreground-elevated') {
|
} else if (type == 'on-uac' || type == 'on-foreground-elevated') {
|
||||||
showOnBlockDialog(id, type, title, text, dialogManager);
|
showOnBlockDialog(sessionId, type, title, text, dialogManager);
|
||||||
} else if (type == 'wait-uac') {
|
} else if (type == 'wait-uac') {
|
||||||
showWaitUacDialog(id, dialogManager, type);
|
showWaitUacDialog(sessionId, dialogManager, type);
|
||||||
} else if (type == 'elevation-error') {
|
} else if (type == 'elevation-error') {
|
||||||
showElevationError(id, type, title, text, dialogManager);
|
showElevationError(sessionId, type, title, text, dialogManager);
|
||||||
} else if (type == 'relay-hint') {
|
} else if (type == 'relay-hint') {
|
||||||
showRelayHintDialog(id, type, title, text, dialogManager);
|
showRelayHintDialog(sessionId, type, title, text, dialogManager);
|
||||||
} else {
|
} else {
|
||||||
var hasRetry = evt['hasRetry'] == 'true';
|
var hasRetry = evt['hasRetry'] == 'true';
|
||||||
showMsgBox(id, type, title, text, link, hasRetry, dialogManager);
|
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show a message box with [type], [title] and [text].
|
/// Show a message box with [type], [title] and [text].
|
||||||
showMsgBox(String id, String type, String title, String text, String link,
|
showMsgBox(SessionID sessionId, String type, String title, String text,
|
||||||
bool hasRetry, OverlayDialogManager dialogManager,
|
String link, bool hasRetry, OverlayDialogManager dialogManager,
|
||||||
{bool? hasCancel}) {
|
{bool? hasCancel}) {
|
||||||
msgBox(id, type, title, text, link, dialogManager,
|
msgBox(sessionId, type, title, text, link, dialogManager,
|
||||||
hasCancel: hasCancel, reconnect: reconnect);
|
hasCancel: hasCancel, reconnect: reconnect);
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
if (hasRetry) {
|
if (hasRetry) {
|
||||||
_timer = Timer(Duration(seconds: _reconnects), () {
|
_timer = Timer(Duration(seconds: _reconnects), () {
|
||||||
reconnect(dialogManager, id, false);
|
reconnect(dialogManager, sessionId, false);
|
||||||
});
|
});
|
||||||
_reconnects *= 2;
|
_reconnects *= 2;
|
||||||
} else {
|
} else {
|
||||||
@ -378,17 +383,17 @@ class FfiModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reconnect(
|
void reconnect(OverlayDialogManager dialogManager, SessionID sessionId,
|
||||||
OverlayDialogManager dialogManager, String id, bool forceRelay) {
|
bool forceRelay) {
|
||||||
bind.sessionReconnect(id: id, forceRelay: forceRelay);
|
bind.sessionReconnect(sessionId: sessionId, forceRelay: forceRelay);
|
||||||
clearPermissions();
|
clearPermissions();
|
||||||
dialogManager.showLoading(translate('Connecting...'),
|
dialogManager.showLoading(translate('Connecting...'),
|
||||||
onCancel: closeConnection);
|
onCancel: closeConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showRelayHintDialog(String id, String type, String title, String text,
|
void showRelayHintDialog(SessionID sessionId, String type, String title,
|
||||||
OverlayDialogManager dialogManager) {
|
String text, OverlayDialogManager dialogManager) {
|
||||||
dialogManager.show(tag: '$id-$type', (setState, close, context) {
|
dialogManager.show(tag: '$sessionId-$type', (setState, close, context) {
|
||||||
onClose() {
|
onClose() {
|
||||||
closeConnection();
|
closeConnection();
|
||||||
close();
|
close();
|
||||||
@ -403,15 +408,17 @@ class FfiModel with ChangeNotifier {
|
|||||||
actions: [
|
actions: [
|
||||||
dialogButton('Close', onPressed: onClose, isOutline: true),
|
dialogButton('Close', onPressed: onClose, isOutline: true),
|
||||||
dialogButton('Retry',
|
dialogButton('Retry',
|
||||||
onPressed: () => reconnect(dialogManager, id, false)),
|
onPressed: () => reconnect(dialogManager, sessionId, false)),
|
||||||
dialogButton('Connect via relay',
|
dialogButton('Connect via relay',
|
||||||
onPressed: () => reconnect(dialogManager, id, true),
|
onPressed: () => reconnect(dialogManager, sessionId, true),
|
||||||
buttonStyle: style),
|
buttonStyle: style),
|
||||||
dialogButton('Always connect via relay', onPressed: () {
|
dialogButton('Always connect via relay', onPressed: () {
|
||||||
const option = 'force-always-relay';
|
const option = 'force-always-relay';
|
||||||
bind.sessionPeerOption(
|
bind.sessionPeerOption(
|
||||||
id: id, name: option, value: bool2option(option, true));
|
sessionId: sessionId,
|
||||||
reconnect(dialogManager, id, true);
|
name: option,
|
||||||
|
value: bool2option(option, true));
|
||||||
|
reconnect(dialogManager, sessionId, true);
|
||||||
}, buttonStyle: style),
|
}, buttonStyle: style),
|
||||||
],
|
],
|
||||||
onCancel: onClose,
|
onCancel: onClose,
|
||||||
@ -419,13 +426,14 @@ class FfiModel with ChangeNotifier {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateSessionWidthHeight(String id) {
|
_updateSessionWidthHeight(SessionID sessionId) {
|
||||||
parent.target?.canvasModel.updateViewStyle();
|
parent.target?.canvasModel.updateViewStyle();
|
||||||
if (display.width <= 0 || display.height <= 0) {
|
if (display.width <= 0 || display.height <= 0) {
|
||||||
debugPrintStack(
|
debugPrintStack(
|
||||||
label: 'invalid display size (${display.width},${display.height})');
|
label: 'invalid display size (${display.width},${display.height})');
|
||||||
} else {
|
} else {
|
||||||
bind.sessionSetSize(id: id, width: display.width, height: display.height);
|
bind.sessionSetSize(
|
||||||
|
sessionId: sessionId, width: display.width, height: display.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,8 +469,9 @@ class FfiModel with ChangeNotifier {
|
|||||||
.showMobileActionsOverlay(ffi: parent.target!));
|
.showMobileActionsOverlay(ffi: parent.target!));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_touchMode =
|
_touchMode = await bind.sessionGetOption(
|
||||||
await bind.sessionGetOption(id: peerId, arg: 'touch-mode') != '';
|
sessionId: sessionId, arg: 'touch-mode') !=
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connType == ConnType.fileTransfer) {
|
if (connType == ConnType.fileTransfer) {
|
||||||
@ -476,7 +485,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
stateGlobal.displaysCount.value = _pi.displays.length;
|
stateGlobal.displaysCount.value = _pi.displays.length;
|
||||||
if (_pi.currentDisplay < _pi.displays.length) {
|
if (_pi.currentDisplay < _pi.displays.length) {
|
||||||
_display = _pi.displays[_pi.currentDisplay];
|
_display = _pi.displays[_pi.currentDisplay];
|
||||||
_updateSessionWidthHeight(peerId);
|
_updateSessionWidthHeight(sessionId);
|
||||||
}
|
}
|
||||||
if (displays.isNotEmpty) {
|
if (displays.isNotEmpty) {
|
||||||
parent.target?.dialogManager.showLoading(
|
parent.target?.dialogManager.showLoading(
|
||||||
@ -491,8 +500,10 @@ class FfiModel with ChangeNotifier {
|
|||||||
parent.target?.elevationModel.onPeerInfo(_pi);
|
parent.target?.elevationModel.onPeerInfo(_pi);
|
||||||
}
|
}
|
||||||
if (connType == ConnType.defaultConn) {
|
if (connType == ConnType.defaultConn) {
|
||||||
setViewOnly(peerId,
|
setViewOnly(
|
||||||
bind.sessionGetToggleOptionSync(id: peerId, arg: 'view-only'));
|
peerId,
|
||||||
|
bind.sessionGetToggleOptionSync(
|
||||||
|
sessionId: sessionId, arg: 'view-only'));
|
||||||
}
|
}
|
||||||
if (connType == ConnType.defaultConn) {
|
if (connType == ConnType.defaultConn) {
|
||||||
final platform_additions = evt['platform_additions'];
|
final platform_additions = evt['platform_additions'];
|
||||||
@ -547,7 +558,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Handle the peer info synchronization event based on [evt].
|
/// Handle the peer info synchronization event based on [evt].
|
||||||
handleSyncPeerInfo(Map<String, dynamic> evt, String peerId) async {
|
handleSyncPeerInfo(Map<String, dynamic> evt, SessionID sessionId) async {
|
||||||
if (evt['displays'] != null) {
|
if (evt['displays'] != null) {
|
||||||
List<dynamic> displays = json.decode(evt['displays']);
|
List<dynamic> displays = json.decode(evt['displays']);
|
||||||
List<Display> newDisplays = [];
|
List<Display> newDisplays = [];
|
||||||
@ -557,7 +568,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
_pi.displays = newDisplays;
|
_pi.displays = newDisplays;
|
||||||
stateGlobal.displaysCount.value = _pi.displays.length;
|
stateGlobal.displaysCount.value = _pi.displays.length;
|
||||||
if (_pi.currentDisplay >= 0 && _pi.currentDisplay < _pi.displays.length) {
|
if (_pi.currentDisplay >= 0 && _pi.currentDisplay < _pi.displays.length) {
|
||||||
_updateCurDisplay(peerId, _pi.displays[_pi.currentDisplay]);
|
_updateCurDisplay(sessionId, _pi.displays[_pi.currentDisplay]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -573,11 +584,12 @@ class FfiModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePrivacyMode(Map<String, dynamic> evt, String peerId) {
|
updatePrivacyMode(
|
||||||
|
Map<String, dynamic> evt, SessionID sessionId, String peerId) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
try {
|
try {
|
||||||
PrivacyModeState.find(peerId).value =
|
PrivacyModeState.find(peerId).value = bind.sessionGetToggleOptionSync(
|
||||||
bind.sessionGetToggleOptionSync(id: peerId, arg: 'privacy-mode');
|
sessionId: sessionId, arg: 'privacy-mode');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
@ -592,8 +604,8 @@ class FfiModel with ChangeNotifier {
|
|||||||
if (value) {
|
if (value) {
|
||||||
ShowRemoteCursorState.find(id).value = value;
|
ShowRemoteCursorState.find(id).value = value;
|
||||||
} else {
|
} else {
|
||||||
ShowRemoteCursorState.find(id).value =
|
ShowRemoteCursorState.find(id).value = bind.sessionGetToggleOptionSync(
|
||||||
bind.sessionGetToggleOptionSync(id: id, arg: 'show-remote-cursor');
|
sessionId: sessionId, arg: 'show-remote-cursor');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//
|
//
|
||||||
@ -612,11 +624,15 @@ class ImageModel with ChangeNotifier {
|
|||||||
|
|
||||||
String id = '';
|
String id = '';
|
||||||
|
|
||||||
|
late final SessionID sessionId;
|
||||||
|
|
||||||
WeakReference<FFI> parent;
|
WeakReference<FFI> parent;
|
||||||
|
|
||||||
final List<Function(String)> callbacksOnFirstImage = [];
|
final List<Function(String)> callbacksOnFirstImage = [];
|
||||||
|
|
||||||
ImageModel(this.parent);
|
ImageModel(this.parent) {
|
||||||
|
sessionId = parent.target!.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
addCallbackOnFirstImage(Function(String) cb) => callbacksOnFirstImage.add(cb);
|
addCallbackOnFirstImage(Function(String) cb) => callbacksOnFirstImage.add(cb);
|
||||||
|
|
||||||
@ -645,7 +661,7 @@ class ImageModel with ChangeNotifier {
|
|||||||
isWeb ? ui.PixelFormat.rgba8888 : ui.PixelFormat.bgra8888,
|
isWeb ? ui.PixelFormat.rgba8888 : ui.PixelFormat.bgra8888,
|
||||||
onPixelsCopied: () {
|
onPixelsCopied: () {
|
||||||
// Unlock the rgba memory from rust codes.
|
// Unlock the rgba memory from rust codes.
|
||||||
platformFFI.nextRgba(id);
|
platformFFI.nextRgba(sessionId);
|
||||||
}).then((image) {
|
}).then((image) {
|
||||||
if (parent.target?.id != pid) return;
|
if (parent.target?.id != pid) return;
|
||||||
try {
|
try {
|
||||||
@ -674,7 +690,7 @@ class ImageModel with ChangeNotifier {
|
|||||||
await initializeCursorAndCanvas(parent.target!);
|
await initializeCursorAndCanvas(parent.target!);
|
||||||
}
|
}
|
||||||
if (parent.target?.ffiModel.isPeerAndroid ?? false) {
|
if (parent.target?.ffiModel.isPeerAndroid ?? false) {
|
||||||
bind.sessionSetViewStyle(id: id, value: 'adaptive');
|
bind.sessionSetViewStyle(sessionId: sessionId, value: 'adaptive');
|
||||||
parent.target?.canvasModel.updateViewStyle();
|
parent.target?.canvasModel.updateViewStyle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -793,6 +809,7 @@ class CanvasModel with ChangeNotifier {
|
|||||||
// double windowBorderWidth = 0.0;
|
// double windowBorderWidth = 0.0;
|
||||||
// remote id
|
// remote id
|
||||||
String id = '';
|
String id = '';
|
||||||
|
late final SessionID sessionId;
|
||||||
// scroll offset x percent
|
// scroll offset x percent
|
||||||
double _scrollX = 0.0;
|
double _scrollX = 0.0;
|
||||||
// scroll offset y percent
|
// scroll offset y percent
|
||||||
@ -804,7 +821,9 @@ class CanvasModel with ChangeNotifier {
|
|||||||
|
|
||||||
WeakReference<FFI> parent;
|
WeakReference<FFI> parent;
|
||||||
|
|
||||||
CanvasModel(this.parent);
|
CanvasModel(this.parent) {
|
||||||
|
sessionId = parent.target!.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
double get x => _x;
|
double get x => _x;
|
||||||
double get y => _y;
|
double get y => _y;
|
||||||
@ -847,7 +866,7 @@ class CanvasModel with ChangeNotifier {
|
|||||||
return Size(w < 0 ? 0 : w, h < 0 ? 0 : h);
|
return Size(w < 0 ? 0 : w, h < 0 ? 0 : h);
|
||||||
}
|
}
|
||||||
|
|
||||||
final style = await bind.sessionGetViewStyle(id: id);
|
final style = await bind.sessionGetViewStyle(sessionId: sessionId);
|
||||||
if (style == null) {
|
if (style == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -883,7 +902,7 @@ class CanvasModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateScrollStyle() async {
|
updateScrollStyle() async {
|
||||||
final style = await bind.sessionGetScrollStyle(id: id);
|
final style = await bind.sessionGetScrollStyle(sessionId: sessionId);
|
||||||
if (style == kRemoteScrollStyleBar) {
|
if (style == kRemoteScrollStyleBar) {
|
||||||
_scrollStyle = ScrollStyle.scrollbar;
|
_scrollStyle = ScrollStyle.scrollbar;
|
||||||
_resetScroll();
|
_resetScroll();
|
||||||
@ -1358,8 +1377,8 @@ class CursorModel with ChangeNotifier {
|
|||||||
Future<bool> _updateCache(
|
Future<bool> _updateCache(
|
||||||
Uint8List rgba, ui.Image image, int id, int w, int h) async {
|
Uint8List rgba, ui.Image image, int id, int w, int h) async {
|
||||||
Uint8List? data;
|
Uint8List? data;
|
||||||
img2.Image imgOrigin =
|
img2.Image imgOrigin = img2.Image.fromBytes(
|
||||||
img2.Image.fromBytes(width: w, height:h, bytes: rgba.buffer, order: img2.ChannelOrder.rgba);
|
width: w, height: h, bytes: rgba.buffer, order: img2.ChannelOrder.rgba);
|
||||||
if (Platform.isWindows) {
|
if (Platform.isWindows) {
|
||||||
data = imgOrigin.getBytes(order: img2.ChannelOrder.bgra);
|
data = imgOrigin.getBytes(order: img2.ChannelOrder.bgra);
|
||||||
} else {
|
} else {
|
||||||
@ -1474,9 +1493,9 @@ class QualityMonitorModel with ChangeNotifier {
|
|||||||
bool get show => _show;
|
bool get show => _show;
|
||||||
QualityMonitorData get data => _data;
|
QualityMonitorData get data => _data;
|
||||||
|
|
||||||
checkShowQualityMonitor(String id) async {
|
checkShowQualityMonitor(SessionID sessionId) async {
|
||||||
final show = await bind.sessionGetToggleOption(
|
final show = await bind.sessionGetToggleOption(
|
||||||
id: id, arg: 'show-quality-monitor') ==
|
sessionId: sessionId, arg: 'show-quality-monitor') ==
|
||||||
true;
|
true;
|
||||||
if (_show != show) {
|
if (_show != show) {
|
||||||
_show = show;
|
_show = show;
|
||||||
@ -1510,32 +1529,35 @@ class RecordingModel with ChangeNotifier {
|
|||||||
|
|
||||||
onSwitchDisplay() {
|
onSwitchDisplay() {
|
||||||
if (isIOS || !_start) return;
|
if (isIOS || !_start) return;
|
||||||
var id = parent.target?.id;
|
final sessionId = parent.target?.sessionId;
|
||||||
int? width = parent.target?.canvasModel.getDisplayWidth();
|
int? width = parent.target?.canvasModel.getDisplayWidth();
|
||||||
int? height = parent.target?.canvasModel.getDisplayHeight();
|
int? height = parent.target?.canvasModel.getDisplayHeight();
|
||||||
if (id == null || width == null || height == null) return;
|
if (sessionId == null || width == null || height == null) return;
|
||||||
bind.sessionRecordScreen(id: id, start: true, width: width, height: height);
|
bind.sessionRecordScreen(
|
||||||
|
sessionId: sessionId, start: true, width: width, height: height);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
if (isIOS) return;
|
if (isIOS) return;
|
||||||
var id = parent.target?.id;
|
final sessionId = parent.target?.sessionId;
|
||||||
if (id == null) return;
|
if (sessionId == null) return;
|
||||||
_start = !_start;
|
_start = !_start;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
if (_start) {
|
if (_start) {
|
||||||
bind.sessionRefresh(id: id);
|
bind.sessionRefresh(sessionId: sessionId);
|
||||||
} else {
|
} else {
|
||||||
bind.sessionRecordScreen(id: id, start: false, width: 0, height: 0);
|
bind.sessionRecordScreen(
|
||||||
|
sessionId: sessionId, start: false, width: 0, height: 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose() {
|
onClose() {
|
||||||
if (isIOS) return;
|
if (isIOS) return;
|
||||||
var id = parent.target?.id;
|
final sessionId = parent.target?.sessionId;
|
||||||
if (id == null) return;
|
if (sessionId == null) return;
|
||||||
_start = false;
|
_start = false;
|
||||||
bind.sessionRecordScreen(id: id, start: false, width: 0, height: 0);
|
bind.sessionRecordScreen(
|
||||||
|
sessionId: sessionId, start: false, width: 0, height: 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1558,6 +1580,7 @@ enum ConnType { defaultConn, fileTransfer, portForward, rdp }
|
|||||||
|
|
||||||
/// Flutter state manager and data communication with the Rust core.
|
/// Flutter state manager and data communication with the Rust core.
|
||||||
class FFI {
|
class FFI {
|
||||||
|
final sessionId = Uuid().v4obj();
|
||||||
var id = '';
|
var id = '';
|
||||||
var version = '';
|
var version = '';
|
||||||
var connType = ConnType.defaultConn;
|
var connType = ConnType.defaultConn;
|
||||||
@ -1610,10 +1633,8 @@ class FFI {
|
|||||||
assert(!(isFileTransfer && isPortForward), 'more than one connect type');
|
assert(!(isFileTransfer && isPortForward), 'more than one connect type');
|
||||||
if (isFileTransfer) {
|
if (isFileTransfer) {
|
||||||
connType = ConnType.fileTransfer;
|
connType = ConnType.fileTransfer;
|
||||||
id = 'ft_$id';
|
|
||||||
} else if (isPortForward) {
|
} else if (isPortForward) {
|
||||||
connType = ConnType.portForward;
|
connType = ConnType.portForward;
|
||||||
id = 'pf_$id';
|
|
||||||
} else {
|
} else {
|
||||||
chatModel.resetClientMode();
|
chatModel.resetClientMode();
|
||||||
connType = ConnType.defaultConn;
|
connType = ConnType.defaultConn;
|
||||||
@ -1623,6 +1644,7 @@ class FFI {
|
|||||||
}
|
}
|
||||||
// ignore: unused_local_variable
|
// ignore: unused_local_variable
|
||||||
final addRes = bind.sessionAddSync(
|
final addRes = bind.sessionAddSync(
|
||||||
|
sessionId: sessionId,
|
||||||
id: id,
|
id: id,
|
||||||
isFileTransfer: isFileTransfer,
|
isFileTransfer: isFileTransfer,
|
||||||
isPortForward: isPortForward,
|
isPortForward: isPortForward,
|
||||||
@ -1631,8 +1653,8 @@ class FFI {
|
|||||||
forceRelay: forceRelay ?? false,
|
forceRelay: forceRelay ?? false,
|
||||||
password: password ?? "",
|
password: password ?? "",
|
||||||
);
|
);
|
||||||
final stream = bind.sessionStart(id: id);
|
final stream = bind.sessionStart(sessionId: sessionId, id: id);
|
||||||
final cb = ffiModel.startEventListener(id);
|
final cb = ffiModel.startEventListener(sessionId, id);
|
||||||
() async {
|
() async {
|
||||||
final useTextureRender = bind.mainUseTextureRender();
|
final useTextureRender = bind.mainUseTextureRender();
|
||||||
// Preserved for the rgba data.
|
// Preserved for the rgba data.
|
||||||
@ -1664,11 +1686,11 @@ class FFI {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fetch the image buffer from rust codes.
|
// Fetch the image buffer from rust codes.
|
||||||
final sz = platformFFI.getRgbaSize(id);
|
final sz = platformFFI.getRgbaSize(sessionId);
|
||||||
if (sz == null || sz == 0) {
|
if (sz == null || sz == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final rgba = platformFFI.getRgba(id, sz);
|
final rgba = platformFFI.getRgba(sessionId, sz);
|
||||||
if (rgba != null) {
|
if (rgba != null) {
|
||||||
imageModel.onRgba(rgba);
|
imageModel.onRgba(rgba);
|
||||||
}
|
}
|
||||||
@ -1682,10 +1704,10 @@ class FFI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Login with [password], choose if the client should [remember] it.
|
/// Login with [password], choose if the client should [remember] it.
|
||||||
void login(String osUsername, String osPassword, String id, String password,
|
void login(String osUsername, String osPassword, SessionID sessionId,
|
||||||
bool remember) {
|
String password, bool remember) {
|
||||||
bind.sessionLogin(
|
bind.sessionLogin(
|
||||||
id: id,
|
sessionId: sessionId,
|
||||||
osUsername: osUsername,
|
osUsername: osUsername,
|
||||||
osPassword: osPassword,
|
osPassword: osPassword,
|
||||||
password: password,
|
password: password,
|
||||||
@ -1696,15 +1718,21 @@ class FFI {
|
|||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
chatModel.close();
|
chatModel.close();
|
||||||
if (imageModel.image != null && !isWebDesktop) {
|
if (imageModel.image != null && !isWebDesktop) {
|
||||||
await setCanvasConfig(id, cursorModel.x, cursorModel.y, canvasModel.x,
|
await setCanvasConfig(
|
||||||
canvasModel.y, canvasModel.scale, ffiModel.pi.currentDisplay);
|
sessionId,
|
||||||
|
cursorModel.x,
|
||||||
|
cursorModel.y,
|
||||||
|
canvasModel.x,
|
||||||
|
canvasModel.y,
|
||||||
|
canvasModel.scale,
|
||||||
|
ffiModel.pi.currentDisplay);
|
||||||
}
|
}
|
||||||
imageModel.update(null);
|
imageModel.update(null);
|
||||||
cursorModel.clear();
|
cursorModel.clear();
|
||||||
ffiModel.clear();
|
ffiModel.clear();
|
||||||
canvasModel.clear();
|
canvasModel.clear();
|
||||||
inputModel.resetModifiers();
|
inputModel.resetModifiers();
|
||||||
await bind.sessionClose(id: id);
|
await bind.sessionClose(sessionId: sessionId);
|
||||||
debugPrint('model $id closed');
|
debugPrint('model $id closed');
|
||||||
id = '';
|
id = '';
|
||||||
}
|
}
|
||||||
@ -1795,8 +1823,14 @@ class PeerInfo {
|
|||||||
|
|
||||||
const canvasKey = 'canvas';
|
const canvasKey = 'canvas';
|
||||||
|
|
||||||
Future<void> setCanvasConfig(String id, double xCursor, double yCursor,
|
Future<void> setCanvasConfig(
|
||||||
double xCanvas, double yCanvas, double scale, int currentDisplay) async {
|
SessionID sessionId,
|
||||||
|
double xCursor,
|
||||||
|
double yCursor,
|
||||||
|
double xCanvas,
|
||||||
|
double yCanvas,
|
||||||
|
double scale,
|
||||||
|
int currentDisplay) async {
|
||||||
final p = <String, dynamic>{};
|
final p = <String, dynamic>{};
|
||||||
p['xCursor'] = xCursor;
|
p['xCursor'] = xCursor;
|
||||||
p['yCursor'] = yCursor;
|
p['yCursor'] = yCursor;
|
||||||
@ -1804,12 +1838,14 @@ Future<void> setCanvasConfig(String id, double xCursor, double yCursor,
|
|||||||
p['yCanvas'] = yCanvas;
|
p['yCanvas'] = yCanvas;
|
||||||
p['scale'] = scale;
|
p['scale'] = scale;
|
||||||
p['currentDisplay'] = currentDisplay;
|
p['currentDisplay'] = currentDisplay;
|
||||||
await bind.sessionSetFlutterConfig(id: id, k: canvasKey, v: jsonEncode(p));
|
await bind.sessionSetFlutterConfig(
|
||||||
|
sessionId: sessionId, k: canvasKey, v: jsonEncode(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>?> getCanvasConfig(String id) async {
|
Future<Map<String, dynamic>?> getCanvasConfig(SessionID sessionId) async {
|
||||||
if (!isWebDesktop) return null;
|
if (!isWebDesktop) return null;
|
||||||
var p = await bind.sessionGetFlutterConfig(id: id, k: canvasKey);
|
var p =
|
||||||
|
await bind.sessionGetFlutterConfig(sessionId: sessionId, k: canvasKey);
|
||||||
if (p == null || p.isEmpty) return null;
|
if (p == null || p.isEmpty) return null;
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> m = json.decode(p);
|
Map<String, dynamic> m = json.decode(p);
|
||||||
@ -1819,12 +1855,8 @@ Future<Map<String, dynamic>?> getCanvasConfig(String id) async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removePreference(String id) async {
|
|
||||||
await bind.sessionSetFlutterConfig(id: id, k: canvasKey, v: '');
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> initializeCursorAndCanvas(FFI ffi) async {
|
Future<void> initializeCursorAndCanvas(FFI ffi) async {
|
||||||
var p = await getCanvasConfig(ffi.id);
|
var p = await getCanvasConfig(ffi.sessionId);
|
||||||
int currentDisplay = 0;
|
int currentDisplay = 0;
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
currentDisplay = p['currentDisplay'];
|
currentDisplay = p['currentDisplay'];
|
||||||
|
@ -104,9 +104,10 @@ class PlatformFFI {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8List? getRgba(String id, int bufSize) {
|
Uint8List? getRgba(SessionID sessionId, int bufSize) {
|
||||||
if (_session_get_rgba == null) return null;
|
if (_session_get_rgba == null) return null;
|
||||||
var a = id.toNativeUtf8();
|
final sessionIdStr = sessionId.toString();
|
||||||
|
var a = sessionIdStr.toNativeUtf8();
|
||||||
try {
|
try {
|
||||||
final buffer = _session_get_rgba!(a);
|
final buffer = _session_get_rgba!(a);
|
||||||
if (buffer == nullptr) {
|
if (buffer == nullptr) {
|
||||||
@ -119,24 +120,27 @@ class PlatformFFI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int? getRgbaSize(String id) {
|
int? getRgbaSize(SessionID sessionId) {
|
||||||
if (_session_get_rgba_size == null) return null;
|
if (_session_get_rgba_size == null) return null;
|
||||||
var a = id.toNativeUtf8();
|
final sessionIdStr = sessionId.toString();
|
||||||
|
var a = sessionIdStr.toNativeUtf8();
|
||||||
final bufferSize = _session_get_rgba_size!(a);
|
final bufferSize = _session_get_rgba_size!(a);
|
||||||
malloc.free(a);
|
malloc.free(a);
|
||||||
return bufferSize;
|
return bufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nextRgba(String id) {
|
void nextRgba(SessionID sessionId) {
|
||||||
if (_session_next_rgba == null) return;
|
if (_session_next_rgba == null) return;
|
||||||
final a = id.toNativeUtf8();
|
final sessionIdStr = sessionId.toString();
|
||||||
|
final a = sessionIdStr.toNativeUtf8();
|
||||||
_session_next_rgba!(a);
|
_session_next_rgba!(a);
|
||||||
malloc.free(a);
|
malloc.free(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerTexture(String id, int ptr) {
|
void registerTexture(SessionID sessionId, int ptr) {
|
||||||
if (_session_register_texture == null) return;
|
if (_session_register_texture == null) return;
|
||||||
final a = id.toNativeUtf8();
|
final sessionIdStr = sessionId.toString();
|
||||||
|
final a = sessionIdStr.toNativeUtf8();
|
||||||
_session_register_texture!(a, ptr);
|
_session_register_texture!(a, ptr);
|
||||||
malloc.free(a);
|
malloc.free(a);
|
||||||
}
|
}
|
||||||
|
@ -343,7 +343,7 @@ class ServerModel with ChangeNotifier {
|
|||||||
Future<void> startService() async {
|
Future<void> startService() async {
|
||||||
_isStart = true;
|
_isStart = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
parent.target?.ffiModel.updateEventListener("");
|
parent.target?.ffiModel.updateEventListener(parent.target!.sessionId, "");
|
||||||
await parent.target?.invokeMethod("init_service");
|
await parent.target?.invokeMethod("init_service");
|
||||||
// ugly is here, because for desktop, below is useless
|
// ugly is here, because for desktop, below is useless
|
||||||
await bind.mainStartService();
|
await bind.mainStartService();
|
||||||
|
@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
void handlePluginEvent(
|
void handlePluginEvent(
|
||||||
Map<String, dynamic> evt,
|
Map<String, dynamic> evt,
|
||||||
String peer,
|
|
||||||
Function(Map<String, dynamic> e) handleMsgBox,
|
Function(Map<String, dynamic> e) handleMsgBox,
|
||||||
) {
|
) {
|
||||||
Map<String, dynamic>? content;
|
Map<String, dynamic>? content;
|
||||||
|
@ -275,7 +275,7 @@ class PluginItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleReloading(Map<String, dynamic> evt, String peer) {
|
void handleReloading(Map<String, dynamic> evt) {
|
||||||
if (evt['id'] == null || evt['location'] == null) {
|
if (evt['id'] == null || evt['location'] == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -295,7 +295,7 @@ void handleReloading(Map<String, dynamic> evt, String peer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleOption(Map<String, dynamic> evt, String peer) {
|
void handleOption(Map<String, dynamic> evt) {
|
||||||
updateOption(
|
updateOption(
|
||||||
evt['location'], evt['id'], evt['peer'] ?? '', evt['key'], evt['value']);
|
evt['location'], evt['id'], evt['peer'] ?? '', evt['key'], evt['value']);
|
||||||
}
|
}
|
||||||
|
@ -1331,7 +1331,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
uuid:
|
uuid:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: uuid
|
name: uuid
|
||||||
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
|
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
|
||||||
|
@ -95,6 +95,7 @@ dependencies:
|
|||||||
texture_rgba_renderer: ^0.0.16
|
texture_rgba_renderer: ^0.0.16
|
||||||
percent_indicator: ^4.2.2
|
percent_indicator: ^4.2.2
|
||||||
dropdown_button2: ^2.0.0
|
dropdown_button2: ^2.0.0
|
||||||
|
uuid: ^3.0.7
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
icons_launcher: ^2.0.4
|
icons_launcher: ^2.0.4
|
||||||
|
@ -5,7 +5,7 @@ use hbb_common::{
|
|||||||
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
||||||
Mutex as TokioMutex,
|
Mutex as TokioMutex,
|
||||||
},
|
},
|
||||||
ResultType,
|
ResultType, SessionID,
|
||||||
};
|
};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
@ -59,7 +59,7 @@ struct ConnEnabled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct MsgChannel {
|
struct MsgChannel {
|
||||||
peer_id: String,
|
session_uuid: SessionID,
|
||||||
conn_id: i32,
|
conn_id: i32,
|
||||||
sender: UnboundedSender<ClipboardFile>,
|
sender: UnboundedSender<ClipboardFile>,
|
||||||
receiver: Arc<TokioMutex<UnboundedReceiver<ClipboardFile>>>,
|
receiver: Arc<TokioMutex<UnboundedReceiver<ClipboardFile>>>,
|
||||||
@ -78,20 +78,23 @@ lazy_static::lazy_static! {
|
|||||||
static ref PROCESS_SIDE: RwLock<ProcessSide> = RwLock::new(ProcessSide::UnknownSide);
|
static ref PROCESS_SIDE: RwLock<ProcessSide> = RwLock::new(ProcessSide::UnknownSide);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_client_conn_id(peer_id: &str) -> Option<i32> {
|
pub fn get_client_conn_id(session_uuid: &SessionID) -> Option<i32> {
|
||||||
VEC_MSG_CHANNEL
|
VEC_MSG_CHANNEL
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|x| x.peer_id == peer_id.to_owned())
|
.find(|x| x.session_uuid == session_uuid.to_owned())
|
||||||
.map(|x| x.conn_id)
|
.map(|x| x.conn_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_rx_cliprdr_client(
|
pub fn get_rx_cliprdr_client(
|
||||||
peer_id: &str,
|
session_uuid: &SessionID,
|
||||||
) -> (i32, Arc<TokioMutex<UnboundedReceiver<ClipboardFile>>>) {
|
) -> (i32, Arc<TokioMutex<UnboundedReceiver<ClipboardFile>>>) {
|
||||||
let mut lock = VEC_MSG_CHANNEL.write().unwrap();
|
let mut lock = VEC_MSG_CHANNEL.write().unwrap();
|
||||||
match lock.iter().find(|x| x.peer_id == peer_id.to_owned()) {
|
match lock
|
||||||
|
.iter()
|
||||||
|
.find(|x| x.session_uuid == session_uuid.to_owned())
|
||||||
|
{
|
||||||
Some(msg_channel) => (msg_channel.conn_id, msg_channel.receiver.clone()),
|
Some(msg_channel) => (msg_channel.conn_id, msg_channel.receiver.clone()),
|
||||||
None => {
|
None => {
|
||||||
let (sender, receiver) = unbounded_channel();
|
let (sender, receiver) = unbounded_channel();
|
||||||
@ -99,7 +102,7 @@ pub fn get_rx_cliprdr_client(
|
|||||||
let receiver2 = receiver.clone();
|
let receiver2 = receiver.clone();
|
||||||
let conn_id = lock.len() as i32 + 1;
|
let conn_id = lock.len() as i32 + 1;
|
||||||
let msg_channel = MsgChannel {
|
let msg_channel = MsgChannel {
|
||||||
peer_id: peer_id.to_owned(),
|
session_uuid: session_uuid.to_owned(),
|
||||||
conn_id,
|
conn_id,
|
||||||
sender,
|
sender,
|
||||||
receiver,
|
receiver,
|
||||||
@ -119,7 +122,7 @@ pub fn get_rx_cliprdr_server(conn_id: i32) -> Arc<TokioMutex<UnboundedReceiver<C
|
|||||||
let receiver = Arc::new(TokioMutex::new(receiver));
|
let receiver = Arc::new(TokioMutex::new(receiver));
|
||||||
let receiver2 = receiver.clone();
|
let receiver2 = receiver.clone();
|
||||||
let msg_channel = MsgChannel {
|
let msg_channel = MsgChannel {
|
||||||
peer_id: "".to_owned(),
|
session_uuid: SessionID::nil(),
|
||||||
conn_id,
|
conn_id,
|
||||||
sender,
|
sender,
|
||||||
receiver,
|
receiver,
|
||||||
|
@ -36,6 +36,7 @@ backtrace = "0.3"
|
|||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
dlopen = "0.1"
|
dlopen = "0.1"
|
||||||
toml = "0.7"
|
toml = "0.7"
|
||||||
|
uuid = { version = "1.3", features = ["v4"] }
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
mac_address = "1.1"
|
mac_address = "1.1"
|
||||||
|
@ -43,15 +43,17 @@ pub use directories_next;
|
|||||||
pub use libc;
|
pub use libc;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
pub use sysinfo;
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
|
||||||
pub use dlopen;
|
pub use dlopen;
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
pub use sysinfo;
|
||||||
pub use toml;
|
pub use toml;
|
||||||
|
pub use uuid;
|
||||||
|
|
||||||
#[cfg(feature = "quic")]
|
#[cfg(feature = "quic")]
|
||||||
pub type Stream = quic::Connection;
|
pub type Stream = quic::Connection;
|
||||||
#[cfg(not(feature = "quic"))]
|
#[cfg(not(feature = "quic"))]
|
||||||
pub type Stream = tcp::FramedStream;
|
pub type Stream = tcp::FramedStream;
|
||||||
|
pub type SessionID = uuid::Uuid;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn sleep(sec: f32) {
|
pub async fn sleep(sec: f32) {
|
||||||
@ -395,7 +397,7 @@ mod test {
|
|||||||
assert!(!is_ipv6_str("[1:2::0]:"));
|
assert!(!is_ipv6_str("[1:2::0]:"));
|
||||||
assert!(!is_ipv6_str("1:2::0]:1"));
|
assert!(!is_ipv6_str("1:2::0]:1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ipv4() {
|
fn test_ipv4() {
|
||||||
assert!(is_ipv4_str("1.2.3.4"));
|
assert!(is_ipv4_str("1.2.3.4"));
|
||||||
@ -409,7 +411,7 @@ mod test {
|
|||||||
assert!(!is_ipv4_str("192.168.0.256"));
|
assert!(!is_ipv4_str("192.168.0.256"));
|
||||||
assert!(!is_ipv4_str("192.168.0.1/24"));
|
assert!(!is_ipv4_str("192.168.0.1/24"));
|
||||||
assert!(!is_ipv4_str("192.168.0."));
|
assert!(!is_ipv4_str("192.168.0."));
|
||||||
assert!(!is_ipv4_str("192.168..1"));
|
assert!(!is_ipv4_str("192.168..1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -672,9 +672,9 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
fn try_stop_clipboard(_self_id: &str) {
|
fn try_stop_clipboard(_self_uuid: &uuid::Uuid) {
|
||||||
#[cfg(feature = "flutter")]
|
#[cfg(feature = "flutter")]
|
||||||
if crate::flutter::other_sessions_running(_self_id) {
|
if crate::flutter::other_sessions_running(_self_uuid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TEXT_CLIPBOARD_STATE.lock().unwrap().running = false;
|
TEXT_CLIPBOARD_STATE.lock().unwrap().running = false;
|
||||||
|
@ -145,7 +145,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
|| self.handler.is_rdp();
|
|| self.handler.is_rdp();
|
||||||
if !is_conn_not_default {
|
if !is_conn_not_default {
|
||||||
(self.client_conn_id, rx_clip_client_lock) =
|
(self.client_conn_id, rx_clip_client_lock) =
|
||||||
clipboard::get_rx_cliprdr_client(&self.handler.id);
|
clipboard::get_rx_cliprdr_client(&self.handler.session_id);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -262,7 +262,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
Client::try_stop_clipboard(&self.handler.id);
|
Client::try_stop_clipboard(&self.handler.session_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_job_status(&mut self, id: i32, file_num: i32, err: Option<String>) {
|
fn handle_job_status(&mut self, id: i32, file_num: i32, err: Option<String>) {
|
||||||
|
120
src/flutter.rs
120
src/flutter.rs
@ -1,11 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::*,
|
client::*,
|
||||||
flutter_ffi::EventToUI,
|
flutter_ffi::{EventToUI, SessionID},
|
||||||
ui_session_interface::{io_loop, InvokeUiSession, Session},
|
ui_session_interface::{io_loop, InvokeUiSession, Session},
|
||||||
};
|
};
|
||||||
use flutter_rust_bridge::StreamSink;
|
use flutter_rust_bridge::StreamSink;
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
bail, config::LocalConfig, get_version_number, log, message_proto::*,
|
anyhow::anyhow, bail, config::LocalConfig, get_version_number, log, message_proto::*,
|
||||||
rendezvous_proto::ConnType, ResultType,
|
rendezvous_proto::ConnType, ResultType,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "flutter_texture_render")]
|
#[cfg(feature = "flutter_texture_render")]
|
||||||
@ -24,6 +24,7 @@ use std::{
|
|||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
os::raw::{c_char, c_int},
|
os::raw::{c_char, c_int},
|
||||||
|
str::FromStr,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,8 +41,8 @@ pub(crate) const APP_TYPE_DESKTOP_FILE_TRANSFER: &str = "file transfer";
|
|||||||
pub(crate) const APP_TYPE_DESKTOP_PORT_FORWARD: &str = "port forward";
|
pub(crate) const APP_TYPE_DESKTOP_PORT_FORWARD: &str = "port forward";
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub(crate) static ref CUR_SESSION_ID: RwLock<String> = Default::default();
|
pub(crate) static ref CUR_SESSION_ID: RwLock<SessionID> = Default::default();
|
||||||
pub(crate) static ref SESSIONS: RwLock<HashMap<String, Session<FlutterHandler>>> = Default::default();
|
pub(crate) static ref SESSIONS: RwLock<HashMap<SessionID, Session<FlutterHandler>>> = Default::default();
|
||||||
static ref GLOBAL_EVENT_STREAM: RwLock<HashMap<String, StreamSink<String>>> = Default::default(); // rust to dart event channel
|
static ref GLOBAL_EVENT_STREAM: RwLock<HashMap<String, StreamSink<String>>> = Default::default(); // rust to dart event channel
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,6 +696,7 @@ impl InvokeUiSession for FlutterHandler {
|
|||||||
/// * `is_file_transfer` - If the session is used for file transfer.
|
/// * `is_file_transfer` - If the session is used for file transfer.
|
||||||
/// * `is_port_forward` - If the session is used for port forward.
|
/// * `is_port_forward` - If the session is used for port forward.
|
||||||
pub fn session_add(
|
pub fn session_add(
|
||||||
|
session_id: &SessionID,
|
||||||
id: &str,
|
id: &str,
|
||||||
is_file_transfer: bool,
|
is_file_transfer: bool,
|
||||||
is_port_forward: bool,
|
is_port_forward: bool,
|
||||||
@ -703,11 +705,11 @@ pub fn session_add(
|
|||||||
force_relay: bool,
|
force_relay: bool,
|
||||||
password: String,
|
password: String,
|
||||||
) -> ResultType<Session<FlutterHandler>> {
|
) -> ResultType<Session<FlutterHandler>> {
|
||||||
let session_id = get_session_id(id.to_owned());
|
LocalConfig::set_remote_id(&id);
|
||||||
LocalConfig::set_remote_id(&session_id);
|
|
||||||
|
|
||||||
let session: Session<FlutterHandler> = Session {
|
let session: Session<FlutterHandler> = Session {
|
||||||
id: session_id.clone(),
|
session_id: session_id.clone(),
|
||||||
|
id: id.to_owned(),
|
||||||
password,
|
password,
|
||||||
server_keyboard_enabled: Arc::new(RwLock::new(true)),
|
server_keyboard_enabled: Arc::new(RwLock::new(true)),
|
||||||
server_file_transfer_enabled: Arc::new(RwLock::new(true)),
|
server_file_transfer_enabled: Arc::new(RwLock::new(true)),
|
||||||
@ -737,13 +739,14 @@ pub fn session_add(
|
|||||||
.lc
|
.lc
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.initialize(session_id, conn_type, switch_uuid, force_relay);
|
.initialize(id.to_owned(), conn_type, switch_uuid, force_relay);
|
||||||
|
|
||||||
if let Some(same_id_session) = SESSIONS
|
if let Some(same_id_session) = SESSIONS
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(id.to_owned(), session.clone())
|
.insert(session_id.to_owned(), session.clone())
|
||||||
{
|
{
|
||||||
|
log::error!("Should not happen");
|
||||||
same_id_session.close();
|
same_id_session.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,8 +759,12 @@ pub fn session_add(
|
|||||||
///
|
///
|
||||||
/// * `id` - The identifier of the remote session with prefix. Regex: [\w]*[\_]*[\d]+
|
/// * `id` - The identifier of the remote session with prefix. Regex: [\w]*[\_]*[\d]+
|
||||||
/// * `events2ui` - The events channel to ui.
|
/// * `events2ui` - The events channel to ui.
|
||||||
pub fn session_start_(id: &str, event_stream: StreamSink<EventToUI>) -> ResultType<()> {
|
pub fn session_start_(
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(id) {
|
session_id: &SessionID,
|
||||||
|
id: &str,
|
||||||
|
event_stream: StreamSink<EventToUI>,
|
||||||
|
) -> ResultType<()> {
|
||||||
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(session_id) {
|
||||||
#[cfg(feature = "flutter_texture_render")]
|
#[cfg(feature = "flutter_texture_render")]
|
||||||
log::info!(
|
log::info!(
|
||||||
"Session {} start, render by flutter texture rgba plugin",
|
"Session {} start, render by flutter texture rgba plugin",
|
||||||
@ -788,8 +795,14 @@ pub fn update_text_clipboard_required() {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
pub fn other_sessions_running(id: &str) -> bool {
|
pub fn other_sessions_running(session_id: &SessionID) -> bool {
|
||||||
SESSIONS.read().unwrap().keys().filter(|k| *k != id).count() != 0
|
SESSIONS
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.keys()
|
||||||
|
.filter(|k| *k != session_id)
|
||||||
|
.count()
|
||||||
|
!= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
@ -928,15 +941,6 @@ pub mod connection_manager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_session_id(id: String) -> String {
|
|
||||||
return if let Some(index) = id.find('_') {
|
|
||||||
id[index + 1..].to_string()
|
|
||||||
} else {
|
|
||||||
id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_fd_flutter(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> String {
|
pub fn make_fd_flutter(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> String {
|
||||||
let mut m = serde_json::Map::new();
|
let mut m = serde_json::Map::new();
|
||||||
m.insert("id".into(), json!(id));
|
m.insert("id".into(), json!(id));
|
||||||
@ -964,13 +968,13 @@ pub fn make_fd_flutter(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> S
|
|||||||
serde_json::to_string(&m).unwrap_or("".into())
|
serde_json::to_string(&m).unwrap_or("".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cur_session_id() -> String {
|
pub fn get_cur_session_id() -> SessionID {
|
||||||
CUR_SESSION_ID.read().unwrap().clone()
|
CUR_SESSION_ID.read().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_cur_session_id(id: String) {
|
pub fn set_cur_session_id(session_id: SessionID) {
|
||||||
if get_cur_session_id() != id {
|
if get_cur_session_id() != session_id {
|
||||||
*CUR_SESSION_ID.write().unwrap() = id;
|
*CUR_SESSION_ID.write().unwrap() = session_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -995,12 +999,17 @@ fn serialize_resolutions(resolutions: &Vec<Resolution>) -> String {
|
|||||||
serde_json::ser::to_string(&v).unwrap_or("".to_string())
|
serde_json::ser::to_string(&v).unwrap_or("".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn char_to_session_id(c: *const char) -> ResultType<SessionID> {
|
||||||
|
let cstr = unsafe { std::ffi::CStr::from_ptr(c as _) };
|
||||||
|
let str = cstr.to_str()?;
|
||||||
|
SessionID::from_str(str).map_err(|e| anyhow!("{:?}", e))
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[cfg(not(feature = "flutter_texture_render"))]
|
pub fn session_get_rgba_size(_session_uuid_str: *const char) -> usize {
|
||||||
pub fn session_get_rgba_size(id: *const char) -> usize {
|
#[cfg(not(feature = "flutter_texture_render"))]
|
||||||
let id = unsafe { std::ffi::CStr::from_ptr(id as _) };
|
if let Ok(session_id) = char_to_session_id(_session_uuid_str) {
|
||||||
if let Ok(id) = id.to_str() {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(id) {
|
|
||||||
return session.rgba.read().unwrap().len();
|
return session.rgba.read().unwrap().len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1008,27 +1017,20 @@ pub fn session_get_rgba_size(id: *const char) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[cfg(feature = "flutter_texture_render")]
|
pub fn session_get_rgba(session_uuid_str: *const char) -> *const u8 {
|
||||||
pub fn session_get_rgba_size(_id: *const char) -> usize {
|
if let Ok(session_id) = char_to_session_id(session_uuid_str) {
|
||||||
0
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn session_get_rgba(id: *const char) -> *const u8 {
|
|
||||||
let id = unsafe { std::ffi::CStr::from_ptr(id as _) };
|
|
||||||
if let Ok(id) = id.to_str() {
|
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(id) {
|
|
||||||
return session.get_rgba();
|
return session.get_rgba();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ptr::null()
|
std::ptr::null()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn session_next_rgba(id: *const char) {
|
pub fn session_next_rgba(session_uuid_str: *const char) {
|
||||||
let id = unsafe { std::ffi::CStr::from_ptr(id as _) };
|
if let Ok(session_id) = char_to_session_id(session_uuid_str) {
|
||||||
if let Ok(id) = id.to_str() {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(id) {
|
|
||||||
return session.next_rgba();
|
return session.next_rgba();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1036,24 +1038,26 @@ pub fn session_next_rgba(id: *const char) {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[cfg(feature = "flutter_texture_render")]
|
pub fn session_register_texture(_session_uuid_str: *const char, _ptr: usize) {
|
||||||
pub fn session_register_texture(id: *const char, ptr: usize) {
|
#[cfg(feature = "flutter_texture_render")]
|
||||||
let id = unsafe { std::ffi::CStr::from_ptr(id as _) };
|
if let Ok(session_id) = char_to_session_id(_session_uuid_str) {
|
||||||
if let Ok(id) = id.to_str() {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(id) {
|
return session.register_texture(_ptr);
|
||||||
return session.register_texture(ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[no_mangle]
|
pub fn push_session_event(
|
||||||
#[cfg(not(feature = "flutter_texture_render"))]
|
session_id: &SessionID,
|
||||||
pub fn session_register_texture(_id: *const char, _ptr: usize) {}
|
name: &str,
|
||||||
|
event: Vec<(&str, &str)>,
|
||||||
#[inline]
|
) -> Option<bool> {
|
||||||
pub fn push_session_event(peer: &str, name: &str, event: Vec<(&str, &str)>) -> Option<bool> {
|
SESSIONS
|
||||||
SESSIONS.read().unwrap().get(peer)?.push_event(name, event)
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.get(session_id)?
|
||||||
|
.push_event(name, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -28,7 +28,7 @@ use std::{
|
|||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
// use crate::hbbs_http::account::AuthResult;
|
pub type SessionID = uuid::Uuid;
|
||||||
|
|
||||||
fn initialize(app_dir: &str) {
|
fn initialize(app_dir: &str) {
|
||||||
*config::APP_DIR.write().unwrap() = app_dir.to_owned();
|
*config::APP_DIR.write().unwrap() = app_dir.to_owned();
|
||||||
@ -74,6 +74,7 @@ pub fn host_stop_system_key_propagate(_stopped: bool) {
|
|||||||
// FIXME: -> ResultType<()> cannot be parsed by frb_codegen
|
// FIXME: -> ResultType<()> cannot be parsed by frb_codegen
|
||||||
// thread 'main' panicked at 'Failed to parse function output type `ResultType<()>`', $HOME\.cargo\git\checkouts\flutter_rust_bridge-ddba876d3ebb2a1e\e5adce5\frb_codegen\src\parser\mod.rs:151:25
|
// thread 'main' panicked at 'Failed to parse function output type `ResultType<()>`', $HOME\.cargo\git\checkouts\flutter_rust_bridge-ddba876d3ebb2a1e\e5adce5\frb_codegen\src\parser\mod.rs:151:25
|
||||||
pub fn session_add_sync(
|
pub fn session_add_sync(
|
||||||
|
session_id: SessionID,
|
||||||
id: String,
|
id: String,
|
||||||
is_file_transfer: bool,
|
is_file_transfer: bool,
|
||||||
is_port_forward: bool,
|
is_port_forward: bool,
|
||||||
@ -83,6 +84,7 @@ pub fn session_add_sync(
|
|||||||
password: String,
|
password: String,
|
||||||
) -> SyncReturn<String> {
|
) -> SyncReturn<String> {
|
||||||
if let Err(e) = session_add(
|
if let Err(e) = session_add(
|
||||||
|
&session_id,
|
||||||
&id,
|
&id,
|
||||||
is_file_transfer,
|
is_file_transfer,
|
||||||
is_port_forward,
|
is_port_forward,
|
||||||
@ -97,33 +99,37 @@ pub fn session_add_sync(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_start(events2ui: StreamSink<EventToUI>, id: String) -> ResultType<()> {
|
pub fn session_start(
|
||||||
session_start_(&id, events2ui)
|
events2ui: StreamSink<EventToUI>,
|
||||||
|
session_id: SessionID,
|
||||||
|
id: String,
|
||||||
|
) -> ResultType<()> {
|
||||||
|
session_start_(&session_id, &id, events2ui)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_remember(id: String) -> Option<bool> {
|
pub fn session_get_remember(session_id: SessionID) -> Option<bool> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_remember())
|
Some(session.get_remember())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_toggle_option(id: String, arg: String) -> Option<bool> {
|
pub fn session_get_toggle_option(session_id: SessionID, arg: String) -> Option<bool> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_toggle_option(arg))
|
Some(session.get_toggle_option(arg))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_toggle_option_sync(id: String, arg: String) -> SyncReturn<bool> {
|
pub fn session_get_toggle_option_sync(session_id: SessionID, arg: String) -> SyncReturn<bool> {
|
||||||
let res = session_get_toggle_option(id, arg) == Some(true);
|
let res = session_get_toggle_option(session_id, arg) == Some(true);
|
||||||
SyncReturn(res)
|
SyncReturn(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_option(id: String, arg: String) -> Option<String> {
|
pub fn session_get_option(session_id: SessionID, arg: String) -> Option<String> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_option(arg))
|
Some(session.get_option(arg))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -131,63 +137,63 @@ pub fn session_get_option(id: String, arg: String) -> Option<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_login(
|
pub fn session_login(
|
||||||
id: String,
|
session_id: SessionID,
|
||||||
os_username: String,
|
os_username: String,
|
||||||
os_password: String,
|
os_password: String,
|
||||||
password: String,
|
password: String,
|
||||||
remember: bool,
|
remember: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.login(os_username, os_password, password, remember);
|
session.login(os_username, os_password, password, remember);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_close(id: String) {
|
pub fn session_close(session_id: SessionID) {
|
||||||
if let Some(mut session) = SESSIONS.write().unwrap().remove(&id) {
|
if let Some(mut session) = SESSIONS.write().unwrap().remove(&session_id) {
|
||||||
session.close_event_stream();
|
session.close_event_stream();
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_refresh(id: String) {
|
pub fn session_refresh(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.refresh_video();
|
session.refresh_video();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_record_screen(id: String, start: bool, width: usize, height: usize) {
|
pub fn session_record_screen(session_id: SessionID, start: bool, width: usize, height: usize) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.record_screen(start, width as _, height as _);
|
session.record_screen(start, width as _, height as _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_reconnect(id: String, force_relay: bool) {
|
pub fn session_reconnect(session_id: SessionID, force_relay: bool) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.reconnect(force_relay);
|
session.reconnect(force_relay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_toggle_option(id: String, value: String) {
|
pub fn session_toggle_option(session_id: SessionID, value: String) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
log::warn!("toggle option {}", &value);
|
log::warn!("toggle option {}", &value);
|
||||||
session.toggle_option(value.clone());
|
session.toggle_option(value.clone());
|
||||||
}
|
}
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
if SESSIONS.read().unwrap().get(&id).is_some() && value == "disable-clipboard" {
|
if SESSIONS.read().unwrap().get(&session_id).is_some() && value == "disable-clipboard" {
|
||||||
crate::flutter::update_text_clipboard_required();
|
crate::flutter::update_text_clipboard_required();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_flutter_config(id: String, k: String) -> Option<String> {
|
pub fn session_get_flutter_config(session_id: SessionID, k: String) -> Option<String> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_flutter_config(k))
|
Some(session.get_flutter_config(k))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_flutter_config(id: String, k: String, v: String) {
|
pub fn session_set_flutter_config(session_id: SessionID, k: String, v: String) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.save_flutter_config(k, v);
|
session.save_flutter_config(k, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,59 +214,59 @@ pub fn set_local_kb_layout_type(kb_layout_type: String) {
|
|||||||
ui_interface::set_kb_layout_type(kb_layout_type)
|
ui_interface::set_kb_layout_type(kb_layout_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_view_style(id: String) -> Option<String> {
|
pub fn session_get_view_style(session_id: SessionID) -> Option<String> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_view_style())
|
Some(session.get_view_style())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_view_style(id: String, value: String) {
|
pub fn session_set_view_style(session_id: SessionID, value: String) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.save_view_style(value);
|
session.save_view_style(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_scroll_style(id: String) -> Option<String> {
|
pub fn session_get_scroll_style(session_id: SessionID) -> Option<String> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_scroll_style())
|
Some(session.get_scroll_style())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_scroll_style(id: String, value: String) {
|
pub fn session_set_scroll_style(session_id: SessionID, value: String) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.save_scroll_style(value);
|
session.save_scroll_style(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_image_quality(id: String) -> Option<String> {
|
pub fn session_get_image_quality(session_id: SessionID) -> Option<String> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_image_quality())
|
Some(session.get_image_quality())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_image_quality(id: String, value: String) {
|
pub fn session_set_image_quality(session_id: SessionID, value: String) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.save_image_quality(value);
|
session.save_image_quality(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_keyboard_mode(id: String) -> Option<String> {
|
pub fn session_get_keyboard_mode(session_id: SessionID) -> Option<String> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_keyboard_mode())
|
Some(session.get_keyboard_mode())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_keyboard_mode(id: String, value: String) {
|
pub fn session_set_keyboard_mode(session_id: SessionID, value: String) {
|
||||||
let mut _mode_updated = false;
|
let mut _mode_updated = false;
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.save_keyboard_mode(value);
|
session.save_keyboard_mode(value);
|
||||||
_mode_updated = true;
|
_mode_updated = true;
|
||||||
}
|
}
|
||||||
@ -270,16 +276,16 @@ pub fn session_set_keyboard_mode(id: String, value: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_custom_image_quality(id: String) -> Option<Vec<i32>> {
|
pub fn session_get_custom_image_quality(session_id: SessionID) -> Option<Vec<i32>> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
Some(session.get_custom_image_quality())
|
Some(session.get_custom_image_quality())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_is_keyboard_mode_supported(id: String, mode: String) -> SyncReturn<bool> {
|
pub fn session_is_keyboard_mode_supported(session_id: SessionID, mode: String) -> SyncReturn<bool> {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
if let Ok(mode) = KeyboardMode::from_str(&mode[..]) {
|
if let Ok(mode) = KeyboardMode::from_str(&mode[..]) {
|
||||||
SyncReturn(is_keyboard_mode_supported(
|
SyncReturn(is_keyboard_mode_supported(
|
||||||
&mode,
|
&mode,
|
||||||
@ -293,45 +299,45 @@ pub fn session_is_keyboard_mode_supported(id: String, mode: String) -> SyncRetur
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_custom_image_quality(id: String, value: i32) {
|
pub fn session_set_custom_image_quality(session_id: SessionID, value: i32) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.save_custom_image_quality(value);
|
session.save_custom_image_quality(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_custom_fps(id: String, fps: i32) {
|
pub fn session_set_custom_fps(session_id: SessionID, fps: i32) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.set_custom_fps(fps);
|
session.set_custom_fps(fps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_lock_screen(id: String) {
|
pub fn session_lock_screen(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.lock_screen();
|
session.lock_screen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_ctrl_alt_del(id: String) {
|
pub fn session_ctrl_alt_del(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.ctrl_alt_del();
|
session.ctrl_alt_del();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_switch_display(id: String, value: i32) {
|
pub fn session_switch_display(session_id: SessionID, value: i32) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.switch_display(value);
|
session.switch_display(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_handle_flutter_key_event(
|
pub fn session_handle_flutter_key_event(
|
||||||
id: String,
|
session_id: SessionID,
|
||||||
name: String,
|
name: String,
|
||||||
platform_code: i32,
|
platform_code: i32,
|
||||||
position_code: i32,
|
position_code: i32,
|
||||||
lock_modes: i32,
|
lock_modes: i32,
|
||||||
down_or_up: bool,
|
down_or_up: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.handle_flutter_key_event(
|
session.handle_flutter_key_event(
|
||||||
&name,
|
&name,
|
||||||
platform_code,
|
platform_code,
|
||||||
@ -342,9 +348,9 @@ pub fn session_handle_flutter_key_event(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_enter_or_leave(_id: String, _enter: bool) {
|
pub fn session_enter_or_leave(_session_id: SessionID, _enter: bool) {
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&_id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&_session_id) {
|
||||||
if _enter {
|
if _enter {
|
||||||
session.enter();
|
session.enter();
|
||||||
} else {
|
} else {
|
||||||
@ -354,7 +360,7 @@ pub fn session_enter_or_leave(_id: String, _enter: bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_input_key(
|
pub fn session_input_key(
|
||||||
id: String,
|
session_id: SessionID,
|
||||||
name: String,
|
name: String,
|
||||||
down: bool,
|
down: bool,
|
||||||
press: bool,
|
press: bool,
|
||||||
@ -363,54 +369,54 @@ pub fn session_input_key(
|
|||||||
shift: bool,
|
shift: bool,
|
||||||
command: bool,
|
command: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
// #[cfg(any(target_os = "android", target_os = "ios"))]
|
// #[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
session.input_key(&name, down, press, alt, ctrl, shift, command);
|
session.input_key(&name, down, press, alt, ctrl, shift, command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_input_string(id: String, value: String) {
|
pub fn session_input_string(session_id: SessionID, value: String) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
// #[cfg(any(target_os = "android", target_os = "ios"))]
|
// #[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
session.input_string(&value);
|
session.input_string(&value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// chat_client_mode
|
// chat_client_mode
|
||||||
pub fn session_send_chat(id: String, text: String) {
|
pub fn session_send_chat(session_id: SessionID, text: String) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.send_chat(text);
|
session.send_chat(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_peer_option(id: String, name: String, value: String) {
|
pub fn session_peer_option(session_id: SessionID, name: String, value: String) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.set_option(name, value);
|
session.set_option(name, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_peer_option(id: String, name: String) -> String {
|
pub fn session_get_peer_option(session_id: SessionID, name: String) -> String {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
return session.get_option(name);
|
return session.get_option(name);
|
||||||
}
|
}
|
||||||
"".to_string()
|
"".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_input_os_password(id: String, value: String) {
|
pub fn session_input_os_password(session_id: SessionID, value: String) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.input_os_password(value, true);
|
session.input_os_password(value, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// File Action
|
// File Action
|
||||||
pub fn session_read_remote_dir(id: String, path: String, include_hidden: bool) {
|
pub fn session_read_remote_dir(session_id: SessionID, path: String, include_hidden: bool) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.read_remote_dir(path, include_hidden);
|
session.read_remote_dir(path, include_hidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_send_files(
|
pub fn session_send_files(
|
||||||
id: String,
|
session_id: SessionID,
|
||||||
act_id: i32,
|
act_id: i32,
|
||||||
path: String,
|
path: String,
|
||||||
to: String,
|
to: String,
|
||||||
@ -418,76 +424,91 @@ pub fn session_send_files(
|
|||||||
include_hidden: bool,
|
include_hidden: bool,
|
||||||
is_remote: bool,
|
is_remote: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.send_files(act_id, path, to, file_num, include_hidden, is_remote);
|
session.send_files(act_id, path, to, file_num, include_hidden, is_remote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_confirm_override_file(
|
pub fn session_set_confirm_override_file(
|
||||||
id: String,
|
session_id: SessionID,
|
||||||
act_id: i32,
|
act_id: i32,
|
||||||
file_num: i32,
|
file_num: i32,
|
||||||
need_override: bool,
|
need_override: bool,
|
||||||
remember: bool,
|
remember: bool,
|
||||||
is_upload: bool,
|
is_upload: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.set_confirm_override_file(act_id, file_num, need_override, remember, is_upload);
|
session.set_confirm_override_file(act_id, file_num, need_override, remember, is_upload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_remove_file(id: String, act_id: i32, path: String, file_num: i32, is_remote: bool) {
|
pub fn session_remove_file(
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
session_id: SessionID,
|
||||||
|
act_id: i32,
|
||||||
|
path: String,
|
||||||
|
file_num: i32,
|
||||||
|
is_remote: bool,
|
||||||
|
) {
|
||||||
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.remove_file(act_id, path, file_num, is_remote);
|
session.remove_file(act_id, path, file_num, is_remote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_read_dir_recursive(
|
pub fn session_read_dir_recursive(
|
||||||
id: String,
|
session_id: SessionID,
|
||||||
act_id: i32,
|
act_id: i32,
|
||||||
path: String,
|
path: String,
|
||||||
is_remote: bool,
|
is_remote: bool,
|
||||||
show_hidden: bool,
|
show_hidden: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.remove_dir_all(act_id, path, is_remote, show_hidden);
|
session.remove_dir_all(act_id, path, is_remote, show_hidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_remove_all_empty_dirs(id: String, act_id: i32, path: String, is_remote: bool) {
|
pub fn session_remove_all_empty_dirs(
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
session_id: SessionID,
|
||||||
|
act_id: i32,
|
||||||
|
path: String,
|
||||||
|
is_remote: bool,
|
||||||
|
) {
|
||||||
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.remove_dir(act_id, path, is_remote);
|
session.remove_dir(act_id, path, is_remote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_cancel_job(id: String, act_id: i32) {
|
pub fn session_cancel_job(session_id: SessionID, act_id: i32) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.cancel_job(act_id);
|
session.cancel_job(act_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_create_dir(id: String, act_id: i32, path: String, is_remote: bool) {
|
pub fn session_create_dir(session_id: SessionID, act_id: i32, path: String, is_remote: bool) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.create_dir(act_id, path, is_remote);
|
session.create_dir(act_id, path, is_remote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_read_local_dir_sync(_id: String, path: String, show_hidden: bool) -> String {
|
pub fn session_read_local_dir_sync(
|
||||||
|
_session_id: SessionID,
|
||||||
|
path: String,
|
||||||
|
show_hidden: bool,
|
||||||
|
) -> String {
|
||||||
if let Ok(fd) = fs::read_dir(&fs::get_path(&path), show_hidden) {
|
if let Ok(fd) = fs::read_dir(&fs::get_path(&path), show_hidden) {
|
||||||
return make_fd_to_json(fd.id, path, &fd.entries);
|
return make_fd_to_json(fd.id, path, &fd.entries);
|
||||||
}
|
}
|
||||||
"".to_string()
|
"".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_platform(id: String, is_remote: bool) -> String {
|
pub fn session_get_platform(session_id: SessionID, is_remote: bool) -> String {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
return session.get_platform(is_remote);
|
return session.get_platform(is_remote);
|
||||||
}
|
}
|
||||||
"".to_string()
|
"".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_load_last_transfer_jobs(id: String) {
|
pub fn session_load_last_transfer_jobs(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
return session.load_last_jobs();
|
return session.load_last_jobs();
|
||||||
} else {
|
} else {
|
||||||
// a tip for flutter dev
|
// a tip for flutter dev
|
||||||
@ -499,7 +520,7 @@ pub fn session_load_last_transfer_jobs(id: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_add_job(
|
pub fn session_add_job(
|
||||||
id: String,
|
session_id: SessionID,
|
||||||
act_id: i32,
|
act_id: i32,
|
||||||
path: String,
|
path: String,
|
||||||
to: String,
|
to: String,
|
||||||
@ -507,44 +528,44 @@ pub fn session_add_job(
|
|||||||
include_hidden: bool,
|
include_hidden: bool,
|
||||||
is_remote: bool,
|
is_remote: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.add_job(act_id, path, to, file_num, include_hidden, is_remote);
|
session.add_job(act_id, path, to, file_num, include_hidden, is_remote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_resume_job(id: String, act_id: i32, is_remote: bool) {
|
pub fn session_resume_job(session_id: SessionID, act_id: i32, is_remote: bool) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.resume_job(act_id, is_remote);
|
session.resume_job(act_id, is_remote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_elevate_direct(id: String) {
|
pub fn session_elevate_direct(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.elevate_direct();
|
session.elevate_direct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_elevate_with_logon(id: String, username: String, password: String) {
|
pub fn session_elevate_with_logon(session_id: SessionID, username: String, password: String) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.elevate_with_logon(username, password);
|
session.elevate_with_logon(username, password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_switch_sides(id: String) {
|
pub fn session_switch_sides(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.switch_sides();
|
session.switch_sides();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_change_resolution(id: String, display: i32, width: i32, height: i32) {
|
pub fn session_change_resolution(session_id: SessionID, display: i32, width: i32, height: i32) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.change_resolution(display, width, height);
|
session.change_resolution(display, width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_set_size(_id: String, _width: usize, _height: usize) {
|
pub fn session_set_size(_session_id: SessionID, _width: usize, _height: usize) {
|
||||||
#[cfg(feature = "flutter_texture_render")]
|
#[cfg(feature = "flutter_texture_render")]
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&_id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&_session_id) {
|
||||||
session.set_size(_width, _height);
|
session.set_size(_width, _height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -897,36 +918,36 @@ pub fn main_get_current_display() -> SyncReturn<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_add_port_forward(
|
pub fn session_add_port_forward(
|
||||||
id: String,
|
session_id: SessionID,
|
||||||
local_port: i32,
|
local_port: i32,
|
||||||
remote_host: String,
|
remote_host: String,
|
||||||
remote_port: i32,
|
remote_port: i32,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.add_port_forward(local_port, remote_host, remote_port);
|
session.add_port_forward(local_port, remote_host, remote_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_remove_port_forward(id: String, local_port: i32) {
|
pub fn session_remove_port_forward(session_id: SessionID, local_port: i32) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.remove_port_forward(local_port);
|
session.remove_port_forward(local_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_new_rdp(id: String) {
|
pub fn session_new_rdp(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.new_rdp();
|
session.new_rdp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_request_voice_call(id: String) {
|
pub fn session_request_voice_call(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.request_voice_call();
|
session.request_voice_call();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_close_voice_call(id: String) {
|
pub fn session_close_voice_call(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
if let Some(session) = SESSIONS.write().unwrap().get_mut(&session_id) {
|
||||||
session.close_voice_call();
|
session.close_voice_call();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1038,7 +1059,7 @@ pub fn main_start_dbus_server() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_send_mouse(id: String, msg: String) {
|
pub fn session_send_mouse(session_id: SessionID, msg: String) {
|
||||||
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(&msg) {
|
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(&msg) {
|
||||||
let alt = m.get("alt").is_some();
|
let alt = m.get("alt").is_some();
|
||||||
let ctrl = m.get("ctrl").is_some();
|
let ctrl = m.get("ctrl").is_some();
|
||||||
@ -1072,20 +1093,20 @@ pub fn session_send_mouse(id: String, msg: String) {
|
|||||||
_ => 0,
|
_ => 0,
|
||||||
} << 3;
|
} << 3;
|
||||||
}
|
}
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.send_mouse(mask, x, y, alt, ctrl, shift, command);
|
session.send_mouse(mask, x, y, alt, ctrl, shift, command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_restart_remote_device(id: String) {
|
pub fn session_restart_remote_device(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.restart_remote_device();
|
session.restart_remote_device();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_get_audit_server_sync(id: String, typ: String) -> SyncReturn<String> {
|
pub fn session_get_audit_server_sync(session_id: SessionID, typ: String) -> SyncReturn<String> {
|
||||||
let res = if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
let res = if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.get_audit_server(typ)
|
session.get_audit_server(typ)
|
||||||
} else {
|
} else {
|
||||||
"".to_owned()
|
"".to_owned()
|
||||||
@ -1093,14 +1114,14 @@ pub fn session_get_audit_server_sync(id: String, typ: String) -> SyncReturn<Stri
|
|||||||
SyncReturn(res)
|
SyncReturn(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_send_note(id: String, note: String) {
|
pub fn session_send_note(session_id: SessionID, note: String) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.send_note(note)
|
session.send_note(note)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_alternative_codecs(id: String) -> String {
|
pub fn session_alternative_codecs(session_id: SessionID) -> String {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
let (vp8, av1, h264, h265) = session.alternative_codecs();
|
let (vp8, av1, h264, h265) = session.alternative_codecs();
|
||||||
let msg = HashMap::from([("vp8", vp8), ("av1", av1), ("h264", h264), ("h265", h265)]);
|
let msg = HashMap::from([("vp8", vp8), ("av1", av1), ("h264", h264), ("h265", h265)]);
|
||||||
serde_json::ser::to_string(&msg).unwrap_or("".to_owned())
|
serde_json::ser::to_string(&msg).unwrap_or("".to_owned())
|
||||||
@ -1109,8 +1130,8 @@ pub fn session_alternative_codecs(id: String) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_change_prefer_codec(id: String) {
|
pub fn session_change_prefer_codec(session_id: SessionID) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
|
||||||
session.change_prefer_codec();
|
session.change_prefer_codec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1338,8 +1359,8 @@ pub fn main_update_me() -> SyncReturn<bool> {
|
|||||||
SyncReturn(true)
|
SyncReturn(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_cur_session_id(id: String) {
|
pub fn set_cur_session_id(session_id: SessionID) {
|
||||||
super::flutter::set_cur_session_id(id);
|
super::flutter::set_cur_session_id(session_id);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
crate::keyboard::update_grab_get_key_name();
|
crate::keyboard::update_grab_get_key_name();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ use hbb_common::{
|
|||||||
sync::mpsc,
|
sync::mpsc,
|
||||||
time::{Duration as TokioDuration, Instant},
|
time::{Duration as TokioDuration, Instant},
|
||||||
},
|
},
|
||||||
Stream,
|
SessionID, Stream,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::client::io_loop::Remote;
|
use crate::client::io_loop::Remote;
|
||||||
@ -49,7 +49,8 @@ const CHANGE_RESOLUTION_VALID_TIMEOUT_SECS: u64 = 15;
|
|||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Session<T: InvokeUiSession> {
|
pub struct Session<T: InvokeUiSession> {
|
||||||
pub id: String,
|
pub session_id: SessionID,
|
||||||
|
pub id: String, // peer id
|
||||||
pub password: String,
|
pub password: String,
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
pub lc: Arc<RwLock<LoginConfigHandler>>,
|
pub lc: Arc<RwLock<LoginConfigHandler>>,
|
||||||
|
Loading…
Reference in New Issue
Block a user