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