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(
headTools(isLocal), decoration: BoxDecoration(
Expanded( color: Colors.white70, border: Border.all(color: Colors.grey)),
child: ListView.builder( margin: const EdgeInsets.all(16.0),
itemCount: entries.length + 1, padding: const EdgeInsets.all(8.0),
itemBuilder: (context, index) { child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
if (index >= entries.length) { headTools(isLocal),
return listTail(isLocal: isLocal); Expanded(
} child: Row(
var selected = false; crossAxisAlignment: CrossAxisAlignment.start,
if (model.selectMode) { children: [
selected = _selectedItems.contains(entries[index]); Expanded(
} child: SingleChildScrollView(
child: DataTable(
final sizeStr = entries[index].isFile showCheckboxColumn: true,
? readableFileSize(entries[index].size.toDouble()) dataRowHeight: 30,
: ""; columnSpacing: 8,
return Card( columns: [
child: ListTile( DataColumn(label: Text(translate(" "))), // icon
leading: Icon( DataColumn(
entries[index].isFile ? Icons.feed_outlined : Icons.folder, label: Text(
size: 40), translate("Name"),
title: Text(entries[index].name), )),
selected: selected, DataColumn(label: Text(translate("Modified"))),
subtitle: Text( DataColumn(label: Text(translate("Size"))),
entries[index] ],
.lastModified() rows: entries.map((entry) {
.toString() final sizeStr = entry.isFile
.replaceAll(".000", "") + ? readableFileSize(entry.size.toDouble())
" " + : "";
sizeStr, return DataRow(
style: TextStyle(fontSize: 12, color: MyTheme.darkGray), key: ValueKey(entry.name),
onSelectChanged: (s) {
// TODO
},
cells: [
// TODO: icon
DataCell(Icon(
entry.isFile ? Icons.feed_outlined : Icons.folder,
size: 25)),
DataCell(
ConstrainedBox(
constraints: BoxConstraints(maxWidth: 100),
child: Text(entry.name,
overflow: TextOverflow.ellipsis)),
onTap: () {
if (entry.isDirectory) {
model.openDirectory(entry.path, isLocal: isLocal);
} else {
// Perform file-related tasks.
}
}),
DataCell(Text(
entry
.lastModified()
.toString()
.replaceAll(".000", "") +
" ",
style: TextStyle(
fontSize: 12, color: MyTheme.darkGray),
)),
DataCell(Text(
sizeStr,
style: TextStyle(
fontSize: 12, color: MyTheme.darkGray),
)),
]);
}).toList(),
),
), ),
trailing: needShowCheckBox() )
? Checkbox( ],
value: selected, )),
onChanged: (v) { Center(child: listTail(isLocal: isLocal)),
if (v == null) return; // Expanded(
if (v && !selected) { // child: ListView.builder(
_selectedItems.add(isLocal, entries[index]); // itemCount: entries.length + 1,
} else if (!v && selected) { // itemBuilder: (context, index) {
_selectedItems.remove(entries[index]); // if (index >= entries.length) {
} // return listTail(isLocal: isLocal);
setState(() {}); // }
}) // var selected = false;
: PopupMenuButton<String>( // if (model.selectMode) {
icon: Icon(Icons.more_vert), // selected = _selectedItems.contains(entries[index]);
itemBuilder: (context) { // }
return [ //
PopupMenuItem( // final sizeStr = entries[index].isFile
child: Text(translate("Delete")), // ? readableFileSize(entries[index].size.toDouble())
value: "delete", // : "";
), // return Card(
PopupMenuItem( // child: ListTile(
child: Text(translate("Multi Select")), // leading: Icon(
value: "multi_select", // entries[index].isFile ? Icons.feed_outlined : Icons.folder,
), // size: 40),
PopupMenuItem( // title: Text(entries[index].name),
child: Text(translate("Properties")), // selected: selected,
value: "properties", // subtitle: Text(
enabled: false, // entries[index]
) // .lastModified()
]; // .toString()
}, // .replaceAll(".000", "") +
onSelected: (v) { // " " +
if (v == "delete") { // sizeStr,
final items = SelectedItems(); // style: TextStyle(fontSize: 12, color: MyTheme.darkGray),
items.add(isLocal, entries[index]); // ),
model.removeAction(items); // trailing: needShowCheckBox()
} else if (v == "multi_select") { // ? Checkbox(
_selectedItems.clear(); // value: selected,
model.toggleSelectMode(); // onChanged: (v) {
} // if (v == null) return;
}), // if (v && !selected) {
onTap: () { // _selectedItems.add(isLocal, entries[index]);
if (model.selectMode && !_selectedItems.isOtherPage(isLocal)) { // } else if (!v && selected) {
if (selected) { // _selectedItems.remove(entries[index]);
_selectedItems.remove(entries[index]); // }
} else { // setState(() {});
_selectedItems.add(isLocal, entries[index]); // })
} // : PopupMenuButton<String>(
setState(() {}); // icon: Icon(Icons.more_vert),
return; // itemBuilder: (context) {
} // return [
if (entries[index].isDirectory) { // PopupMenuItem(
model.openDirectory(entries[index].path, isLocal: isLocal); // child: Text(translate("Delete")),
breadCrumbScrollToEnd(isLocal); // value: "delete",
} else { // ),
// Perform file-related tasks. // PopupMenuItem(
} // child: Text(translate("Multi Select")),
}, // value: "multi_select",
onLongPress: () { // ),
_selectedItems.clear(); // PopupMenuItem(
model.toggleSelectMode(); // child: Text(translate("Properties")),
if (model.selectMode) { // value: "properties",
_selectedItems.add(isLocal, entries[index]); // enabled: false,
} // )
setState(() {}); // ];
}, // },
), // 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),
), preferredSize: Size(200, double.infinity)); decoration: BoxDecoration(color: Colors.white70,border: Border.all(color: Colors.grey)),
),
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 = [