diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 021f03713..88f470717 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -93,6 +93,7 @@ class _FileManagerPageState extends State Wakelock.enable(); } debugPrint("File manager page init success with id ${widget.id}"); + model.onDirChanged = breadCrumbScrollToEnd; // register location listener _locationNodeLocal.addListener(onLocalLocationFocusChanged); _locationNodeRemote.addListener(onRemoteLocationFocusChanged); @@ -100,17 +101,18 @@ class _FileManagerPageState extends State @override void dispose() { - model.onClose(); - _ffi.close(); - _ffi.dialogManager.dismissAll(); - if (!Platform.isLinux) { - Wakelock.disable(); - } - Get.delete(tag: 'ft_${widget.id}'); - _locationNodeLocal.removeListener(onLocalLocationFocusChanged); - _locationNodeRemote.removeListener(onRemoteLocationFocusChanged); - _locationNodeLocal.dispose(); - _locationNodeRemote.dispose(); + model.onClose().whenComplete(() { + _ffi.close(); + _ffi.dialogManager.dismissAll(); + if (!Platform.isLinux) { + Wakelock.disable(); + } + Get.delete(tag: 'ft_${widget.id}'); + _locationNodeLocal.removeListener(onLocalLocationFocusChanged); + _locationNodeRemote.removeListener(onRemoteLocationFocusChanged); + _locationNodeLocal.dispose(); + _locationNodeRemote.dispose(); + }); super.dispose(); } @@ -636,7 +638,6 @@ class _FileManagerPageState extends State }), IconButton( onPressed: () { - breadCrumbScrollToEnd(isLocal); model.refresh(isLocal: isLocal); }, splashRadius: kDesktopIconButtonSplashRadius, @@ -800,7 +801,8 @@ class _FileManagerPageState extends State onPointerSignal: (e) { if (e is PointerScrollEvent) { final sc = getBreadCrumbScrollController(isLocal); - sc.jumpTo(sc.offset + e.scrollDelta.dy / 4); + final scale = Platform.isWindows ? 2 : 4; + sc.jumpTo(sc.offset + e.scrollDelta.dy / scale); } }, child: BreadCrumb( @@ -824,7 +826,7 @@ class _FileManagerPageState extends State final x = offset.dx; final y = offset.dy + size.height + 1; - final isPeerWindows = isWindows(isLocal); + final isPeerWindows = model.getCurrentIsWindows(isLocal); final List menuItems = [ MenuEntryButton( childBuilder: (TextStyle? style) => isPeerWindows @@ -912,7 +914,8 @@ class _FileManagerPageState extends State bool isLocal, void Function(List) onPressed) { final path = model.getCurrentDir(isLocal).path; final breadCrumbList = List.empty(growable: true); - if (isWindows(isLocal) && path == '/') { + final isWindows = model.getCurrentIsWindows(isLocal); + if (isWindows && path == '/') { breadCrumbList.add(BreadCrumbItem( content: TextButton( child: buildWindowsThisPC(), @@ -921,7 +924,7 @@ class _FileManagerPageState extends State onPressed: () => onPressed(['/'])) .marginSymmetric(horizontal: 4))); } else { - final list = PathUtil.split(path, model.getCurrentIsWindows(isLocal)); + final list = PathUtil.split(path, isWindows); breadCrumbList.addAll(list.asMap().entries.map((e) => BreadCrumbItem( content: TextButton( child: Text(e.value), @@ -933,14 +936,6 @@ class _FileManagerPageState extends State return breadCrumbList; } - bool isWindows(bool isLocal) { - if (isLocal) { - return Platform.isWindows; - } else { - return _ffi.ffiModel.pi.platform.toLowerCase() == "windows"; - } - } - breadCrumbScrollToEnd(bool isLocal) { Future.delayed(Duration(milliseconds: 200), () { final breadCrumbScroller = getBreadCrumbScrollController(isLocal); @@ -999,9 +994,7 @@ class _FileManagerPageState extends State } openDirectory(String path, {bool isLocal = false}) { - model.openDirectory(path, isLocal: isLocal).then((_) { - breadCrumbScrollToEnd(isLocal); - }); + model.openDirectory(path, isLocal: isLocal); } void handleDragDone(DropDoneDetails details, bool isLocal) { diff --git a/flutter/lib/mobile/pages/file_manager_page.dart b/flutter/lib/mobile/pages/file_manager_page.dart index 6e5c91484..73df2cb01 100644 --- a/flutter/lib/mobile/pages/file_manager_page.dart +++ b/flutter/lib/mobile/pages/file_manager_page.dart @@ -32,15 +32,17 @@ class _FileManagerPageState extends State { .showLoading(translate('Connecting...'), onCancel: closeConnection); }); gFFI.ffiModel.updateEventListener(widget.id); + model.onDirChanged = (_) => breadCrumbScrollToEnd(); Wakelock.enable(); } @override void dispose() { - model.onClose(); - gFFI.close(); - gFFI.dialogManager.dismissAll(); - Wakelock.disable(); + model.onClose().whenComplete(() { + gFFI.close(); + gFFI.dialogManager.dismissAll(); + Wakelock.disable(); + }); super.dispose(); } @@ -136,7 +138,7 @@ class _FileManagerPageState extends State { child: Row( children: [ Icon( - model.currentShowHidden + model.getCurrentShowHidden() ? Icons.check_box_outlined : Icons.check_box_outline_blank, color: Theme.of(context).iconTheme.color), @@ -183,7 +185,8 @@ class _FileManagerPageState extends State { model.createDir(PathUtil.join( model.currentDir.path, name.value.text, - model.currentIsWindows)); + model + .getCurrentIsWindows())); close(); } }, @@ -309,7 +312,6 @@ class _FileManagerPageState extends State { } if (entries[index].isDirectory || entries[index].isDrive) { model.openDirectory(entries[index].path); - breadCrumbScrollToEnd(); } else { // Perform file-related tasks. } @@ -350,12 +352,12 @@ class _FileManagerPageState extends State { if (model.currentHome.startsWith(list[0])) { // absolute path for (var item in list) { - path = PathUtil.join(path, item, model.currentIsWindows); + path = PathUtil.join(path, item, model.getCurrentIsWindows()); } } else { path += model.currentHome; for (var item in list) { - path = PathUtil.join(path, item, model.currentIsWindows); + path = PathUtil.join(path, item, model.getCurrentIsWindows()); } } model.openDirectory(path); @@ -499,7 +501,7 @@ class _FileManagerPageState extends State { List getPathBreadCrumbItems( void Function() onHome, void Function(List) onPressed) { final path = model.currentShortPath; - final list = PathUtil.split(path, model.currentIsWindows); + final list = PathUtil.split(path, model.getCurrentIsWindows()); final breadCrumbList = [ BreadCrumbItem( content: IconButton( diff --git a/flutter/lib/models/file_model.dart b/flutter/lib/models/file_model.dart index 4beac01be..182f51ef8 100644 --- a/flutter/lib/models/file_model.dart +++ b/flutter/lib/models/file_model.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; @@ -42,6 +43,9 @@ class FileModel extends ChangeNotifier { /// JobTable final _jobTable = List.empty(growable: true).obs; + /// `isLocal` bool + Function(bool)? onDirChanged; + RxList get jobTable => _jobTable; bool get isLocal => _isSelectedLocal; @@ -141,18 +145,14 @@ class FileModel extends ChangeNotifier { } } - bool get currentShowHidden => - _isSelectedLocal ? _localOption.showHidden : _remoteOption.showHidden; - - bool getCurrentShowHidden(bool isLocal) { - return isLocal ? _localOption.showHidden : _remoteOption.showHidden; + bool getCurrentShowHidden([bool? isLocal]) { + final isLocal_ = isLocal ?? _isSelectedLocal; + return isLocal_ ? _localOption.showHidden : _remoteOption.showHidden; } - bool get currentIsWindows => - _isSelectedLocal ? _localOption.isWindows : _remoteOption.isWindows; - - bool getCurrentIsWindows(bool isLocal) { - return isLocal ? _localOption.isWindows : _remoteOption.isWindows; + bool getCurrentIsWindows([bool? isLocal]) { + final isLocal_ = isLocal ?? _isSelectedLocal; + return isLocal_ ? _localOption.isWindows : _remoteOption.isWindows; } final _fileFetcher = FileFetcher(); @@ -327,13 +327,13 @@ class FileModel extends ChangeNotifier { _localOption.showHidden = (await bind.sessionGetPeerOption( id: parent.target?.id ?? "", name: "local_show_hidden")) .isNotEmpty; + _localOption.isWindows = Platform.isWindows; _remoteOption.showHidden = (await bind.sessionGetPeerOption( id: parent.target?.id ?? "", name: "remote_show_hidden")) .isNotEmpty; - _remoteOption.isWindows = parent.target?.ffiModel.pi.platform == "Windows"; - - debugPrint("remote platform: ${parent.target?.ffiModel.pi.platform}"); + _remoteOption.isWindows = + parent.target?.ffiModel.pi.platform.toLowerCase() == "windows"; await Future.delayed(Duration(milliseconds: 100)); @@ -354,10 +354,12 @@ class FileModel extends ChangeNotifier { await bind.sessionLoadLastTransferJobs(id: '${parent.target?.id}'); } - onClose() { + Future onClose() async { parent.target?.dialogManager.dismissAll(); jobReset(); + onDirChanged = null; + // save config Map msgMap = {}; @@ -367,7 +369,7 @@ class FileModel extends ChangeNotifier { msgMap["remote_show_hidden"] = _remoteOption.showHidden ? "Y" : ""; final id = parent.target?.id ?? ""; for (final msg in msgMap.entries) { - bind.sessionPeerOption(id: id, name: msg.key, value: msg.value); + await bind.sessionPeerOption(id: id, name: msg.key, value: msg.value); } _currentLocalDir.clear(); _currentRemoteDir.clear(); @@ -399,14 +401,10 @@ class FileModel extends ChangeNotifier { if (!isBack) { pushHistory(isLocal); } - final showHidden = - isLocal ? _localOption.showHidden : _remoteOption.showHidden; - final isWindows = - isLocal ? _localOption.isWindows : _remoteOption.isWindows; + final showHidden = getCurrentShowHidden(isLocal); + final isWindows = getCurrentIsWindows(isLocal); // process /C:\ -> C:\ on Windows - if (isLocal - ? _localOption.isWindows - : _remoteOption.isWindows && path.length > 1 && path[0] == '/') { + if (isWindows && path.length > 1 && path[0] == '/') { path = path.substring(1); if (path[path.length - 1] != '\\') { path = "$path\\"; @@ -421,6 +419,7 @@ class FileModel extends ChangeNotifier { _currentRemoteDir = fd; } notifyListeners(); + onDirChanged?.call(isLocal); } catch (e) { debugPrint("Failed to openDirectory $path: $e"); }