feat: extension support (#78)

This commit is contained in:
Levi authored and GitHub committed 2023-10-16 09:47:31 +08:00
1 parent 82d316af83
commit c073fc0a67
118 files changed
+6971 -780

No files matched your search

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:gopeed/api/model/meta.dart';
import 'package:path/path.dart' as path;
import 'package:styled_widget/styled_widget.dart';
import '../../api/api.dart';
import '../../api/model/task.dart';
@@ -37,8 +38,11 @@ class BuildTaskListView extends GetView {
Widget buildTaskList(BuildContext context, tasks) {
return ListView.builder(
itemCount: tasks.length,
itemCount: tasks.length + 1,
itemBuilder: (context, index) {
if (index == tasks.length) {
return const SizedBox(height: 75);
}
return item(context, tasks[index]);
},
);
@@ -54,14 +58,12 @@ class BuildTaskListView extends GetView {
}
String buildExplorerUrl(Task task) {
if (task.meta.res.rootDir.trim().isEmpty) {
return path.join(
Util.safeDir(task.meta.opts.path),
Util.safeDir(task.meta.res.files[0].path),
task.meta.res.files[0].name);
if (task.meta.res!.name.isEmpty) {
return path.join(Util.safeDir(task.meta.opts.path),
Util.safeDir(task.meta.res!.files[0].path), fileName(task.meta));
} else {
return path.join(Util.safeDir(task.meta.opts.path),
Util.safeDir(task.meta.res.rootDir));
Util.safeDir(fileName(task.meta)));
}
}
@@ -89,7 +91,7 @@ class BuildTaskListView extends GetView {
),
TextButton(
child: Text(
'delete'.tr,
'confirm'.tr,
style: const TextStyle(color: Colors.redAccent),
),
onPressed: () async {
@@ -156,80 +158,85 @@ class BuildTaskListView extends GetView {
}
double getProgress() {
return task.size <= 0 ? 1 : task.progress.downloaded / task.size;
final totalSize = task.meta.res?.size ?? 0;
return totalSize <= 0 ? 0 : task.progress.downloaded / totalSize;
}
Color pickColor() {
switch (task.status) {
// ready, running, pause, error, done
case Status.running:
return Get.theme.colorScheme.primary;
// case Status.pause:
// return Get.theme.colorScheme.secondary;
case Status.error:
return Get.theme.colorScheme.error;
default:
return Get.theme.colorScheme.primary;
String getProgressText() {
if (isDone()) {
return Util.fmtByte(task.meta.res!.size);
}
if (task.meta.res == null) {
return "";
}
final total = task.meta.res!.size;
return Util.fmtByte(task.progress.downloaded) +
(total > 0 ? " / ${Util.fmtByte(total)}" : "");
}
return InkWell(
// onTap: () {},
child: Column(mainAxisSize: MainAxisSize.min, children: [
Stack(children: [
!isDone()
? Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: Opacity(
opacity: 0.6,
child: LinearProgressIndicator(
backgroundColor: Colors.transparent,
color: pickColor(),
// minHeight: 76,
value: getProgress(),
),
))
: const SizedBox.shrink(),
ListTile(
// isThreeLine: true,
title: Text(fileName(task.meta),
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: Get.textTheme.titleSmall),
subtitle: Text(
"${isDone() ? "" : "${Util.fmtByte(task.progress.downloaded)} / "}${Util.fmtByte(task.size)}",
style: context.textTheme.bodyLarge
?.copyWith(color: Get.theme.disabledColor),
return Card(
elevation: 4.0,
child: InkWell(
onTap: () {},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Text(fileName(task.meta)),
leading: (task.meta.res?.name.isNotEmpty ?? false
? const Icon(FaIcons.folder)
: Icon(FaIcons.allIcons[findIcon(fileName(task.meta))]))),
Row(
children: [
Expanded(
flex: 1,
child: Text(
getProgressText(),
style: Get.textTheme.bodyLarge
?.copyWith(color: Get.theme.disabledColor),
).padding(left: 18)),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("${Util.fmtByte(task.progress.speed)} / s",
style: Get.textTheme.titleSmall),
...buildActions()
],
)),
],
),
LinearProgressIndicator(
value: getProgress(),
),
],
),
leading: (task.meta.res.rootDir.isNotEmpty
? const Icon(FaIcons.folder)
: Icon(FaIcons.allIcons[findIcon(fileName(task.meta))])),
trailing: SizedBox(
width: 180,
child: Row(
// crossAxisAlignment: CrossAxisAlignment.baseline,
// textBaseline: DefaultTextStyle.of(context).style.textBaseline,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("${Util.fmtByte(task.progress.speed)} / s",
style: context.textTheme.titleSmall),
...buildActions()
],
),
),
),
])
]));
)).padding(horizontal: 14, top: 8);
}
String fileName(Meta meta) {
if (meta.res.files.length > 1) {
return meta.res.name;
if (meta.opts.name.isNotEmpty) {
return meta.opts.name;
}
return meta.opts.name.isEmpty ? meta.res.files[0].name : meta.opts.name;
if (meta.res == null) {
final u = Uri.parse(meta.req.url);
if (u.scheme.startsWith("http")) {
return u.path.isNotEmpty
? u.path.substring(u.path.lastIndexOf("/") + 1)
: u.host;
} else {
final params = u.queryParameters;
if (params.containsKey("dn")) {
return params["dn"]!;
} else {
return params["xt"]!.split(":").last;
}
}
}
if (meta.res!.name.isNotEmpty) {
return meta.res!.name;
}
return meta.res!.files[0].name;
}
}
+11 -9
View File
@@ -88,7 +88,7 @@ class FileListView extends GetView {
if (reason == fluent.TreeViewItemInvokeReason.selectionToggle) {
List childrenIds = findChildFileIdsR(fileInfo['children']);
if (item.selected == true) {
parentController.selectedIndexes.addAll(childrenIds);
parentController.selectedIndexes.addAll(childrenIds.cast());
parentController.fileInfos[fileInfo['id']]['size'] = 0;
addDescendantFolderSizeR(item.value);
addAncestorFolderSizeR(item.value, fileInfo['size']);
@@ -178,13 +178,15 @@ class FileListView extends GetView {
overflow: TextOverflow.ellipsis,
// style: context.textTheme.titleSmall,
)),
Text(
Util.fmtByte(
fileInfo['size'],
),
// style: context.textTheme.labelMedium,
overflow: TextOverflow.ellipsis,
),
fileInfo['size'] > 0
? Text(
Util.fmtByte(
fileInfo['size'],
),
// style: context.textTheme.labelMedium,
overflow: TextOverflow.ellipsis,
)
: const SizedBox.shrink(),
]),
));
}
@@ -251,7 +253,7 @@ class FileListView extends GetView {
idNext++;
}
parentController.fileInfos.value = infos;
parentController.selectedIndexes.value = selectedFileIds;
parentController.selectedIndexes.value = selectedFileIds.cast();
parentController.openedFolders.value = openedFolders;
List<fluent.TreeViewItem> treeItems = buildTreeViewItemsR(0, -1);
return treeItems;
@@ -0,0 +1,53 @@
import 'package:flutter/material.dart';
class IconButtonLoading extends StatefulWidget {
final Widget icon;
final VoidCallback? onPressed;
final IconButtonLoadingController controller;
const IconButtonLoading(
{Key? key,
required this.icon,
required this.onPressed,
required this.controller})
: super(key: key);
@override
State<IconButtonLoading> createState() => _IconButtonLoadingState();
}
class _IconButtonLoadingState extends State<IconButtonLoading> {
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<bool>(
valueListenable: widget.controller,
builder: (context, value, child) {
return IconButton(
key: widget.key,
onPressed: value ? null : widget.onPressed,
icon: value
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
: widget.icon,
);
},
);
}
}
class IconButtonLoadingController extends ValueNotifier<bool> {
IconButtonLoadingController() : super(false);
void start() {
value = true;
}
void stop() {
value = false;
}
}
@@ -0,0 +1,53 @@
import 'package:flutter/material.dart';
class TextButtonLoading extends StatefulWidget {
final Widget child;
final VoidCallback? onPressed;
final TextButtonLoadingController controller;
const TextButtonLoading(
{Key? key,
required this.child,
required this.onPressed,
required this.controller})
: super(key: key);
@override
State<TextButtonLoading> createState() => _TextButtonLoadingState();
}
class _TextButtonLoadingState extends State<TextButtonLoading> {
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<bool>(
valueListenable: widget.controller,
builder: (context, value, child) {
return TextButton(
key: widget.key,
onPressed: value ? null : widget.onPressed,
child: value
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
: widget.child,
);
},
);
}
}
class TextButtonLoadingController extends ValueNotifier<bool> {
TextButtonLoadingController() : super(false);
void start() {
value = true;
}
void stop() {
value = false;
}
}