diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index d4ace7578..4a00b803e 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -261,6 +261,27 @@ class FileModel { debugPrint("Failed to decode onSelectedFiles: $e"); } } + + void sendEmptyDirs(dynamic obj) { + late final List emptyDirs; + try { + emptyDirs = jsonDecode(obj['dirs'] as String); + } catch (e) { + debugPrint("Failed to decode sendEmptyDirs: $e"); + } + final otherSideData = remoteController.directoryData(); + final toPath = otherSideData.directory.path; + final isPeerWindows = otherSideData.options.isWindows; + + final isLocalWindows = isWindows || isWebOnWindows; + for (var dir in emptyDirs) { + if (isLocalWindows != isPeerWindows) { + dir = PathUtil.convert(dir, isLocalWindows, isPeerWindows); + } + var peerPath = PathUtil.join(toPath, dir, isPeerWindows); + remoteController.createDirWithRemote(peerPath, true); + } + } } class DirectoryData { @@ -502,8 +523,9 @@ class FileController { "path: ${from.path}, toPath: $toPath, to: ${PathUtil.join(toPath, from.name, isWindows)}"); } - if (!isLocal && - versionCmp(rootState.target!.ffiModel.pi.version, '1.3.3') < 0) { + if (isWeb || + (!isLocal && + versionCmp(rootState.target!.ffiModel.pi.version, '1.3.3') < 0)) { return; } @@ -1506,6 +1528,12 @@ class PathUtil { return pathUtil.split(path); } + static String convert(String path, bool isMainWindows, bool isOtherWindows) { + final mainPathUtil = isMainWindows ? windowsContext : posixContext; + final otherPathUtil = isOtherWindows ? windowsContext : posixContext; + return otherPathUtil.joinAll(mainPathUtil.split(path)); + } + static String dirname(String path, bool isWindows) { final pathUtil = isWindows ? windowsContext : posixContext; return pathUtil.dirname(path); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index e5cde939f..5a5dcf623 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -402,6 +402,10 @@ class FfiModel with ChangeNotifier { if (isWeb) { parent.target?.fileModel.onSelectedFiles(evt); } + } else if (name == "send_emptry_dirs") { + if (isWeb) { + parent.target?.fileModel.sendEmptyDirs(evt); + } } else if (name == "record_status") { if (desktopType == DesktopType.remote || isMobile) { parent.target?.recordingModel.updateStatus(evt['start'] == 'true'); diff --git a/flutter/lib/web/bridge.dart b/flutter/lib/web/bridge.dart index ffbf66382..498a464ae 100644 --- a/flutter/lib/web/bridge.dart +++ b/flutter/lib/web/bridge.dart @@ -1801,6 +1801,26 @@ class RustdeskImpl { throw UnimplementedError("mainMaxEncryptLen"); } + bool mainAudioSupportLoopback({dynamic hint}) { + return false; + } + + Future sessionReadLocalEmptyDirsRecursiveSync( + {required UuidValue sessionId, + required String path, + required bool includeHidden, + dynamic hint}) { + throw UnimplementedError("sessionReadLocalEmptyDirsRecursiveSync"); + } + + Future sessionReadRemoteEmptyDirsRecursiveSync( + {required UuidValue sessionId, + required String path, + required bool includeHidden, + dynamic hint}) { + throw UnimplementedError("sessionReadRemoteEmptyDirsRecursiveSync"); + } + Future sessionRenameFile( {required UuidValue sessionId, required int actId,