diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 35001cbf2..7d91b03b3 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -391,14 +391,30 @@ class FileController { await Future.delayed(Duration(milliseconds: 100)); - final dir = (await bind.sessionGetPeerOption( + final savedDir = (await bind.sessionGetPeerOption( sessionId: sessionId, name: isLocal ? "local_dir" : "remote_dir")); - openDirectory(dir.isEmpty ? options.value.home : dir); + Future tryOpenReadyDirs() async { + final dirs = { + if (directory.value.path.isNotEmpty) directory.value.path, + if (savedDir.isNotEmpty) savedDir, + options.value.home, + }; + for (final dir in dirs) { + if (await _openDirectoryPath(dir, isBack: true)) { + return true; + } + } + return false; + } + + var opened = await tryOpenReadyDirs(); await Future.delayed(Duration(seconds: 1)); - if (directory.value.path.isEmpty) { - openDirectory(options.value.home); + if (!opened) { + // The peer may become ready during the reconnect delay, so retry the + // same candidates instead of only retrying the default home directory. + await tryOpenReadyDirs(); } } @@ -429,19 +445,23 @@ class FileController { }); } - Future refresh() async { - await openDirectory(directory.value.path); + Future refresh() async { + // "." can be both a refresh command and a real remote directory path. + // Refresh must bypass openDirectory's command dispatch to avoid recursion. + return await _openDirectoryPath(directory.value.path, isBack: true); } - Future openDirectory(String path, {bool isBack = false}) async { - if (path == ".") { - refresh(); - return; + Future openDirectory(String path, {bool isBack = false}) async { + if (!isBack && path == ".") { + return await refresh(); } - if (path == "..") { - goToParentDirectory(); - return; + if (!isBack && path == "..") { + return await _goToParentDirectory(isBack: isBack); } + return await _openDirectoryPath(path, isBack: isBack); + } + + Future _openDirectoryPath(String path, {bool isBack = false}) async { if (!isBack) { pushHistory(); } @@ -458,8 +478,10 @@ class FileController { final fd = await fileFetcher.fetchDirectory(path, isLocal, showHidden); fd.format(isWindows, sort: sortBy.value); directory.value = fd; + return true; } catch (e) { debugPrint("Failed to openDirectory $path: $e"); + return false; } } @@ -487,19 +509,22 @@ class FileController { goBack(); return; } - openDirectory(path, isBack: true); + unawaited(_openDirectoryPath(path, isBack: true).then((_) {})); } void goToParentDirectory() { + unawaited(_goToParentDirectory().then((_) {})); + } + + Future _goToParentDirectory({bool isBack = false}) async { final isWindows = options.value.isWindows; final dirPath = directory.value.path; var parent = PathUtil.dirname(dirPath, isWindows); // specially for C:\, D:\, goto '/' if (parent == dirPath && isWindows) { - openDirectory('/'); - return; + return await _openDirectoryPath('/', isBack: isBack); } - openDirectory(parent); + return await _openDirectoryPath(parent, isBack: isBack); } // TODO deprecated this