refact, tab to window, flutter data, init commit

Signed-off-by: dignow <linlong1265@gmail.com>
This commit is contained in:
dignow 2023-08-14 18:28:31 +08:00
parent 5112398ad3
commit e205577145
4 changed files with 127 additions and 28 deletions

View File

@ -5,6 +5,7 @@ import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/models/state_model.dart';
const double kDesktopRemoteTabBarHeight = 28.0; const double kDesktopRemoteTabBarHeight = 28.0;
const int kInvalidWindowId = -1;
const int kMainWindowId = 0; const int kMainWindowId = 0;
const String kPeerPlatformWindows = "Windows"; const String kPeerPlatformWindows = "Windows";
@ -39,6 +40,7 @@ const String kWindowEventGetSessionIdList = "get_session_id_list";
const String kWindowEventMoveTabToNewWindow = "move_tab_to_new_window"; const String kWindowEventMoveTabToNewWindow = "move_tab_to_new_window";
const String kWindowEventCloseForSeparateWindow = "close_for_separate_window"; const String kWindowEventCloseForSeparateWindow = "close_for_separate_window";
const String kWindowEventSendNewWindowData = "send_new_window_data";
const String kOptionOpenNewConnInTabs = "enable-open-new-connections-in-tabs"; const String kOptionOpenNewConnInTabs = "enable-open-new-connections-in-tabs";
const String kOptionOpenInTabs = "allow-open-in-tabs"; const String kOptionOpenInTabs = "allow-open-in-tabs";

View File

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/common/shared_state.dart'; import 'package:flutter_hbb/common/shared_state.dart';
import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/models/model.dart';
import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/models/state_model.dart';
import 'package:flutter_hbb/desktop/pages/remote_page.dart'; import 'package:flutter_hbb/desktop/pages/remote_page.dart';
import 'package:flutter_hbb/desktop/widgets/remote_toolbar.dart'; import 'package:flutter_hbb/desktop/widgets/remote_toolbar.dart';
@ -148,9 +149,40 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
.toList() .toList()
.join(';'); .join(';');
} else if (call.method == kWindowEventCloseForSeparateWindow) { } else if (call.method == kWindowEventCloseForSeparateWindow) {
final peerId = call.arguments; debugPrint('REMOVE ME ============================= ${call.arguments}');
final peerId = call.arguments['peerId'];
final newWindowId = call.arguments['newWindowId'];
late RemotePage page;
try {
page = tabController.state.value.tabs.firstWhere((tab) {
return tab.key == peerId;
}).page as RemotePage;
} catch (e) {
debugPrint('Failed to find tab for peerId $peerId');
return false;
}
final sendRes = await rustDeskWinManager.call(
newWindowId,
kWindowEventSendNewWindowData,
page.ffi.ffiModel.cachedPeerData) as bool;
if (!sendRes) {
return false;
}
// Pass the required data to new window.
closeSessionOnDispose[peerId] = false; closeSessionOnDispose[peerId] = false;
tabController.closeBy(peerId); tabController.closeBy(peerId);
return true;
} else if (call.method == kWindowEventSendNewWindowData) {
if (peerId == null) {
return false;
}
if (tabController.state.value.tabs.isEmpty) {
return false;
}
final page = tabController.state.value.tabs[0].page as RemotePage;
page.ffi.ffiModel
.handleCachedPeerData(call.arguments as CachedPeerData, peerId!);
return true;
} }
_update_remote_count(); _update_remote_count();
}); });

View File

