diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 162e9d720..0deb6741d 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -36,14 +36,13 @@ class _FileManagerPageState extends State @override void initState() { super.initState(); - Get.put(FFI(), tag: 'ft_${widget.id}'); - _ffi.ffiModel.platformFFI = gFFI.ffiModel.platformFFI; - - _ffi.connect(widget.id, isFileTransfer: true); - _ffi.ffiModel.updateEventListener(widget.id); + Get.put(FFI.newFFI()..connect(widget.id, isFileTransfer: true), + tag: 'ft_${widget.id}'); + // _ffi.ffiModel.updateEventListener(widget.id); if (!Platform.isLinux) { Wakelock.enable(); } + print("init success with id ${widget.id}"); } @override diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 0f7ce0df2..aefdcf639 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -519,6 +519,10 @@ class FileModel extends ChangeNotifier { _currentRemoteDir.changeSortStyle(sort); notifyListeners(); } + + initFileFetcher() { + _fileFetcher.id = _ffi.target?.id; + } } class JobResultListener { @@ -566,6 +570,17 @@ class FileFetcher { Map> remoteTasks = Map(); Map> readRecursiveTasks = Map(); + String? _id; + + String? get id => _id; + + set id(String? id) { + _id = id; + } + + // if id == null, means to fetch global FFI + FFI get _ffi => ffi(_id == null ? "" : 'ft_${_id}'); + Future registerReadTask(bool isLocal, String path) { // final jobs = isLocal?localJobs:remoteJobs; // maybe we will use read local dir async later final tasks = remoteTasks; // bypass now @@ -633,13 +648,14 @@ class FileFetcher { Future fetchDirectory( String path, bool isLocal, bool showHidden) async { try { - final msg = {"path": path, "show_hidden": showHidden.toString()}; if (isLocal) { - final res = gFFI.getByName("read_local_dir_sync", jsonEncode(msg)); + final res = await _ffi.bind.sessionReadLocalDirSync( + id: id ?? "", path: path, showHidden: showHidden); final fd = FileDirectory.fromJson(jsonDecode(res)); return fd; } else { - gFFI.setByName("read_remote_dir", jsonEncode(msg)); + await _ffi.bind.sessionReadRemoteDir( + id: id ?? "", path: path, includeHidden: showHidden); return registerReadTask(isLocal, path); } } catch (e) { @@ -657,7 +673,8 @@ class FileFetcher { "show_hidden": showHidden.toString(), "is_remote": (!isLocal).toString() }; - gFFI.setByName("read_dir_recursive", jsonEncode(msg)); + // TODO + _ffi.setByName("read_dir_recursive", jsonEncode(msg)); return registerReadRecursiveTask(id); } catch (e) { return Future.error(e); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 5c383f774..0332dc797 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -784,6 +784,13 @@ class FFI { this.fileModel = FileModel(WeakReference(this)); } + static FFI newFFI() { + final ffi = FFI(); + // keep platformFFI only once + ffi.ffiModel.platformFFI = gFFI.ffiModel.platformFFI; + return ffi; + } + /// Get the remote id for current client. String getId() { return getByName('remote_id'); // TODO @@ -888,32 +895,32 @@ class FFI { setByName('connect_file_transfer', id); } else { chatModel.resetClientMode(); - // setByName('connect', id); - // TODO multi model instances canvasModel.id = id; imageModel._id = id; cursorModel.id = id; - final stream = - bind.sessionConnect(id: id, isFileTransfer: isFileTransfer); - final cb = ffiModel.startEventListener(id); - () async { - await for (final message in stream) { - if (message is Event) { - try { - debugPrint("event:${message.field0}"); - Map event = json.decode(message.field0); - cb(event); - } catch (e) { - print('json.decode fail(): $e'); - } - } else if (message is Rgba) { - imageModel.onRgba(message.field0); - } - } - }(); - // every instance will bind a stream } + final stream = bind.sessionConnect(id: id, isFileTransfer: isFileTransfer); + final cb = ffiModel.startEventListener(id); + () async { + await for (final message in stream) { + if (message is Event) { + try { + debugPrint("event:${message.field0}"); + Map event = json.decode(message.field0); + cb(event); + } catch (e) { + print('json.decode fail(): $e'); + } + } else if (message is Rgba) { + imageModel.onRgba(message.field0); + } + } + }(); + // every instance will bind a stream this.id = id; + if (isFileTransfer) { + this.fileModel.initFileFetcher(); + } } /// Login with [password], choose if the client should [remember] it. diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index 1ae523b8b..c0fd4dfa1 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -93,7 +93,12 @@ class PlatformFFI { _ffiBind = RustdeskImpl(dylib); _startListenEvent(_ffiBind); // global event try { - _homeDir = (await ExternalPath.getExternalStorageDirectories())[0]; + if (isAndroid) { + // only support for android + _homeDir = (await ExternalPath.getExternalStorageDirectories())[0]; + } else { + _homeDir = (await getDownloadsDirectory())?.path ?? ""; + } } catch (e) { print(e); } diff --git a/flutter/macos/Runner/bridge_generated.h b/flutter/macos/Runner/bridge_generated.h index 20f318836..6eb6cbd51 100644 --- a/flutter/macos/Runner/bridge_generated.h +++ b/flutter/macos/Runner/bridge_generated.h @@ -149,6 +149,11 @@ void wire_session_create_dir(int64_t port_, struct wire_uint_8_list *path, bool is_remote); +void wire_session_read_local_dir_sync(int64_t port_, + struct wire_uint_8_list *id, + struct wire_uint_8_list *path, + bool show_hidden); + struct wire_uint_8_list *new_uint_8_list(int32_t len); void free_WireSyncReturnStruct(struct WireSyncReturnStruct val); @@ -194,6 +199,7 @@ static int64_t dummy_method_to_enforce_bundling(void) { dummy_var ^= ((int64_t) (void*) wire_session_remove_all_empty_dirs); dummy_var ^= ((int64_t) (void*) wire_session_cancel_job); dummy_var ^= ((int64_t) (void*) wire_session_create_dir); + dummy_var ^= ((int64_t) (void*) wire_session_read_local_dir_sync); dummy_var ^= ((int64_t) (void*) new_uint_8_list); dummy_var ^= ((int64_t) (void*) free_WireSyncReturnStruct); dummy_var ^= ((int64_t) (void*) store_dart_post_cobject); diff --git a/src/common.rs b/src/common.rs index 03e5f4f4b..b3141a7fe 100644 --- a/src/common.rs +++ b/src/common.rs @@ -24,10 +24,9 @@ lazy_static::lazy_static! { pub static ref SOFTWARE_UPDATE_URL: Arc> = Default::default(); } -#[cfg(any(target_os = "android", target_os = "ios"))] lazy_static::lazy_static! { - pub static ref MOBILE_INFO1: Arc> = Default::default(); - pub static ref MOBILE_INFO2: Arc> = Default::default(); + pub static ref FLUTTER_INFO1: Arc> = Default::default(); + pub static ref FLUTTER_INFO2: Arc> = Default::default(); } #[inline] diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 25c37d418..055e62721 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -307,6 +307,15 @@ pub fn session_create_dir(id: String, act_id: i32, path: String, is_remote: bool } } +pub fn session_read_local_dir_sync(id: String, path: String, show_hidden: bool) -> String { + if let Some(session) = SESSIONS.read().unwrap().get(&id) { + if let Ok(fd) = fs::read_dir(&fs::get_path(&path), show_hidden) { + return make_fd_to_json(fd); + } + } + "".to_string() +} + /// FFI for **get** commands which are idempotent. /// Return result in c string. /// @@ -397,21 +406,21 @@ unsafe extern "C" fn get_by_name(name: *const c_char, arg: *const c_char) -> *co "get_home_dir" => { res = fs::get_home_as_string(); } - "read_local_dir_sync" => { - if let Ok(value) = arg.to_str() { - if let Ok(m) = serde_json::from_str::>(value) { - if let (Some(path), Some(show_hidden)) = - (m.get("path"), m.get("show_hidden")) - { - if let Ok(fd) = - fs::read_dir(&fs::get_path(path), show_hidden.eq("true")) - { - res = make_fd_to_json(fd); - } - } - } - } - } + // "read_local_dir_sync" => { + // if let Ok(value) = arg.to_str() { + // if let Ok(m) = serde_json::from_str::>(value) { + // if let (Some(path), Some(show_hidden)) = + // (m.get("path"), m.get("show_hidden")) + // { + // if let Ok(fd) = + // fs::read_dir(&fs::get_path(path), show_hidden.eq("true")) + // { + // res = make_fd_to_json(fd); + // } + // } + // } + // } + // } // Server Side #[cfg(not(any(target_os = "ios")))] "clients_state" => { @@ -452,13 +461,11 @@ unsafe extern "C" fn set_by_name(name: *const c_char, value: *const c_char) { "init" => { initialize(value); } - #[cfg(any(target_os = "android", target_os = "ios"))] "info1" => { - *crate::common::MOBILE_INFO1.lock().unwrap() = value.to_owned(); + *crate::common::FLUTTER_INFO1.lock().unwrap() = value.to_owned(); } - #[cfg(any(target_os = "android", target_os = "ios"))] "info2" => { - *crate::common::MOBILE_INFO2.lock().unwrap() = value.to_owned(); + *crate::common::FLUTTER_INFO2.lock().unwrap() = value.to_owned(); } // "connect" => { // Session::start(value, false);