mobile new file SelectMode state

This commit is contained in:
csf 2023-03-09 22:34:43 +09:00
parent 00b1439f32
commit 69d8498404
2 changed files with 108 additions and 64 deletions

View File

@ -18,10 +18,46 @@ class FileManagerPage extends StatefulWidget {
State<StatefulWidget> createState() => _FileManagerPageState(); State<StatefulWidget> createState() => _FileManagerPageState();
} }
enum SelectMode { local, remote, none }
extension SelectModeEq on SelectMode {
bool eq(bool? currentIsLocal) {
if (currentIsLocal == null) {
return false;
}
if (currentIsLocal) {
return this == SelectMode.local;
} else {
return this == SelectMode.remote;
}
}
}
extension SelectModeExt on Rx<SelectMode> {
void toggle(bool currentIsLocal) {
switch (value) {
case SelectMode.local:
value = SelectMode.none;
break;
case SelectMode.remote:
value = SelectMode.none;
break;
case SelectMode.none:
if (currentIsLocal) {
value = SelectMode.local;
} else {
value = SelectMode.remote;
}
break;
}
}
}
class _FileManagerPageState extends State<FileManagerPage> { class _FileManagerPageState extends State<FileManagerPage> {
final model = gFFI.fileModel; final model = gFFI.fileModel;
final selectMode = SelectMode.none.obs;
var showLocal = true; var showLocal = true;
var isSelecting = false.obs;
FileController get currentFileController => FileController get currentFileController =>
showLocal ? model.localController : model.remoteController; showLocal ? model.localController : model.remoteController;
@ -53,8 +89,9 @@ class _FileManagerPageState extends State<FileManagerPage> {
@override @override
Widget build(BuildContext context) => WillPopScope( Widget build(BuildContext context) => WillPopScope(
onWillPop: () async { onWillPop: () async {
if (isSelecting.value) { if (selectMode.value != SelectMode.none) {
isSelecting.value = false; selectMode.value = SelectMode.none;
setState(() {});
} else { } else {
currentFileController.goBack(); currentFileController.goBack();
} }
@ -154,7 +191,8 @@ class _FileManagerPageState extends State<FileManagerPage> {
} else if (v == "select") { } else if (v == "select") {
model.localController.selectedItems.clear(); model.localController.selectedItems.clear();
model.remoteController.selectedItems.clear(); model.remoteController.selectedItems.clear();
isSelecting.toggle(); selectMode.toggle(showLocal);
setState(() {});
} else if (v == "folder") { } else if (v == "folder") {
final name = TextEditingController(); final name = TextEditingController();
gFFI.dialogManager gFFI.dialogManager
@ -196,43 +234,38 @@ class _FileManagerPageState extends State<FileManagerPage> {
body: showLocal body: showLocal
? FileManagerView( ? FileManagerView(
controller: model.localController, controller: model.localController,
isSelecting: isSelecting, selectMode: selectMode,
showCheckBox: showCheckBox()) )
: FileManagerView( : FileManagerView(
controller: model.remoteController, controller: model.remoteController,
isSelecting: isSelecting, selectMode: selectMode,
showCheckBox: showCheckBox()), ),
bottomSheet: bottomSheet(), bottomSheet: bottomSheet(),
)); ));
bool showCheckBox() {
final selectedItems = getActiveSelectedItems();
if (selectedItems != null) {
return selectedItems.isLocal == showLocal;
}
return false;
}
Widget? bottomSheet() { Widget? bottomSheet() {
return Obx(() { return Obx(() {
final selectedItems = getActiveSelectedItems(); final selectedItems = getActiveSelectedItems();
final jobTable = model.jobController.jobTable;
final localLabel = selectedItems?.isLocal == null final localLabel = selectedItems?.isLocal == null
? "" ? ""
: " [${selectedItems!.isLocal ? translate("Local") : translate("Remote")}]"; : " [${selectedItems!.isLocal ? translate("Local") : translate("Remote")}]";
if (!(selectMode.value == SelectMode.none)) {
if (isSelecting.value) {
final selectedItemsLen = final selectedItemsLen =
"${selectedItems?.items.length ?? 0} ${translate("items")}"; "${selectedItems?.items.length ?? 0} ${translate("items")}";
if (selectedItems == null || if (selectedItems == null ||
selectedItems.items.isEmpty || selectedItems.items.isEmpty ||
showCheckBox()) { selectMode.value.eq(showLocal)) {
return BottomSheetBody( return BottomSheetBody(
leading: Icon(Icons.check), leading: Icon(Icons.check),
title: translate("Selected"), title: translate("Selected"),
text: selectedItemsLen + localLabel, text: selectedItemsLen + localLabel,
onCanceled: () => isSelecting.toggle(), onCanceled: () {
selectedItems?.items.clear();
selectMode.value = SelectMode.none;
setState(() {});
},
actions: [ actions: [
IconButton( IconButton(
icon: Icon(Icons.compare_arrows), icon: Icon(Icons.compare_arrows),
@ -241,9 +274,12 @@ class _FileManagerPageState extends State<FileManagerPage> {
IconButton( IconButton(
icon: Icon(Icons.delete_forever), icon: Icon(Icons.delete_forever),
onPressed: selectedItems != null onPressed: selectedItems != null
? () { ? () async {
if (selectedItems.items.isNotEmpty) { if (selectedItems.items.isNotEmpty) {
currentFileController.removeAction(selectedItems); await currentFileController
.removeAction(selectedItems);
selectedItems.items.clear();
selectMode.value = SelectMode.none;
} }
} }
: null, : null,
@ -254,7 +290,11 @@ class _FileManagerPageState extends State<FileManagerPage> {
leading: Icon(Icons.input), leading: Icon(Icons.input),
title: translate("Paste here?"), title: translate("Paste here?"),
text: selectedItemsLen + localLabel, text: selectedItemsLen + localLabel,
onCanceled: () => isSelecting.toggle(), onCanceled: () {
selectedItems.items.clear();
selectMode.value = SelectMode.none;
setState(() {});
},
actions: [ actions: [
IconButton( IconButton(
icon: Icon(Icons.compare_arrows), icon: Icon(Icons.compare_arrows),
@ -263,50 +303,51 @@ class _FileManagerPageState extends State<FileManagerPage> {
IconButton( IconButton(
icon: Icon(Icons.paste), icon: Icon(Icons.paste),
onPressed: () { onPressed: () {
isSelecting.toggle(); selectMode.value = SelectMode.none;
final otherSide = showLocal final otherSide = showLocal
? model.remoteController ? model.remoteController
: model.localController; : model.localController;
final otherSideData = DirectoryData( final thisSideData =
otherSide.directory.value, otherSide.options.value); DirectoryData(currentDir, currentOptions);
currentFileController.sendFiles( otherSide.sendFiles(selectedItems, thisSideData);
selectedItems, otherSideData); selectedItems.items.clear();
selectMode.value = SelectMode.none;
}, },
) )
]); ]);
} }
} }
final jobTable = model.jobController.jobTable;
if (jobTable.isEmpty) { if (jobTable.isEmpty) {
return Offstage(); return Offstage();
} }
switch (jobTable.last.state) { switch (jobTable.last.state) {
case JobState.inProgress: case JobState.inProgress:
return Obx(() => BottomSheetBody( return BottomSheetBody(
leading: CircularProgressIndicator(), leading: CircularProgressIndicator(),
title: translate("Waiting"), title: translate("Waiting"),
text: text:
"${translate("Speed")}: ${readableFileSize(jobTable.last.speed)}/s", "${translate("Speed")}: ${readableFileSize(jobTable.last.speed)}/s",
onCanceled: () => onCanceled: () {
model.jobController.cancelJob(jobTable.last.id), model.jobController.cancelJob(jobTable.last.id);
)); jobTable.clear();
},
);
case JobState.done: case JobState.done:
return Obx(() => BottomSheetBody( return BottomSheetBody(
leading: Icon(Icons.check), leading: Icon(Icons.check),
title: "${translate("Successful")}!", title: "${translate("Successful")}!",
text: jobTable.last.display(), text: jobTable.last.display(),
onCanceled: () => jobTable.clear(), onCanceled: () => jobTable.clear(),
)); );
case JobState.error: case JobState.error:
return Obx(() => BottomSheetBody( return BottomSheetBody(
leading: Icon(Icons.error), leading: Icon(Icons.error),
title: "${translate("Error")}!", title: "${translate("Error")}!",
text: "", text: "",
onCanceled: () => jobTable.clear(), onCanceled: () => jobTable.clear(),
)); );
case JobState.none: case JobState.none:
break; break;
case JobState.paused: case JobState.paused:
@ -343,13 +384,9 @@ class _FileManagerPageState extends State<FileManagerPage> {
class FileManagerView extends StatefulWidget { class FileManagerView extends StatefulWidget {
final FileController controller; final FileController controller;
final RxBool isSelecting; final Rx<SelectMode> selectMode;
final bool showCheckBox;
FileManagerView( FileManagerView({required this.controller, required this.selectMode});
{required this.controller,
required this.isSelecting,
required this.showCheckBox});
@override @override
State<StatefulWidget> createState() => _FileManagerViewState(); State<StatefulWidget> createState() => _FileManagerViewState();
@ -383,13 +420,18 @@ class _FileManagerViewState extends State<FileManagerView> {
return listTail(); return listTail();
} }
var selected = false; var selected = false;
if (widget.isSelecting.value) { if (widget.selectMode.value != SelectMode.none) {
selected = _selectedItems.items.contains(entries[index]); selected = _selectedItems.items.contains(entries[index]);
} }
final sizeStr = entries[index].isFile final sizeStr = entries[index].isFile
? readableFileSize(entries[index].size.toDouble()) ? readableFileSize(entries[index].size.toDouble())
: ""; : "";
final showCheckBox = () {
return widget.selectMode.value != SelectMode.none &&
widget.selectMode.value.eq(controller.selectedItems.isLocal);
}();
return Card( return Card(
child: ListTile( child: ListTile(
leading: entries[index].isDrive leading: entries[index].isDrive
@ -417,7 +459,7 @@ class _FileManagerViewState extends State<FileManagerView> {
), ),
trailing: entries[index].isDrive trailing: entries[index].isDrive
? null ? null
: widget.isSelecting.value && widget.showCheckBox : showCheckBox
? Checkbox( ? Checkbox(
value: selected, value: selected,
onChanged: (v) { onChanged: (v) {
@ -455,16 +497,18 @@ class _FileManagerViewState extends State<FileManagerView> {
controller.removeAction(items); controller.removeAction(items);
} else if (v == "multi_select") { } else if (v == "multi_select") {
_selectedItems.clear(); _selectedItems.clear();
widget.isSelecting.toggle(); widget.selectMode.toggle(isLocal);
setState(() {});
} }
}), }),
onTap: () { onTap: () {
if (widget.isSelecting.value && widget.showCheckBox) { if (showCheckBox) {
if (selected) { if (selected) {
_selectedItems.remove(entries[index]); _selectedItems.remove(entries[index]);
} else { } else {
_selectedItems.add(entries[index]); _selectedItems.add(entries[index]);
} }
setState(() {});
return; return;
} }
if (entries[index].isDirectory || entries[index].isDrive) { if (entries[index].isDirectory || entries[index].isDrive) {
@ -477,8 +521,8 @@ class _FileManagerViewState extends State<FileManagerView> {
? null ? null
: () { : () {
_selectedItems.clear(); _selectedItems.clear();
widget.isSelecting.toggle(); widget.selectMode.toggle(isLocal);
if (widget.isSelecting.value) { if (widget.selectMode.value != SelectMode.none) {
_selectedItems.add(entries[index]); _selectedItems.add(entries[index]);
} }
setState(() {}); setState(() {});

View File

@ -390,7 +390,7 @@ class FileController {
} }
} }
/// sendFiles from other side (SelectedItems) to current side (FileController.isLocal). /// sendFiles from current side (FileController.isLocal) to other side (SelectedItems).
void sendFiles(SelectedItems items, DirectoryData otherSideData) { void sendFiles(SelectedItems items, DirectoryData otherSideData) {
/// ignore wrong items side status /// ignore wrong items side status
if (items.isLocal != isLocal) { if (items.isLocal != isLocal) {