@ -41,7 +41,19 @@ final _waitForImageDialogShow = <UuidValue, bool>{};
final _waitForFirstImage = <UuidValue, bool>{}; final _waitForFirstImage = <UuidValue, bool>{};
final _constSessionId = Uuid().v4obj(); final _constSessionId = Uuid().v4obj();
class CachedPeerData {
Map<String, dynamic> updatePrivacyMode = {};
Map<String, dynamic> peerInfo = {};
List<Map<String, dynamic>> cursorDataList = [];
Map<String, dynamic> lastCursorId = {};
bool secure = false;
bool direct = false;
CachedPeerData();
}
class FfiModel with ChangeNotifier { class FfiModel with ChangeNotifier {
CachedPeerData cachedPeerData = CachedPeerData();
PeerInfo _pi = PeerInfo(); PeerInfo _pi = PeerInfo();
Display _display = Display(); Display _display = Display();
@ -117,6 +129,8 @@ class FfiModel with ChangeNotifier {
} }
setConnectionType(String peerId, bool secure, bool direct) { setConnectionType(String peerId, bool secure, bool direct) {
cachedPeerData.secure = secure;
cachedPeerData.direct = direct;
_secure = secure; _secure = secure;
_direct = direct; _direct = direct;
try { try {
@ -143,6 +157,22 @@ class FfiModel with ChangeNotifier {
_permissions.clear(); _permissions.clear();
} }
handleCachedPeerData(CachedPeerData data, String peerId) async {
handleMsgBox({
'type': 'success',
'title': 'Successful',
'text': 'Connected, waiting for image...',
'link': '',
}, sessionId, peerId);
updatePrivacyMode(data.updatePrivacyMode, sessionId, peerId);
setConnectionType(peerId, data.secure, data.direct);
handlePeerInfo(data.peerInfo, peerId);
for (var element in data.cursorDataList) {
handleCursorData(element);
}
handleCursorId(data.lastCursorId);
}
// todo: why called by two position // todo: why called by two position
StreamEventHandler startEventListener(SessionID sessionId, String peerId) { StreamEventHandler startEventListener(SessionID sessionId, String peerId) {
return (evt) async { return (evt) async {
@ -159,9 +189,9 @@ class FfiModel with ChangeNotifier {
} else if (name == 'switch_display') { } else if (name == 'switch_display') {
handleSwitchDisplay(evt, sessionId, peerId); handleSwitchDisplay(evt, sessionId, peerId);
} else if (name == 'cursor_data') { } else if (name == 'cursor_data') {
await parent.target?.cursorModel.updateCursorData(evt); await handleCursorData(evt);
} else if (name == 'cursor_id') { } else if (name == 'cursor_id') {
await parent.target?.cursorModel.updateCursorId(evt); await handleCursorId(evt);
} else if (name == 'cursor_position') { } else if (name == 'cursor_position') {
await parent.target?.cursorModel.updateCursorPosition(evt, peerId); await parent.target?.cursorModel.updateCursorPosition(evt, peerId);
} else if (name == 'clipboard') { } else if (name == 'clipboard') {
@ -453,6 +483,8 @@ class FfiModel with ChangeNotifier {
/// Handle the peer info event based on [evt]. /// Handle the peer info event based on [evt].
handlePeerInfo(Map<String, dynamic> evt, String peerId) async { handlePeerInfo(Map<String, dynamic> evt, String peerId) async {
cachedPeerData.peerInfo = evt;
// recent peer updated by handle_peer_info(ui_session_interface.rs) --> handle_peer_info(client.rs) --> save_config(client.rs) // recent peer updated by handle_peer_info(ui_session_interface.rs) --> handle_peer_info(client.rs) --> save_config(client.rs)
bind.mainLoadRecentPeers(); bind.mainLoadRecentPeers();
@ -568,9 +600,20 @@ class FfiModel with ChangeNotifier {
return d; return d;
} }
handleCursorId(Map<String, dynamic> evt) async {
cachedPeerData.lastCursorId = evt;
await parent.target?.cursorModel.updateCursorId(evt);
}
handleCursorData(Map<String, dynamic> evt) async {
cachedPeerData.cursorDataList.add(evt);
await parent.target?.cursorModel.updateCursorData(evt);
}
/// Handle the peer info synchronization event based on [evt]. /// Handle the peer info synchronization event based on [evt].
handleSyncPeerInfo(Map<String, dynamic> evt, SessionID sessionId) async { handleSyncPeerInfo(Map<String, dynamic> evt, SessionID sessionId) async {
if (evt['displays'] != null) { if (evt['displays'] != null) {
cachedPeerData.peerInfo['displays'] = evt['displays'];
List<dynamic> displays = json.decode(evt['displays']); List<dynamic> displays = json.decode(evt['displays']);
List<Display> newDisplays = []; List<Display> newDisplays = [];
for (int i = 0; i < displays.length; ++i) { for (int i = 0; i < displays.length; ++i) {
@ -1667,7 +1710,8 @@ class FFI {
stream.listen((message) { stream.listen((message) {
if (closed) return; if (closed) return;
if (isSessionAdded && !isToNewWindowNotified.value) { if (isSessionAdded && !isToNewWindowNotified.value) {
bind.sessionReadyToNewWindow(sessionId: sessionId); // bind.sessionReadyToNewWindow(sessionId: sessionId);
bind.sessionRefresh(sessionId: sessionId);
isToNewWindowNotified.value = true; isToNewWindowNotified.value = true;
} }
() async { () async {

View File

@ -28,6 +28,13 @@ extension Index on int {
} }
} }
class MultiWindowCallResult {
int windowId;
dynamic result;
MultiWindowCallResult(this.windowId, this.result);
}
/// Window Manager /// Window Manager
/// mainly use it in `Main Window` /// mainly use it in `Main Window`
/// use it in sub window is not recommended /// use it in sub window is not recommended
@ -49,7 +56,10 @@ class RustDeskMultiWindowManager {
'id': peerId, 'id': peerId,
'session_id': sessionId, 'session_id': sessionId,
}; };
await _newSession( // It's better to use the window id that returned by _newSession.
// Do not pass original window id to _newSession,
// as this function cann't promise the necessary data is passed to new window.
final multiWindowRes = await _newSession(
false, false,
WindowType.RemoteDesktop, WindowType.RemoteDesktop,
kWindowEventNewRemoteDesktop, kWindowEventNewRemoteDesktop,
@ -57,17 +67,21 @@ class RustDeskMultiWindowManager {
_remoteDesktopWindows, _remoteDesktopWindows,
jsonEncode(params), jsonEncode(params),
); );
// kWindowEventCloseForSeparateWindow will not only close the tab, but also pass the required data to new window.
await DesktopMultiWindow.invokeMethod( await DesktopMultiWindow.invokeMethod(
windowId, kWindowEventCloseForSeparateWindow, peerId); windowId, kWindowEventCloseForSeparateWindow, {
'peerId': peerId,
'newWindowId': multiWindowRes.windowId,
});
} }
newSessionWindow( Future<int> newSessionWindow(
WindowType type, String remoteId, String msg, List<int> windows) async { WindowType type, String remoteId, String msg, List<int> windows) async {
final windowController = await DesktopMultiWindow.createWindow(msg); final windowController = await DesktopMultiWindow.createWindow(msg);
final windowId = windowController.windowId;
windowController windowController
..setFrame(const Offset(0, 0) & ..setFrame(
Size(1280 + windowController.windowId * 20, const Offset(0, 0) & Size(1280 + windowId * 20, 720 + windowId * 20))
720 + windowController.windowId * 20))
..center() ..center()
..setTitle(getWindowNameWithId( ..setTitle(getWindowNameWithId(
remoteId, remoteId,
@ -76,11 +90,12 @@ class RustDeskMultiWindowManager {
if (Platform.isMacOS) { if (Platform.isMacOS) {
Future.microtask(() => windowController.show()); Future.microtask(() => windowController.show());
} }
registerActiveWindow(windowController.windowId); registerActiveWindow(windowId);
windows.add(windowController.windowId); windows.add(windowId);
return windowId;
} }
_newSession( Future<MultiWindowCallResult> _newSession(
bool openInTabs, bool openInTabs,
WindowType type, WindowType type,
String methodName, String methodName,
@ -90,9 +105,10 @@ class RustDeskMultiWindowManager {
) async { ) async {
if (openInTabs) { if (openInTabs) {
if (windows.isEmpty) { if (windows.isEmpty) {
await newSessionWindow(type, remoteId, msg, windows); final windowId = await newSessionWindow(type, remoteId, msg, windows);
return MultiWindowCallResult(windowId, null);
} else { } else {
call(type, methodName, msg); return call(type, methodName, msg);
} }
} else { } else {
if (_inactiveWindows.isNotEmpty) { if (_inactiveWindows.isNotEmpty) {
@ -103,15 +119,16 @@ class RustDeskMultiWindowManager {
await DesktopMultiWindow.invokeMethod(windowId, methodName, msg); await DesktopMultiWindow.invokeMethod(windowId, methodName, msg);
WindowController.fromWindowId(windowId).show(); WindowController.fromWindowId(windowId).show();
registerActiveWindow(windowId); registerActiveWindow(windowId);
return; return MultiWindowCallResult(windowId, null);
} }
} }
} }
await newSessionWindow(type, remoteId, msg, windows); final windowId = await newSessionWindow(type, remoteId, msg, windows);
return MultiWindowCallResult(windowId, null);
} }
} }
Future<dynamic> newSession( Future<MultiWindowCallResult> newSession(
WindowType type, WindowType type,
String methodName, String methodName,
String remoteId, String remoteId,
@ -143,15 +160,15 @@ class RustDeskMultiWindowManager {
for (final windowId in windows) { for (final windowId in windows) {
if (await DesktopMultiWindow.invokeMethod( if (await DesktopMultiWindow.invokeMethod(
windowId, kWindowEventActiveSession, remoteId)) { windowId, kWindowEventActiveSession, remoteId)) {
return; return MultiWindowCallResult(windowId, null);
} }
} }
} }
await _newSession(openInTabs, type, methodName, remoteId, windows, msg); return _newSession(openInTabs, type, methodName, remoteId, windows, msg);
} }
Future<dynamic> newRemoteDesktop( Future<MultiWindowCallResult> newRemoteDesktop(
String remoteId, { String remoteId, {
String? password, String? password,
String? switchUuid, String? switchUuid,
@ -168,7 +185,7 @@ class RustDeskMultiWindowManager {
); );
} }
Future<dynamic> newFileTransfer(String remoteId, Future<MultiWindowCallResult> newFileTransfer(String remoteId,
{String? password, bool? forceRelay}) async { {String? password, bool? forceRelay}) async {
return await newSession( return await newSession(
WindowType.FileTransfer, WindowType.FileTransfer,
@ -180,7 +197,7 @@ class RustDeskMultiWindowManager {
); );
} }
Future<dynamic> newPortForward(String remoteId, bool isRDP, Future<MultiWindowCallResult> newPortForward(String remoteId, bool isRDP,
{String? password, bool? forceRelay}) async { {String? password, bool? forceRelay}) async {
return await newSession( return await newSession(
WindowType.PortForward, WindowType.PortForward,
@ -193,18 +210,22 @@ class RustDeskMultiWindowManager {
); );
} }
Future<dynamic> call(WindowType type, String methodName, dynamic args) async { Future<MultiWindowCallResult> call(
WindowType type, String methodName, dynamic args) async {
final wnds = _findWindowsByType(type); final wnds = _findWindowsByType(type);
if (wnds.isEmpty) { if (wnds.isEmpty) {
return; return MultiWindowCallResult(kInvalidWindowId, null);
} }
for (final windowId in wnds) { for (final windowId in wnds) {
if (_activeWindows.contains(windowId)) { if (_activeWindows.contains(windowId)) {
return await DesktopMultiWindow.invokeMethod( final res =
windowId, methodName, args); await DesktopMultiWindow.invokeMethod(windowId, methodName, args);
return MultiWindowCallResult(windowId, res);
} }
} }
return await DesktopMultiWindow.invokeMethod(wnds[0], methodName, args); final res =
await DesktopMultiWindow.invokeMethod(wnds[0], methodName, args);
return MultiWindowCallResult(wnds[0], res);
} }
List<int> _findWindowsByType(WindowType type) { List<int> _findWindowsByType(WindowType type) {