refactor Desktop file_manager_page.dart
This commit is contained in:
parent
2dd4545be0
commit
d867decd98
@ -69,6 +69,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
late FFI _ffi;
|
late FFI _ffi;
|
||||||
|
|
||||||
FileModel get model => _ffi.fileModel;
|
FileModel get model => _ffi.fileModel;
|
||||||
|
JobController get jobController => model.jobController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -84,7 +85,6 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
Wakelock.enable();
|
Wakelock.enable();
|
||||||
}
|
}
|
||||||
debugPrint("File manager page init success with id ${widget.id}");
|
debugPrint("File manager page init success with id ${widget.id}");
|
||||||
model.onDirChanged = breadCrumbScrollToEnd;
|
|
||||||
_ffi.dialogManager.setOverlayState(_overlayKeyState);
|
_ffi.dialogManager.setOverlayState(_overlayKeyState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,14 +107,8 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
// TODO
|
|
||||||
final localController = FileController(isLocal: true);
|
|
||||||
final remoteController = FileController(isLocal: false);
|
|
||||||
return Overlay(key: _overlayKeyState.key, initialEntries: [
|
return Overlay(key: _overlayKeyState.key, initialEntries: [
|
||||||
OverlayEntry(builder: (_) {
|
OverlayEntry(builder: (_) {
|
||||||
return ChangeNotifierProvider.value(
|
|
||||||
value: _ffi.fileModel,
|
|
||||||
child: Consumer<FileModel>(builder: (context, model, child) {
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
body: Row(
|
body: Row(
|
||||||
@ -122,16 +116,15 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
Flexible(
|
Flexible(
|
||||||
flex: 3,
|
flex: 3,
|
||||||
child: dropArea(FileManagerView(
|
child: dropArea(FileManagerView(
|
||||||
localController, _ffi, _mouseFocusScope))),
|
model.localController, _ffi, _mouseFocusScope))),
|
||||||
Flexible(
|
Flexible(
|
||||||
flex: 3,
|
flex: 3,
|
||||||
child: dropArea(FileManagerView(
|
child: dropArea(FileManagerView(
|
||||||
remoteController, _ffi, _mouseFocusScope))),
|
model.remoteController, _ffi, _mouseFocusScope))),
|
||||||
Flexible(flex: 2, child: statusList())
|
Flexible(flex: 2, child: statusList())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}));
|
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -169,7 +162,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0),
|
margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0),
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: model.jobTable.isEmpty
|
child: jobController.jobTable.isEmpty
|
||||||
? generateCard(
|
? generateCard(
|
||||||
Center(
|
Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -195,7 +188,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
() => ListView.builder(
|
() => ListView.builder(
|
||||||
controller: ScrollController(),
|
controller: ScrollController(),
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
final item = model.jobTable[index];
|
final item = jobController.jobTable[index];
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 5),
|
padding: const EdgeInsets.only(bottom: 5),
|
||||||
child: generateCard(
|
child: generateCard(
|
||||||
@ -206,7 +199,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Transform.rotate(
|
Transform.rotate(
|
||||||
angle: item.isRemote ? pi : 0,
|
angle: item.isRemoteToLocal ? pi : 0,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
"assets/arrow.svg",
|
"assets/arrow.svg",
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
@ -293,7 +286,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
offstage: item.state != JobState.paused,
|
offstage: item.state != JobState.paused,
|
||||||
child: MenuButton(
|
child: MenuButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
model.resumeJob(item.id);
|
jobController.resumeJob(item.id);
|
||||||
},
|
},
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
"assets/refresh.svg",
|
"assets/refresh.svg",
|
||||||
@ -310,8 +303,8 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
model.jobTable.removeAt(index);
|
jobController.jobTable.removeAt(index);
|
||||||
model.cancelJob(item.id);
|
jobController.cancelJob(item.id);
|
||||||
},
|
},
|
||||||
color: MyTheme.accent,
|
color: MyTheme.accent,
|
||||||
hoverColor: MyTheme.accent80,
|
hoverColor: MyTheme.accent80,
|
||||||
@ -325,7 +318,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
itemCount: model.jobTable.length,
|
itemCount: jobController.jobTable.length,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -337,18 +330,15 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
// ignore local
|
// ignore local
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var items = SelectedItems();
|
final items = SelectedItems(isLocal: false);
|
||||||
for (var file in details.files) {
|
for (var file in details.files) {
|
||||||
final f = File(file.path);
|
final f = File(file.path);
|
||||||
items.add(
|
items.add(Entry()
|
||||||
true,
|
|
||||||
Entry()
|
|
||||||
..path = file.path
|
..path = file.path
|
||||||
..name = file.name
|
..name = file.name
|
||||||
..size =
|
..size = FileSystemEntity.isDirectorySync(f.path) ? 0 : f.lengthSync());
|
||||||
FileSystemEntity.isDirectorySync(f.path) ? 0 : f.lengthSync());
|
|
||||||
}
|
}
|
||||||
model.sendFiles(items, isRemote: false);
|
model.remoteController.sendFiles(items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +354,6 @@ class FileManagerView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FileManagerViewState extends State<FileManagerView> {
|
class _FileManagerViewState extends State<FileManagerView> {
|
||||||
final _selectedItems = SelectedItems();
|
|
||||||
final _locationStatus = LocationStatus.bread.obs;
|
final _locationStatus = LocationStatus.bread.obs;
|
||||||
final _locationNode = FocusNode();
|
final _locationNode = FocusNode();
|
||||||
final _locationBarKey = GlobalKey();
|
final _locationBarKey = GlobalKey();
|
||||||
@ -376,6 +365,8 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
final _modifiedColWidth = kDesktopFileTransferModifiedColWidth.obs;
|
final _modifiedColWidth = kDesktopFileTransferModifiedColWidth.obs;
|
||||||
final _fileListScrollController = ScrollController();
|
final _fileListScrollController = ScrollController();
|
||||||
|
|
||||||
|
late final _selectedItems = SelectedItems(isLocal: isLocal);
|
||||||
|
|
||||||
/// [_lastClickTime], [_lastClickEntry] help to handle double click
|
/// [_lastClickTime], [_lastClickEntry] help to handle double click
|
||||||
var _lastClickTime =
|
var _lastClickTime =
|
||||||
DateTime.now().millisecondsSinceEpoch - bind.getDoubleClickTime() - 1000;
|
DateTime.now().millisecondsSinceEpoch - bind.getDoubleClickTime() - 1000;
|
||||||
@ -390,6 +381,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
// register location listener
|
// register location listener
|
||||||
_locationNode.addListener(onLocationFocusChanged);
|
_locationNode.addListener(onLocationFocusChanged);
|
||||||
|
controller.directory.listen((e) => breadCrumbScrollToEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -508,7 +500,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
hoverColor: Theme.of(context).hoverColor,
|
hoverColor: Theme.of(context).hoverColor,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_selectedItems.clear();
|
_selectedItems.clear();
|
||||||
model.goBack(isLocal: isLocal);
|
controller.goBack();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
MenuButton(
|
MenuButton(
|
||||||
@ -523,7 +515,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
hoverColor: Theme.of(context).hoverColor,
|
hoverColor: Theme.of(context).hoverColor,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_selectedItems.clear();
|
_selectedItems.clear();
|
||||||
model.goToParentDirectory(isLocal: isLocal);
|
controller.goToParentDirectory();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -560,8 +552,8 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: _locationStatus.value ==
|
child: _locationStatus.value ==
|
||||||
LocationStatus.bread
|
LocationStatus.bread
|
||||||
? buildBread(isLocal)
|
? buildBread()
|
||||||
: buildPathLocation(isLocal)),
|
: buildPathLocation()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -617,7 +609,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
left: 3,
|
left: 3,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
model.refresh(isLocal: isLocal);
|
controller.refresh();
|
||||||
},
|
},
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
"assets/refresh.svg",
|
"assets/refresh.svg",
|
||||||
@ -641,7 +633,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
right: 3,
|
right: 3,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
model.goHome(isLocal: isLocal);
|
controller.goToHomeDirectory();
|
||||||
},
|
},
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
"assets/home.svg",
|
"assets/home.svg",
|
||||||
@ -656,12 +648,11 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
_ffi.dialogManager.show((setState, close) {
|
_ffi.dialogManager.show((setState, close) {
|
||||||
submit() {
|
submit() {
|
||||||
if (name.value.text.isNotEmpty) {
|
if (name.value.text.isNotEmpty) {
|
||||||
model.createDir(
|
controller.createDir(PathUtil.join(
|
||||||
PathUtil.join(
|
controller.directory.value.path,
|
||||||
model.getCurrentDir(isLocal).path,
|
|
||||||
name.value.text,
|
name.value.text,
|
||||||
model.getCurrentIsWindows(isLocal)),
|
controller.options.value.isWindows,
|
||||||
isLocal: isLocal);
|
));
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -722,8 +713,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
MenuButton(
|
MenuButton(
|
||||||
onPressed: validItems(_selectedItems)
|
onPressed: validItems(_selectedItems)
|
||||||
? () async {
|
? () async {
|
||||||
await (model.removeAction(_selectedItems,
|
await (controller.removeAction(_selectedItems));
|
||||||
isLocal: isLocal));
|
|
||||||
_selectedItems.clear();
|
_selectedItems.clear();
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@ -751,7 +741,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
),
|
),
|
||||||
onPressed: validItems(_selectedItems)
|
onPressed: validItems(_selectedItems)
|
||||||
? () {
|
? () {
|
||||||
model.sendFiles(_selectedItems, isRemote: !isLocal);
|
controller.sendFiles(_selectedItems);
|
||||||
_selectedItems.clear();
|
_selectedItems.clear();
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@ -814,10 +804,10 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
switchType: SwitchType.scheckbox,
|
switchType: SwitchType.scheckbox,
|
||||||
text: translate("Show Hidden Files"),
|
text: translate("Show Hidden Files"),
|
||||||
getter: () async {
|
getter: () async {
|
||||||
return model.getCurrentShowHidden(isLocal);
|
return controller.options.value.isWindows;
|
||||||
},
|
},
|
||||||
setter: (bool v) async {
|
setter: (bool v) async {
|
||||||
model.toggleShowHidden(local: isLocal);
|
controller.toggleShowHidden();
|
||||||
},
|
},
|
||||||
padding: kDesktopMenuPadding,
|
padding: kDesktopMenuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
@ -825,7 +815,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
MenuEntryButton(
|
MenuEntryButton(
|
||||||
childBuilder: (style) => Text(translate("Select All"), style: style),
|
childBuilder: (style) => Text(translate("Select All"), style: style),
|
||||||
proc: () => setState(() =>
|
proc: () => setState(() =>
|
||||||
_selectedItems.selectAll(model.getCurrentDir(isLocal).entries)),
|
_selectedItems.selectAll(controller.directory.value.entries)),
|
||||||
padding: kDesktopMenuPadding,
|
padding: kDesktopMenuPadding,
|
||||||
dismissOnClicked: true),
|
dismissOnClicked: true),
|
||||||
MenuEntryButton(
|
MenuEntryButton(
|
||||||
@ -872,7 +862,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
|
|
||||||
Widget _buildFileList(
|
Widget _buildFileList(
|
||||||
BuildContext context, bool isLocal, ScrollController scrollController) {
|
BuildContext context, bool isLocal, ScrollController scrollController) {
|
||||||
final fd = model.getCurrentDir(isLocal);
|
final fd = controller.directory.value;
|
||||||
final entries = fd.entries;
|
final entries = fd.entries;
|
||||||
|
|
||||||
return ListSearchActionListener(
|
return ListSearchActionListener(
|
||||||
@ -919,11 +909,11 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
_jumpToEntry(isLocal, searchResult.first, scrollController,
|
_jumpToEntry(isLocal, searchResult.first, scrollController,
|
||||||
kDesktopFileTransferRowHeight);
|
kDesktopFileTransferRowHeight);
|
||||||
},
|
},
|
||||||
child: ObxValue<RxString>(
|
child: Obx(() {
|
||||||
(searchText) {
|
final entries = controller.directory.value.entries;
|
||||||
final filteredEntries = searchText.isNotEmpty
|
final filteredEntries = _searchText.isNotEmpty
|
||||||
? entries.where((element) {
|
? entries.where((element) {
|
||||||
return element.name.contains(searchText.value);
|
return element.name.contains(_searchText.value);
|
||||||
}).toList(growable: false)
|
}).toList(growable: false)
|
||||||
: entries;
|
: entries;
|
||||||
final rows = filteredEntries.map((entry) {
|
final rows = filteredEntries.map((entry) {
|
||||||
@ -958,8 +948,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
() => Container(
|
() => Container(
|
||||||
width: _nameColWidth.value,
|
width: _nameColWidth.value,
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
waitDuration:
|
waitDuration: Duration(milliseconds: 500),
|
||||||
Duration(milliseconds: 500),
|
|
||||||
message: entry.name,
|
message: entry.name,
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
entry.isDrive
|
entry.isDrive
|
||||||
@ -980,8 +969,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
.labelColor,
|
.labelColor,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(entry.name.nonBreaking,
|
||||||
entry.name.nonBreaking,
|
|
||||||
overflow:
|
overflow:
|
||||||
TextOverflow.ellipsis))
|
TextOverflow.ellipsis))
|
||||||
]),
|
]),
|
||||||
@ -991,7 +979,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
final items = _selectedItems;
|
final items = _selectedItems;
|
||||||
// handle double click
|
// handle double click
|
||||||
if (_checkDoubleClick(entry)) {
|
if (_checkDoubleClick(entry)) {
|
||||||
openDirectory(entry.path, isLocal: isLocal);
|
controller.openDirectory(entry.path);
|
||||||
items.clear();
|
items.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1007,8 +995,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
() => SizedBox(
|
() => SizedBox(
|
||||||
width: _modifiedColWidth.value,
|
width: _modifiedColWidth.value,
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
waitDuration:
|
waitDuration: Duration(milliseconds: 500),
|
||||||
Duration(milliseconds: 500),
|
|
||||||
message: lastModifiedStr,
|
message: lastModifiedStr,
|
||||||
child: Text(
|
child: Text(
|
||||||
lastModifiedStr,
|
lastModifiedStr,
|
||||||
@ -1035,8 +1022,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
sizeStr,
|
sizeStr,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10, color: MyTheme.darkGray),
|
||||||
color: MyTheme.darkGray),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1071,9 +1057,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
_searchText,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,7 +1068,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
|
|
||||||
void _jumpToEntry(bool isLocal, Entry entry,
|
void _jumpToEntry(bool isLocal, Entry entry,
|
||||||
ScrollController scrollController, double rowHeight) {
|
ScrollController scrollController, double rowHeight) {
|
||||||
final entries = model.getCurrentDir(isLocal).entries;
|
final entries = controller.directory.value.entries;
|
||||||
final index = entries.indexOf(entry);
|
final index = entries.indexOf(entry);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
debugPrint("entry is not valid: ${entry.path}");
|
debugPrint("entry is not valid: ${entry.path}");
|
||||||
@ -1101,7 +1085,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
scrollController.position.maxScrollExtent);
|
scrollController.position.maxScrollExtent);
|
||||||
scrollController.jumpTo(offset);
|
scrollController.jumpTo(offset);
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedEntries.add(isLocal, searchResult.first);
|
selectedEntries.add(searchResult.first);
|
||||||
debugPrint("focused on ${searchResult.first.name}");
|
debugPrint("focused on ${searchResult.first.name}");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1116,7 +1100,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
if (selectedItems.contains(entry)) {
|
if (selectedItems.contains(entry)) {
|
||||||
selectedItems.remove(entry);
|
selectedItems.remove(entry);
|
||||||
} else {
|
} else {
|
||||||
selectedItems.add(isLocal, entry);
|
selectedItems.add(entry);
|
||||||
}
|
}
|
||||||
} else if (isShiftDown) {
|
} else if (isShiftDown) {
|
||||||
final List<int> indexGroup = [];
|
final List<int> indexGroup = [];
|
||||||
@ -1130,10 +1114,10 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
selectedItems.clear();
|
selectedItems.clear();
|
||||||
entries
|
entries
|
||||||
.getRange(minIndex, maxIndex + 1)
|
.getRange(minIndex, maxIndex + 1)
|
||||||
.forEach((e) => selectedItems.add(isLocal, e));
|
.forEach((e) => selectedItems.add(e));
|
||||||
} else {
|
} else {
|
||||||
selectedItems.clear();
|
selectedItems.clear();
|
||||||
selectedItems.add(isLocal, entry);
|
selectedItems.add(entry);
|
||||||
}
|
}
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@ -1205,7 +1189,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
} else {
|
} else {
|
||||||
ascending.value = !ascending.value!;
|
ascending.value = !ascending.value!;
|
||||||
}
|
}
|
||||||
model.changeSortStyle(sortBy,
|
controller.changeSortStyle(sortBy,
|
||||||
isLocal: isLocal, ascending: ascending.value!);
|
isLocal: isLocal, ascending: ascending.value!);
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
@ -1234,21 +1218,21 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
), () {
|
), () {
|
||||||
if (model.getSortStyle(isLocal) == sortBy) {
|
if (controller.sortBy.value == sortBy) {
|
||||||
return model.getSortAscending(isLocal).obs;
|
return controller.sortAscending;
|
||||||
} else {
|
} else {
|
||||||
return Rx<bool?>(null);
|
return Rx<bool?>(null);
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildBread(bool isLocal) {
|
Widget buildBread() {
|
||||||
final items = getPathBreadCrumbItems(isLocal, (list) {
|
final items = getPathBreadCrumbItems(isLocal, (list) {
|
||||||
var path = "";
|
var path = "";
|
||||||
for (var item in list) {
|
for (var item in list) {
|
||||||
path = PathUtil.join(path, item, model.getCurrentIsWindows(isLocal));
|
path = PathUtil.join(path, item, controller.options.value.isWindows);
|
||||||
}
|
}
|
||||||
openDirectory(path, isLocal: isLocal);
|
controller.openDirectory(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
return items.isEmpty
|
return items.isEmpty
|
||||||
@ -1290,7 +1274,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
final x = offset.dx;
|
final x = offset.dx;
|
||||||
final y = offset.dy + size.height + 1;
|
final y = offset.dy + size.height + 1;
|
||||||
|
|
||||||
final isPeerWindows = model.getCurrentIsWindows(isLocal);
|
final isPeerWindows = controller.options.value.isWindows;
|
||||||
final List<MenuEntryBase> menuItems = [
|
final List<MenuEntryBase> menuItems = [
|
||||||
MenuEntryButton(
|
MenuEntryButton(
|
||||||
childBuilder: (TextStyle? style) => isPeerWindows
|
childBuilder: (TextStyle? style) => isPeerWindows
|
||||||
@ -1300,7 +1284,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
style: style,
|
style: style,
|
||||||
),
|
),
|
||||||
proc: () {
|
proc: () {
|
||||||
openDirectory('/', isLocal: isLocal);
|
controller.openDirectory('/');
|
||||||
},
|
},
|
||||||
dismissOnClicked: true),
|
dismissOnClicked: true),
|
||||||
MenuEntryDivider()
|
MenuEntryDivider()
|
||||||
@ -1311,8 +1295,9 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
loadingTag = _ffi.dialogManager.showLoading("Waiting");
|
loadingTag = _ffi.dialogManager.showLoading("Waiting");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final fd =
|
final showHidden = controller.options.value.showHidden;
|
||||||
await model.fetchDirectory("/", isLocal, isLocal);
|
final fd = await controller.fileFetcher
|
||||||
|
.fetchDirectory("/", isLocal, showHidden);
|
||||||
for (var entry in fd.entries) {
|
for (var entry in fd.entries) {
|
||||||
menuItems.add(MenuEntryButton(
|
menuItems.add(MenuEntryButton(
|
||||||
childBuilder: (TextStyle? style) =>
|
childBuilder: (TextStyle? style) =>
|
||||||
@ -1331,8 +1316,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
proc: () {
|
proc: () {
|
||||||
openDirectory('${entry.name}\\',
|
controller.openDirectory('${entry.name}\\');
|
||||||
isLocal: isLocal);
|
|
||||||
},
|
},
|
||||||
dismissOnClicked: true));
|
dismissOnClicked: true));
|
||||||
}
|
}
|
||||||
@ -1369,9 +1353,9 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
|
|
||||||
List<BreadCrumbItem> getPathBreadCrumbItems(
|
List<BreadCrumbItem> getPathBreadCrumbItems(
|
||||||
bool isLocal, void Function(List<String>) onPressed) {
|
bool isLocal, void Function(List<String>) onPressed) {
|
||||||
final path = model.getCurrentDir(isLocal).path;
|
final path = controller.directory.value.path;
|
||||||
final breadCrumbList = List<BreadCrumbItem>.empty(growable: true);
|
final breadCrumbList = List<BreadCrumbItem>.empty(growable: true);
|
||||||
final isWindows = model.getCurrentIsWindows(isLocal);
|
final isWindows = controller.options.value.isWindows;
|
||||||
if (isWindows && path == '/') {
|
if (isWindows && path == '/') {
|
||||||
breadCrumbList.add(BreadCrumbItem(
|
breadCrumbList.add(BreadCrumbItem(
|
||||||
content: TextButton(
|
content: TextButton(
|
||||||
@ -1403,7 +1387,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
return breadCrumbList;
|
return breadCrumbList;
|
||||||
}
|
}
|
||||||
|
|
||||||
breadCrumbScrollToEnd(bool isLocal) {
|
breadCrumbScrollToEnd() {
|
||||||
Future.delayed(Duration(milliseconds: 200), () {
|
Future.delayed(Duration(milliseconds: 200), () {
|
||||||
if (_breadCrumbScroller.hasClients) {
|
if (_breadCrumbScroller.hasClients) {
|
||||||
_breadCrumbScroller.animateTo(
|
_breadCrumbScroller.animateTo(
|
||||||
@ -1414,9 +1398,9 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPathLocation(bool isLocal) {
|
Widget buildPathLocation() {
|
||||||
final text = _locationStatus.value == LocationStatus.pathLocation
|
final text = _locationStatus.value == LocationStatus.pathLocation
|
||||||
? model.getCurrentDir(isLocal).path
|
? controller.directory.value.path
|
||||||
: _searchText.value;
|
: _searchText.value;
|
||||||
final textController = TextEditingController(text: text)
|
final textController = TextEditingController(text: text)
|
||||||
..selection = TextSelection.collapsed(offset: text.length);
|
..selection = TextSelection.collapsed(offset: text.length);
|
||||||
@ -1440,7 +1424,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
),
|
),
|
||||||
controller: textController,
|
controller: textController,
|
||||||
onSubmitted: (path) {
|
onSubmitted: (path) {
|
||||||
openDirectory(path, isLocal: isLocal);
|
controller.openDirectory(path);
|
||||||
},
|
},
|
||||||
onChanged: _locationStatus.value == LocationStatus.fileSearchBar
|
onChanged: _locationStatus.value == LocationStatus.fileSearchBar
|
||||||
? (searchText) => onSearchText(searchText, isLocal)
|
? (searchText) => onSearchText(searchText, isLocal)
|
||||||
|
@ -32,34 +32,37 @@ class JobID {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SortStyle {
|
typedef GetSessionID = String Function();
|
||||||
var by = SortBy.name;
|
|
||||||
var ascending = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class FileModel {
|
class FileModel {
|
||||||
final WeakReference<FFI> parent;
|
final WeakReference<FFI> parent;
|
||||||
late final String sessionID;
|
// late final String sessionID;
|
||||||
|
late final FileFetcher fileFetcher;
|
||||||
|
late final JobController jobController;
|
||||||
|
|
||||||
|
late final FileController localController;
|
||||||
|
late final FileController remoteController;
|
||||||
|
|
||||||
|
late final GetSessionID getSessionID;
|
||||||
|
String get sessionID => getSessionID();
|
||||||
|
|
||||||
FileModel(this.parent) {
|
FileModel(this.parent) {
|
||||||
sessionID = parent.target?.id ?? "";
|
getSessionID = () => parent.target?.id ?? "";
|
||||||
}
|
fileFetcher = FileFetcher(getSessionID);
|
||||||
|
jobController = JobController(getSessionID);
|
||||||
late final fileFetcher = FileFetcher(sessionID);
|
localController = FileController(
|
||||||
late final jobController = JobController(sessionID);
|
|
||||||
|
|
||||||
late final localController = FileController(
|
|
||||||
isLocal: true,
|
isLocal: true,
|
||||||
sessionID: sessionID,
|
getSessionID: getSessionID,
|
||||||
dialogManager: parent.target?.dialogManager,
|
dialogManager: parent.target?.dialogManager,
|
||||||
jobController: jobController,
|
jobController: jobController,
|
||||||
fileFetcher: fileFetcher);
|
fileFetcher: fileFetcher);
|
||||||
|
remoteController = FileController(
|
||||||
late final remoteController = FileController(
|
|
||||||
isLocal: false,
|
isLocal: false,
|
||||||
sessionID: sessionID,
|
getSessionID: getSessionID,
|
||||||
dialogManager: parent.target?.dialogManager,
|
dialogManager: parent.target?.dialogManager,
|
||||||
jobController: jobController,
|
jobController: jobController,
|
||||||
fileFetcher: fileFetcher);
|
fileFetcher: fileFetcher);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> onReady() async {
|
Future<void> onReady() async {
|
||||||
await localController.onReady();
|
await localController.onReady();
|
||||||
@ -188,7 +191,8 @@ class FileModel {
|
|||||||
|
|
||||||
class FileController {
|
class FileController {
|
||||||
final bool isLocal;
|
final bool isLocal;
|
||||||
final String sessionID;
|
final GetSessionID getSessionID;
|
||||||
|
String get sessionID => getSessionID();
|
||||||
|
|
||||||
final FileFetcher fileFetcher;
|
final FileFetcher fileFetcher;
|
||||||
|
|
||||||
@ -196,13 +200,14 @@ class FileController {
|
|||||||
final directory = FileDirectory().obs;
|
final directory = FileDirectory().obs;
|
||||||
|
|
||||||
final history = RxList<String>.empty(growable: true);
|
final history = RxList<String>.empty(growable: true);
|
||||||
final sortStyle = SortStyle().obs;
|
final sortBy = SortBy.name.obs;
|
||||||
|
final sortAscending = true.obs;
|
||||||
final JobController jobController;
|
final JobController jobController;
|
||||||
final OverlayDialogManager? dialogManager;
|
final OverlayDialogManager? dialogManager;
|
||||||
|
|
||||||
FileController(
|
FileController(
|
||||||
{required this.isLocal,
|
{required this.isLocal,
|
||||||
required this.sessionID,
|
required this.getSessionID,
|
||||||
required this.dialogManager,
|
required this.dialogManager,
|
||||||
required this.jobController,
|
required this.jobController,
|
||||||
required this.fileFetcher});
|
required this.fileFetcher});
|
||||||
@ -265,8 +270,8 @@ class FileController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void changeSortStyle(SortBy sort, {bool? isLocal, bool ascending = true}) {
|
void changeSortStyle(SortBy sort, {bool? isLocal, bool ascending = true}) {
|
||||||
sortStyle.value.by = sort;
|
sortBy.value = sort;
|
||||||
sortStyle.value.ascending = ascending;
|
sortAscending.value = ascending;
|
||||||
directory.value.changeSortStyle(sort, ascending: ascending);
|
directory.value.changeSortStyle(sort, ascending: ascending);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +302,7 @@ class FileController {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final fd = await fileFetcher.fetchDirectory(path, isLocal, showHidden);
|
final fd = await fileFetcher.fetchDirectory(path, isLocal, showHidden);
|
||||||
fd.format(isWindows, sort: sortStyle.value.by);
|
fd.format(isWindows, sort: sortBy.value);
|
||||||
directory.value = fd;
|
directory.value = fd;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint("Failed to openDirectory $path: $e");
|
debugPrint("Failed to openDirectory $path: $e");
|
||||||
@ -342,7 +347,7 @@ class FileController {
|
|||||||
void initDirAndHome(Map<String, dynamic> evt) {
|
void initDirAndHome(Map<String, dynamic> evt) {
|
||||||
try {
|
try {
|
||||||
final fd = FileDirectory.fromJson(jsonDecode(evt['value']));
|
final fd = FileDirectory.fromJson(jsonDecode(evt['value']));
|
||||||
fd.format(options.value.isWindows, sort: sortStyle.value.by);
|
fd.format(options.value.isWindows, sort: sortBy.value);
|
||||||
if (fd.id > 0) {
|
if (fd.id > 0) {
|
||||||
final jobIndex = jobController.getJob(fd.id);
|
final jobIndex = jobController.getJob(fd.id);
|
||||||
if (jobIndex != -1) {
|
if (jobIndex != -1) {
|
||||||
@ -575,9 +580,10 @@ class JobController {
|
|||||||
static final JobID jobID = JobID();
|
static final JobID jobID = JobID();
|
||||||
final jobTable = RxList<JobProgress>.empty(growable: true);
|
final jobTable = RxList<JobProgress>.empty(growable: true);
|
||||||
final jobResultListener = JobResultListener<Map<String, dynamic>>();
|
final jobResultListener = JobResultListener<Map<String, dynamic>>();
|
||||||
final String sessionID;
|
final GetSessionID getSessionID;
|
||||||
|
String get sessionID => getSessionID();
|
||||||
|
|
||||||
JobController(this.sessionID);
|
JobController(this.getSessionID);
|
||||||
|
|
||||||
int getJob(int id) {
|
int getJob(int id) {
|
||||||
return jobTable.indexWhere((element) => element.id == id);
|
return jobTable.indexWhere((element) => element.id == id);
|
||||||
@ -764,9 +770,10 @@ class FileFetcher {
|
|||||||
Map<String, Completer<FileDirectory>> remoteTasks = {};
|
Map<String, Completer<FileDirectory>> remoteTasks = {};
|
||||||
Map<int, Completer<FileDirectory>> readRecursiveTasks = {};
|
Map<int, Completer<FileDirectory>> readRecursiveTasks = {};
|
||||||
|
|
||||||
String id;
|
final GetSessionID getSessionID;
|
||||||
|
String get sessionID => getSessionID();
|
||||||
|
|
||||||
FileFetcher(this.id);
|
FileFetcher(this.getSessionID);
|
||||||
|
|
||||||
Future<FileDirectory> registerReadTask(bool isLocal, String path) {
|
Future<FileDirectory> registerReadTask(bool isLocal, String path) {
|
||||||
// final jobs = isLocal?localJobs:remoteJobs; // maybe we will use read local dir async later
|
// final jobs = isLocal?localJobs:remoteJobs; // maybe we will use read local dir async later
|
||||||
@ -829,12 +836,12 @@ class FileFetcher {
|
|||||||
try {
|
try {
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
final res = await bind.sessionReadLocalDirSync(
|
final res = await bind.sessionReadLocalDirSync(
|
||||||
id: id ?? "", path: path, showHidden: showHidden);
|
id: sessionID ?? "", path: path, showHidden: showHidden);
|
||||||
final fd = FileDirectory.fromJson(jsonDecode(res));
|
final fd = FileDirectory.fromJson(jsonDecode(res));
|
||||||
return fd;
|
return fd;
|
||||||
} else {
|
} else {
|
||||||
await bind.sessionReadRemoteDir(
|
await bind.sessionReadRemoteDir(
|
||||||
id: id ?? "", path: path, includeHidden: showHidden);
|
id: sessionID ?? "", path: path, includeHidden: showHidden);
|
||||||
return registerReadTask(isLocal, path);
|
return registerReadTask(isLocal, path);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -847,7 +854,7 @@ class FileFetcher {
|
|||||||
// TODO test Recursive is show hidden default?
|
// TODO test Recursive is show hidden default?
|
||||||
try {
|
try {
|
||||||
await bind.sessionReadDirRecursive(
|
await bind.sessionReadDirRecursive(
|
||||||
id: id,
|
id: sessionID,
|
||||||
actId: actID,
|
actId: actID,
|
||||||
path: path,
|
path: path,
|
||||||
isRemote: !isLocal,
|
isRemote: !isLocal,
|
||||||
@ -1032,7 +1039,7 @@ class SelectedItems {
|
|||||||
|
|
||||||
int get length => _items.length;
|
int get length => _items.length;
|
||||||
|
|
||||||
SelectedItems(this.isLocal);
|
SelectedItems({required this.isLocal});
|
||||||
|
|
||||||
add(Entry e) {
|
add(Entry e) {
|
||||||
if (e.isDrive) return;
|
if (e.isDrive) return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user