download some codes

This commit is contained in:
DASHU
2025-05-08 14:00:21 +08:00
parent 586e76df5c
commit a55faa3f1e
19 changed files with 702 additions and 19 deletions

View File

@@ -0,0 +1,182 @@
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:nowser/const/base.dart';
import 'package:nowser/data/download_log.dart';
import 'package:nowser/main.dart';
import 'package:nowser/util/file_size_util.dart';
import 'package:path/path.dart' as path;
class DownloadListItemComponent extends StatelessWidget {
DownloadLog downloadLog;
DownloadListItemComponent(this.downloadLog);
@override
Widget build(BuildContext context) {
var themeData = Theme.of(context);
Widget fileIconWidget = const Icon(
AntDesign.file1,
size: 40,
);
if (downloadLog.fileName != null) {
var mimeType = getFileType(downloadLog.fileName!);
if (mimeType.contains("image")) {
fileIconWidget = const Icon(
Icons.image,
size: 40,
);
} else if (mimeType.contains("markdown")) {
fileIconWidget = const Icon(
AntDesign.file_markdown,
size: 40,
);
} else if (mimeType.contains("document")) {
fileIconWidget = const Icon(
AntDesign.filetext1,
size: 40,
);
} else if (mimeType.contains("video")) {
fileIconWidget = const Icon(
Icons.movie,
size: 40,
);
} else if (mimeType.contains("audio")) {
fileIconWidget = const Icon(
Icons.music_note,
size: 40,
);
} else if (mimeType.contains("archive")) {
fileIconWidget = const Icon(
Icons.folder_zip,
size: 40,
);
} else if (mimeType.contains("apk")) {
fileIconWidget = const Icon(
AntDesign.android,
size: 40,
);
}
}
Widget rightIcon = GestureDetector(
onTap: () {},
child: const Icon(
Icons.more_horiz,
),
);
if (downloadLog.progress != null) {
rightIcon = GestureDetector(
onTap: () {},
child: const Icon(
Icons.stop_circle_outlined,
),
);
}
Widget fileStatusWidget = Container();
if (downloadLog.progress != null) {
fileStatusWidget = Text(
"${(downloadLog.progress! * 100).toStringAsFixed(1)}%",
style: TextStyle(
fontSize: themeData.textTheme.bodySmall!.fontSize,
color: themeData.hintColor,
),
);
} else if (downloadLog.fileSize != null) {
fileStatusWidget = Text(
FileSizeUtil.getFileSize(downloadLog.fileSize!),
style: TextStyle(
fontSize: themeData.textTheme.bodySmall!.fontSize,
color: themeData.hintColor,
),
);
}
return Container(
padding: const EdgeInsets.only(
left: Base.BASE_PADDING_HALF,
right: Base.BASE_PADDING_HALF,
top: 2,
bottom: 2,
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(6),
child: fileIconWidget,
),
Expanded(
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
downloadLog.fileName ?? "unknow_file",
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
fileStatusWidget,
],
),
),
),
Container(
padding: const EdgeInsets.all(6),
child: rightIcon,
),
],
),
);
}
String getFileType(String filePath) {
// 获取扩展名(含点,如 '.jpg'
String extension = path.extension(filePath).toLowerCase();
// 处理无扩展名的情况
if (extension.isEmpty) return 'other';
// 去掉点并检查映射
String cleanedExtension =
extension.startsWith('.') ? extension.substring(1) : extension;
return _fileExtensionToType[cleanedExtension] ?? 'other';
}
Map<String, String> _fileExtensionToType = {
// 图片类型
'jpg': 'image',
'jpeg': 'image',
'png': 'image',
'gif': 'image',
'webp': 'image',
'bmp': 'image',
'mp4': 'video',
'mov': 'video',
'avi': 'video',
'mkv': 'video',
'flv': 'video',
'pdf': 'document',
'doc': 'document',
'docx': 'document',
'xls': 'document',
'xlsx': 'document',
'ppt': 'document',
'pptx': 'document',
'txt': 'document',
'md': 'markdown',
'markdown': 'markdown',
'mp3': 'audio',
'wav': 'audio',
'aac': 'audio',
'ogg': 'audio',
'zip': 'archive',
'rar': 'archive',
'7z': 'archive',
'tar': 'archive',
'gz': 'archive',
'apk': 'apk',
};
}

