From b663b2d1efc1910309a108f34a7190948e6aacfc Mon Sep 17 00:00:00 2001 From: wanghongenpin Date: Thu, 16 Jan 2025 18:16:10 +0800 Subject: [PATCH] image save --- lib/network/http/content_type.dart | 2 + lib/network/util/process_info.dart | 2 +- lib/ui/content/body.dart | 67 +++++++++++++++---- lib/ui/desktop/request/request_sequence.dart | 10 ++- .../setting/rewrite/rewrite_replace.dart | 2 +- 5 files changed, 66 insertions(+), 17 deletions(-) diff --git a/lib/network/http/content_type.dart b/lib/network/http/content_type.dart index 372d2a5..e6dbff4 100644 --- a/lib/network/http/content_type.dart +++ b/lib/network/http/content_type.dart @@ -39,6 +39,8 @@ enum ContentType { bool get isBinary { return this == image || this == font || this == video; } + + bool get isImage => this == image; } class MediaType { diff --git a/lib/network/util/process_info.dart b/lib/network/util/process_info.dart index 9cb81a5..c166afa 100644 --- a/lib/network/util/process_info.dart +++ b/lib/network/util/process_info.dart @@ -157,7 +157,7 @@ class ProcessInfo { icon = (await InstalledApps.getAppInfo(id)).icon; } - if (Platform.operatingSystem == os || path.endsWith('.exe')) { + if ('windows' == os || path.endsWith('.exe')) { icon = await _getWindowsIcon(path); } diff --git a/lib/ui/content/body.dart b/lib/ui/content/body.dart index 0de78d7..1c89b4e 100644 --- a/lib/ui/content/body.dart +++ b/lib/ui/content/body.dart @@ -17,10 +17,12 @@ import 'dart:convert'; import 'dart:io'; import 'package:desktop_multi_window/desktop_multi_window.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_toastr/flutter_toastr.dart'; +import 'package:image_pickers/image_pickers.dart'; import 'package:proxypin/network/components/manager/request_rewrite_manager.dart'; import 'package:proxypin/network/components/manager/rewrite_rule.dart'; import 'package:proxypin/network/http/content_type.dart'; @@ -111,6 +113,7 @@ class HttpBodyState extends State { if (tabIndex > 0 && tabIndex >= tabs.list.length) tabIndex = tabs.list.length - 1; bodyKey.currentState?.changeState(widget.httpMessage, tabs.list[tabIndex]); + //TabBar List list = [ widget.inNewWindow ? const SizedBox() : titleWidget(), const SizedBox(height: 3), @@ -161,20 +164,25 @@ class HttpBodyState extends State { Widget titleWidget({inNewWindow = false}) { var type = widget.httpMessage is HttpRequest ? "Request" : "Response"; + bool isImage = widget.httpMessage?.contentType == ContentType.image; + var list = [ Text('$type Body', style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), const SizedBox(width: 10), - IconButton( - icon: const Icon(Icons.copy, size: 18), - tooltip: localizations.copy, - onPressed: () { - var body = bodyKey.currentState?.body; - if (body == null) { - return; - } - Clipboard.setData(ClipboardData(text: body)) - .then((value) => FlutterToastr.show(localizations.copied, context)); - }), + isImage + ? downloadImageButton() + : IconButton( + icon: Icon(Icons.copy, size: 18), + tooltip: localizations.copy, + onPressed: () { + var body = bodyKey.currentState?.body; + if (body == null) { + return; + } + Clipboard.setData(ClipboardData(text: body)).then((value) { + if (mounted) FlutterToastr.show(localizations.copied, context); + }); + }), ]; if (!widget.hideRequestRewrite) { @@ -201,7 +209,39 @@ class HttpBodyState extends State { return Wrap(crossAxisAlignment: WrapCrossAlignment.center, children: list); } - //展示请求重写 + ///下载图片 + Widget downloadImageButton() { + return IconButton( + icon: Icon(Icons.download, size: 20), + tooltip: localizations.saveImage, + onPressed: () async { + var body = bodyKey.currentState?.message?.body; + if (body == null) { + return; + } + var bytes = Uint8List.fromList(body); + if (Platforms.isMobile()) { + String? path = await ImagePickers.saveByteDataImageToGallery(bytes); + if (path != null && mounted) { + FlutterToastr.show(localizations.saveSuccess, context, duration: 2, rootNavigator: true); + } + return; + } + + if (Platforms.isDesktop()) { + var fileName = "image_${DateTime.now().millisecondsSinceEpoch}.png"; + String? path = (await FilePicker.platform.saveFile(fileName: fileName)); + if (path == null) return; + + await File(path).writeAsBytes(bytes); + if (mounted) { + FlutterToastr.show(localizations.saveSuccess, context, duration: 2); + } + } + }); + } + + ///展示请求重写 showRequestRewrite() async { HttpRequest? request; if (widget.httpMessage == null) { @@ -239,6 +279,7 @@ class HttpBodyState extends State { } } + ///打开新窗口 void openNew() async { if (Platforms.isDesktop()) { var size = MediaQuery.of(context).size; @@ -374,7 +415,7 @@ class _BodyState extends State<_Body> { return SelectableText(Uri.decodeFull(message!.bodyAsString), contextMenuBuilder: contextMenu); } if (type == ViewType.image) { - return Image.memory(Uint8List.fromList(message?.body ?? []), fit: BoxFit.scaleDown); + return Center(child: Image.memory(Uint8List.fromList(message?.body ?? []), fit: BoxFit.scaleDown)); } if (type == ViewType.video) { return const Center(child: Text("video not support preview")); diff --git a/lib/ui/desktop/request/request_sequence.dart b/lib/ui/desktop/request/request_sequence.dart index 48e6cc3..c797732 100644 --- a/lib/ui/desktop/request/request_sequence.dart +++ b/lib/ui/desktop/request/request_sequence.dart @@ -125,8 +125,14 @@ class RequestSequenceState extends State with AutomaticKeepAliv return futureWidget( processInfo.getIcon(), - (data) => - data.isEmpty ? const SizedBox() : Image.memory(data, width: 23, height: Platform.isWindows ? 16 : null)); + (data) => data.isEmpty + ? const SizedBox() + : Image.memory( + data, + width: 23, + height: Platform.isWindows ? 16 : null, + errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) => const SizedBox(), + )); } ///高亮处理 diff --git a/lib/ui/desktop/toolbar/setting/rewrite/rewrite_replace.dart b/lib/ui/desktop/toolbar/setting/rewrite/rewrite_replace.dart index 7a93fe5..faae18b 100644 --- a/lib/ui/desktop/toolbar/setting/rewrite/rewrite_replace.dart +++ b/lib/ui/desktop/toolbar/setting/rewrite/rewrite_replace.dart @@ -199,7 +199,7 @@ class RewriteReplaceState extends State { }); }, ), - const SizedBox(width: 10), + const SizedBox(width: 15), Text(localizations.enable), const SizedBox(width: 10), SwitchWidget(