add: use DataTable for desktop file transfer

This commit is contained in:
Kingtous 2022-07-01 17:17:25 +08:00
parent 6b8fc6efe9
commit e7a8bbd291

View File

@ -118,8 +118,7 @@ class _FileManagerPageState extends State<FileManagerPage>
PopupMenuItem( PopupMenuItem(
child: Row( child: Row(
children: [ children: [
Icon(Icons.folder_outlined, Icon(Icons.folder_outlined, color: Colors.black),
color: Colors.black),
SizedBox(width: 5), SizedBox(width: 5),
Text(translate("Create Folder")) Text(translate("Create Folder"))
], ],
@ -150,16 +149,15 @@ class _FileManagerPageState extends State<FileManagerPage>
model.toggleSelectMode(); model.toggleSelectMode();
} else if (v == "folder") { } else if (v == "folder") {
final name = TextEditingController(); final name = TextEditingController();
DialogManager.show((setState, close) => DialogManager.show((setState, close) => CustomAlertDialog(
CustomAlertDialog(
title: Text(translate("Create Folder")), title: Text(translate("Create Folder")),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
TextFormField( TextFormField(
decoration: InputDecoration( decoration: InputDecoration(
labelText: translate( labelText:
"Please enter the folder name"), translate("Please enter the folder name"),
), ),
controller: name, controller: name,
), ),
@ -192,120 +190,195 @@ class _FileManagerPageState extends State<FileManagerPage>
Widget body({bool isLocal = false}) { Widget body({bool isLocal = false}) {
final fd = isLocal ? model.currentLocalDir : model.currentRemoteDir; final fd = isLocal ? model.currentLocalDir : model.currentRemoteDir;
final entries = fd.entries; final entries = fd.entries;
return Column(children: [ return Container(
decoration: BoxDecoration(
color: Colors.white70, border: Border.all(color: Colors.grey)),
margin: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(8.0),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
headTools(isLocal), headTools(isLocal),
Expanded( Expanded(
child: ListView.builder( child: Row(
itemCount: entries.length + 1, crossAxisAlignment: CrossAxisAlignment.start,
itemBuilder: (context, index) { children: [
if (index >= entries.length) { Expanded(
return listTail(isLocal: isLocal); child: SingleChildScrollView(
} child: DataTable(
var selected = false; showCheckboxColumn: true,
if (model.selectMode) { dataRowHeight: 30,
selected = _selectedItems.contains(entries[index]); columnSpacing: 8,
} columns: [
DataColumn(label: Text(translate(" "))), // icon
final sizeStr = entries[index].isFile DataColumn(
? readableFileSize(entries[index].size.toDouble()) label: Text(
translate("Name"),
)),
DataColumn(label: Text(translate("Modified"))),
DataColumn(label: Text(translate("Size"))),
],
rows: entries.map((entry) {
final sizeStr = entry.isFile
? readableFileSize(entry.size.toDouble())
: ""; : "";
return Card( return DataRow(
child: ListTile( key: ValueKey(entry.name),
leading: Icon( onSelectChanged: (s) {
entries[index].isFile ? Icons.feed_outlined : Icons.folder, // TODO
size: 40),
title: Text(entries[index].name),
selected: selected,
subtitle: Text(
entries[index]
.lastModified()
.toString()
.replaceAll(".000", "") +
" " +
sizeStr,
style: TextStyle(fontSize: 12, color: MyTheme.darkGray),
),
trailing: needShowCheckBox()
? Checkbox(
value: selected,
onChanged: (v) {
if (v == null) return;
if (v && !selected) {
_selectedItems.add(isLocal, entries[index]);
} else if (!v && selected) {
_selectedItems.remove(entries[index]);
}
setState(() {});
})
: PopupMenuButton<String>(
icon: Icon(Icons.more_vert),
itemBuilder: (context) {
return [
PopupMenuItem(
child: Text(translate("Delete")),
value: "delete",
),
PopupMenuItem(
child: Text(translate("Multi Select")),
value: "multi_select",
),
PopupMenuItem(
child: Text(translate("Properties")),
value: "properties",
enabled: false,
)
];
}, },
onSelected: (v) { cells: [
if (v == "delete") { // TODO: icon
final items = SelectedItems(); DataCell(Icon(
items.add(isLocal, entries[index]); entry.isFile ? Icons.feed_outlined : Icons.folder,
model.removeAction(items); size: 25)),
} else if (v == "multi_select") { DataCell(
_selectedItems.clear(); ConstrainedBox(
model.toggleSelectMode(); constraints: BoxConstraints(maxWidth: 100),
} child: Text(entry.name,
}), overflow: TextOverflow.ellipsis)),
onTap: () { onTap: () {
if (model.selectMode && !_selectedItems.isOtherPage(isLocal)) { if (entry.isDirectory) {
if (selected) { model.openDirectory(entry.path, isLocal: isLocal);
_selectedItems.remove(entries[index]);
} else {
_selectedItems.add(isLocal, entries[index]);
}
setState(() {});
return;
}
if (entries[index].isDirectory) {
model.openDirectory(entries[index].path, isLocal: isLocal);
breadCrumbScrollToEnd(isLocal);
} else { } else {
// Perform file-related tasks. // Perform file-related tasks.
} }
}, }),
onLongPress: () { DataCell(Text(
_selectedItems.clear(); entry
model.toggleSelectMode(); .lastModified()
if (model.selectMode) { .toString()
_selectedItems.add(isLocal, entries[index]); .replaceAll(".000", "") +
} " ",
setState(() {}); style: TextStyle(
}, fontSize: 12, color: MyTheme.darkGray),
), )),
); DataCell(Text(
}, sizeStr,
)) style: TextStyle(
fontSize: 12, color: MyTheme.darkGray),
)),
]); ]);
}).toList(),
),
),
)
],
)),
Center(child: listTail(isLocal: isLocal)),
// Expanded(
// child: ListView.builder(
// itemCount: entries.length + 1,
// itemBuilder: (context, index) {
// if (index >= entries.length) {
// return listTail(isLocal: isLocal);
// }
// var selected = false;
// if (model.selectMode) {
// selected = _selectedItems.contains(entries[index]);
// }
//
// final sizeStr = entries[index].isFile
// ? readableFileSize(entries[index].size.toDouble())
// : "";
// return Card(
// child: ListTile(
// leading: Icon(
// entries[index].isFile ? Icons.feed_outlined : Icons.folder,
// size: 40),
// title: Text(entries[index].name),
// selected: selected,
// subtitle: Text(
// entries[index]
// .lastModified()
// .toString()
// .replaceAll(".000", "") +
// " " +
// sizeStr,
// style: TextStyle(fontSize: 12, color: MyTheme.darkGray),
// ),
// trailing: needShowCheckBox()
// ? Checkbox(
// value: selected,
// onChanged: (v) {
// if (v == null) return;
// if (v && !selected) {
// _selectedItems.add(isLocal, entries[index]);
// } else if (!v && selected) {
// _selectedItems.remove(entries[index]);
// }
// setState(() {});
// })
// : PopupMenuButton<String>(
// icon: Icon(Icons.more_vert),
// itemBuilder: (context) {
// return [
// PopupMenuItem(
// child: Text(translate("Delete")),
// value: "delete",
// ),
// PopupMenuItem(
// child: Text(translate("Multi Select")),
// value: "multi_select",
// ),
// PopupMenuItem(
// child: Text(translate("Properties")),
// value: "properties",
// enabled: false,
// )
// ];
// },
// onSelected: (v) {
// if (v == "delete") {
// final items = SelectedItems();
// items.add(isLocal, entries[index]);
// model.removeAction(items);
// } else if (v == "multi_select") {
// _selectedItems.clear();
// model.toggleSelectMode();
// }
// }),
// onTap: () {
// if (model.selectMode && !_selectedItems.isOtherPage(isLocal)) {
// if (selected) {
// _selectedItems.remove(entries[index]);
// } else {
// _selectedItems.add(isLocal, entries[index]);
// }
// setState(() {});
// return;
// }
// if (entries[index].isDirectory) {
// model.openDirectory(entries[index].path, isLocal: isLocal);
// breadCrumbScrollToEnd(isLocal);
// } else {
// // Perform file-related tasks.
// }
// },
// onLongPress: () {
// _selectedItems.clear();
// model.toggleSelectMode();
// if (model.selectMode) {
// _selectedItems.add(isLocal, entries[index]);
// }
// setState(() {});
// },
// ),
// );
// },
// ))
]),
);
} }
/// transfer status list /// transfer status list
/// watch transfer status /// watch transfer status
Widget statusList() { Widget statusList() {
return PreferredSize(child: Container( return PreferredSize(
decoration: BoxDecoration( child: Container(
border: Border.all(color: Colors.white70) margin: const EdgeInsets.only(top: 16.0,bottom: 16.0, right: 16.0),
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(color: Colors.white70,border: Border.all(color: Colors.grey)),
), ),
), preferredSize: Size(200, double.infinity)); preferredSize: Size(200, double.infinity));
} }
goBack({bool? isLocal}) { goBack({bool? isLocal}) {
@ -313,10 +386,10 @@ class _FileManagerPageState extends State<FileManagerPage>
} }
breadCrumbScrollToEnd(bool isLocal) { breadCrumbScrollToEnd(bool isLocal) {
final controller = isLocal ? _breadCrumbLocalScroller : _breadCrumbRemoteScroller; final controller =
isLocal ? _breadCrumbLocalScroller : _breadCrumbRemoteScroller;
Future.delayed(Duration(milliseconds: 200), () { Future.delayed(Duration(milliseconds: 200), () {
controller.animateTo( controller.animateTo(controller.position.maxScrollExtent,
controller.position.maxScrollExtent,
duration: Duration(milliseconds: 200), duration: Duration(milliseconds: 200),
curve: Curves.fastLinearToSlowEaseIn); curve: Curves.fastLinearToSlowEaseIn);
}); });
@ -343,7 +416,10 @@ class _FileManagerPageState extends State<FileManagerPage>
model.openDirectory(path, isLocal: isLocal); model.openDirectory(path, isLocal: isLocal);
}, isLocal), }, isLocal),
divider: Icon(Icons.chevron_right), divider: Icon(Icons.chevron_right),
overflow: ScrollableOverflow(controller: isLocal ? _breadCrumbLocalScroller : _breadCrumbRemoteScroller), overflow: ScrollableOverflow(
controller: isLocal
? _breadCrumbLocalScroller
: _breadCrumbRemoteScroller),
)), )),
Row( Row(
children: [ children: [
@ -478,8 +554,8 @@ class _FileManagerPageState extends State<FileManagerPage>
return null; return null;
} }
List<BreadCrumbItem> getPathBreadCrumbItems( List<BreadCrumbItem> getPathBreadCrumbItems(void Function() onHome,
void Function() onHome, void Function(List<String>) onPressed, bool isLocal) { void Function(List<String>) onPressed, bool isLocal) {
final path = model.shortPath(isLocal); final path = model.shortPath(isLocal);
final list = PathUtil.split(path, model.currentIsWindows); final list = PathUtil.split(path, model.currentIsWindows);
final breadCrumbList = [ final breadCrumbList = [