use uuid as session id

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages
2023-06-06 07:39:44 +08:00
parent 71838ad821
commit 2ececed0c1
36 changed files with 706 additions and 546 deletions

View File

@@ -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);
}
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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'];

View File

@@ -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);
}

View File

@@ -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();