View File

@@ -0,0 +1,121 @@
import 'package:flutter/material.dart';
import 'package:nostr_sdk/utils/platform_util.dart';
import 'package:nowser/provider/download_provider.dart';
import 'package:nowser/util/router_util.dart';
import '../const/base.dart';
import '../generated/l10n.dart';
import '../main.dart';
import '../util/table_mode_util.dart';
class DownloadTaskDialog extends StatefulWidget {
String downloadUrl;
DownloadTaskDialog(this.downloadUrl);
static Future<void> show(BuildContext context, String downloadUrl) async {
await showDialog<String>(
context: context,
builder: (_context) {
return DownloadTaskDialog(downloadUrl);
},
);
}
@override
State<StatefulWidget> createState() {
return _DownloadTaskDialog();
}
}
class _DownloadTaskDialog extends State<DownloadTaskDialog> {
TextEditingController urlTextController = TextEditingController();
TextEditingController fileNameTextController = TextEditingController();
late S s;
@override
void initState() {
super.initState();
String fileName =
widget.downloadUrl.substring(widget.downloadUrl.lastIndexOf('/') + 1);
urlTextController.text = widget.downloadUrl;
fileNameTextController.text = fileName;
}
@override
Widget build(BuildContext context) {
var themeData = Theme.of(context);
s = S.of(context);
List<Widget> list = [];
list.add(Container(
margin: EdgeInsets.only(
bottom: Base.BASE_PADDING,
),
child: Text(
s.Downloads,
style: TextStyle(
fontSize: themeData.textTheme.bodyLarge!.fontSize,
fontWeight: FontWeight.bold,
),
),
));
list.add(Container(
child: TextField(
controller: urlTextController,
decoration: InputDecoration(
labelText: s.Url,
),
),
));
list.add(Container(
child: TextField(
controller: fileNameTextController,
decoration: InputDecoration(
labelText: s.Name,
),
),
));
list.add(Container(
margin: EdgeInsets.only(
top: Base.BASE_PADDING * 2,
bottom: Base.BASE_PADDING,
),
width: double.infinity,
child: FilledButton(onPressed: confirm, child: Text(s.Confirm)),
));
Widget main = Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: list,
),
);
if (PlatformUtil.isPC() || TableModeUtil.isTableMode()) {
main = Container(
width: mediaDataCache.size.width / 2,
child: main,
);
}
return Dialog(
child: Container(
padding: EdgeInsets.all(Base.BASE_PADDING * 2),
child: main,
),
);
}
void confirm() {
var url = urlTextController.text;
var fileName = fileNameTextController.text;
downloadProvider.startDownload(url, fileName);
RouterUtil.back(context);
}
}

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:nostr_sdk/utils/string_util.dart';
import 'package:nowser/component/download_task_dialog.dart';
import 'package:nowser/main.dart';
import '../../const/base.dart';
@@ -98,7 +99,9 @@ class _LongPressDialog extends State<LongPressDialog> {
));
list.add(LongPressDialogItem(
s.Download_image,
onTap: () {},
onTap: () {
DownloadTaskDialog.show(context, src);
},
showBottomLine: false,
));
}
@@ -180,10 +183,10 @@ class LongPressDialogItem extends StatelessWidget {
return GestureDetector(
onTap: () {
RouterUtil.back(context);
if (onTap != null) {
onTap!();
}
RouterUtil.back(context);
},
child: Container(
decoration: BoxDecoration(

View File

@@ -7,6 +7,7 @@ import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:nostr_sdk/event.dart';
import 'package:nostr_sdk/utils/platform_util.dart';
import 'package:nostr_sdk/utils/string_util.dart';
import 'package:nowser/component/download_task_dialog.dart';
import 'package:nowser/component/webview/long_press_dialog.dart';
import 'package:nowser/component/webview/web_info.dart';
import 'package:nowser/const/app_type.dart';
@@ -224,6 +225,11 @@ class _WebViewComponent extends State<WebViewComponent>
}
}
},
onDownloadStartRequest: (InAppWebViewController controller,
DownloadStartRequest downloadStartRequest) {
String downloadUrl = downloadStartRequest.url.path;
DownloadTaskDialog.show(context, downloadUrl);
},
),
);
}