diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index cedb4c5..33d003a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -232,6 +232,15 @@ "scriptEdit": "Edit script", "material3": "Material 3 is the latest version of Google’s open-source design system", - "iosVpnBackgroundAudio": "After turning on packet capture, exit to the background. In order to maintain the main UI thread for network communication, a silent audio playback will be enabled to keep the main thread running. Otherwise, it will only run in the background for 30 seconds. Do you agree to play audio in the background after turning on packet capture?" + "iosVpnBackgroundAudio": "After turning on packet capture, exit to the background. In order to maintain the main UI thread for network communication, a silent audio playback will be enabled to keep the main thread running. Otherwise, it will only run in the background for 30 seconds. Do you agree to play audio in the background after turning on packet capture?", + + "highlight": "Highlight", + "blue" : "Blue", + "green" : "Green", + "yellow" : "Yellow", + "red" : "Red", + "pink" : "Pink", + "gray" : "Gray", + "underline" : "Underline" } \ No newline at end of file diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index f998f17..09167a0 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -115,7 +115,7 @@ "domainListSubtitle": "最后请求时间: {time}, 次数: {count}", "copy": "复制", - "copyUrl": "复制请求连接", + "copyUrl": "复制URL", "copyRequestResponse": "复制请求和响应", "copyCurl": "复制 cURL 请求", "delete": "删除", @@ -125,7 +125,7 @@ "repeatCount": "次数", "repeatInterval": "间隔(ms)", "repeatDelay": "延时(ms)", - "editRequest": "编辑请求重放", + "editRequest": "编辑请求", "reSendRequest": "已重新发送请求", "viewExport": "视图导出", @@ -231,5 +231,15 @@ "scriptUseDescribe": "使用 JavaScript 修改请求和响应", "scriptEdit": "编辑脚本", "material3": "Material3是谷歌开源设计系统的最新版本", - "iosVpnBackgroundAudio": "开启抓包后,退出到后台。为了维护主UI线程的网络通信,将启用静音音频播放以保持主线程运行。否则,它将只在后台运行30秒。您同意在启用抓包后在后台播放音频吗?" + "iosVpnBackgroundAudio": "开启抓包后,退出到后台。为了维护主UI线程的网络通信,将启用静音音频播放以保持主线程运行。否则,它将只在后台运行30秒。您同意在启用抓包后在后台播放音频吗?", + + "highlight": "高亮", + "blue" : "蓝色", + "green" : "绿色", + "yellow" : "黄色", + "red" : "红色", + "pink" : "粉色", + "gray" : "灰色", + "underline" : "下划线" + } \ No newline at end of file diff --git a/lib/ui/component/widgets.dart b/lib/ui/component/widgets.dart index 6983579..e57b1da 100644 --- a/lib/ui/component/widgets.dart +++ b/lib/ui/component/widgets.dart @@ -112,15 +112,22 @@ class BottomSheetItem extends StatelessWidget { class IconText extends StatelessWidget { final GestureTapCallback? onTap; - final Icon icon; + final Icon? icon; + final Widget? trailing; final String text; + final TextStyle? textStyle; - const IconText({super.key, this.onTap, required this.text, required this.icon}); + const IconText({super.key, this.onTap, required this.text, this.icon, this.trailing, this.textStyle}); @override Widget build(BuildContext context) { return InkWell( onTap: onTap, - child: Row(children: [icon, const SizedBox(width: 8), Text(text)])); + child: Row(children: [ + if (icon != null) icon!, + if (icon != null) const SizedBox(width: 8), + Expanded(child: Text(text, style: textStyle)), + if (trailing != null) trailing! + ])); } } diff --git a/lib/ui/desktop/desktop.dart b/lib/ui/desktop/desktop.dart index 27ca8b2..9dd90fc 100644 --- a/lib/ui/desktop/desktop.dart +++ b/lib/ui/desktop/desktop.dart @@ -203,17 +203,19 @@ class _DesktopHomePagePageState extends State implements EventL '1. 历史记录支持自动缓存时间设置;\n' '2. 增加当前视图导出;\n' '3. 历史记录增加搜索;\n' - '4. Android返回键进入小窗口;\n' - '5. Android白名单应用列表展示隐藏图标应用;\n' - '6. 修复websocket暗黑主题展示不清楚;\n' + '4. 支持高亮请求;\n' + '5. Android返回键进入小窗口;\n' + '6. Android白名单应用列表展示隐藏图标应用;\n' + '7. 修复websocket暗黑主题展示不清楚;\n' : 'Tips:By default, HTTPS packet capture will not be enabled. Please install the certificate before enabling HTTPS packet capture。\n' 'Click HTTPS Capture packets(Lock icon),Choose to install the root certificate and follow the prompts to proceed。\n\n' '1. History support auto cache time setting;\n' '2. Add current view export;\n' '3. History Add Search;\n' - '4. Android Return key to enter the small window;\n' - '5. Android Whitelist application list display hidden icon applications;\n' - '6. Fix websocket dark theme display unclear;\n', + '4. Supports highlighting requests;\n' + '5. Android Return key to enter the small window;\n' + '6. Android Whitelist application list display hidden icon applications;\n' + '7. Fix websocket dark theme display unclear;\n', style: const TextStyle(fontSize: 14))); }); } diff --git a/lib/ui/desktop/left/history.dart b/lib/ui/desktop/left/history.dart index e012461..09247a2 100644 --- a/lib/ui/desktop/left/history.dart +++ b/lib/ui/desktop/left/history.dart @@ -71,19 +71,22 @@ class HistoryPageWidget extends StatelessWidget { style: const TextStyle(fontSize: 14)), actions: [ PopupMenuButton( - offset: const Offset(0, 30), - icon: const Icon(Icons.more_vert_outlined), + offset: const Offset(0, 32), + icon: const Icon(Icons.more_vert_outlined, size: 20), itemBuilder: (BuildContext context) { return [ PopupMenuItem( - height: 35, + height: 32, onTap: () { String fileName = '${item.name.contains("ProxyPin") ? '' : 'ProxyPin'}${item.name}.har' .replaceAll(" ", "_") .replaceAll(":", "_"); domainKey.currentState?.export(fileName); }, - child: IconText(icon: const Icon(Icons.share), text: localizations.viewExport)), + child: IconText( + icon: const Icon(Icons.share, size: 18), + text: localizations.viewExport, + textStyle: const TextStyle(fontSize: 14))), ]; }), ], @@ -134,7 +137,6 @@ class _HistoryListState extends State<_HistoryListWidget> { if (mounted) setState(() {}); })); }); - } @override diff --git a/lib/ui/desktop/left/request.dart b/lib/ui/desktop/left/request.dart index 8967f2a..bc93b70 100644 --- a/lib/ui/desktop/left/request.dart +++ b/lib/ui/desktop/left/request.dart @@ -5,6 +5,7 @@ import 'package:date_format/date_format.dart'; import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_desktop_context_menu/flutter_desktop_context_menu.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_toastr/flutter_toastr.dart'; import 'package:network_proxy/network/bin/server.dart'; @@ -50,6 +51,8 @@ class _RequestWidgetState extends State { bool selected = false; + Color? highlightColor; //高亮颜色 + AppLocalizations get localizations => AppLocalizations.of(context)!; @override @@ -66,9 +69,11 @@ class _RequestWidgetState extends State { var packagesSize = getPackagesSize(request, response); return GestureDetector( - onSecondaryTapDown: menu, + onSecondaryTap: contextualMenu, child: ListTile( minLeadingWidth: 5, + textColor: highlightColor, + selectedColor: highlightColor, leading: getIcon(widget.response.get() ?? widget.request.response), title: Text(title, overflow: TextOverflow.ellipsis, maxLines: 1), subtitle: Text( @@ -87,41 +92,124 @@ class _RequestWidgetState extends State { setState(() {}); } - ///右键菜单 - menu(TapDownDetails details) { - showContextMenu( - context, - details.globalPosition, - items: [ - popupItem(localizations.copyUrl, onTap: () { + contextualMenu() { + Menu menu = Menu(items: [ + MenuItem( + label: localizations.copyUrl, + onClick: (_) { var requestUrl = widget.request.requestUrl; Clipboard.setData(ClipboardData(text: requestUrl)) .then((value) => FlutterToastr.show(localizations.copied, context)); - }), - popupItem(localizations.copyRequestResponse, onTap: () { + }, + ), + MenuItem( + label: localizations.copyRequestResponse, + onClick: (_) { Clipboard.setData(ClipboardData(text: copyRequest(widget.request, widget.response.get()))) .then((value) => FlutterToastr.show(localizations.copied, context)); - }), - popupItem(localizations.copyCurl, onTap: () { + }, + ), + MenuItem( + label: localizations.copyCurl, + onClick: (_) { Clipboard.setData(ClipboardData(text: curlRequest(widget.request))) .then((value) => FlutterToastr.show(localizations.copied, context)); - }), - const PopupMenuDivider(height: 0.3), - popupItem(localizations.repeat, onTap: () => onRepeat(widget.request)), - popupItem(localizations.customRepeat, onTap: () => showCustomRepeat(widget.request)), - popupItem(localizations.editRequest, onTap: () { + }, + ), + MenuItem.separator(), + MenuItem( + label: localizations.repeat, + onClick: (_) => onRepeat(widget.request), + ), + MenuItem( + label: localizations.customRepeat, + onClick: (_) => showCustomRepeat(widget.request), + ), + MenuItem( + label: localizations.editRequest, + onClick: (_) { WidgetsBinding.instance.addPostFrameCallback((_) { requestEdit(); }); - }), - popupItem(localizations.favorite, onTap: () { + }, + ), + MenuItem.separator(), + MenuItem( + label: localizations.favorite, + onClick: (_) { FavoriteStorage.addFavorite(widget.request); FlutterToastr.show(localizations.operationSuccess, context); - }), - const PopupMenuDivider(height: 0.3), - popupItem(localizations.delete, onTap: () { + }, + ), + MenuItem( + label: localizations.highlight, + type: 'submenu', + submenu: highlightMenu(), + onClick: (_) { + setState(() { + highlightColor = Colors.red; + }); + }, + ), + MenuItem.separator(), + MenuItem( + label: localizations.delete, + onClick: (_) { widget.remove?.call(widget); - }), + }, + ), + ]); + + popUpContextMenu(menu); + } + + ///高亮 + Menu highlightMenu() { + return Menu( + items: [ + MenuItem( + label: localizations.red, + onClick: (_) { + setState(() { + highlightColor = Colors.red; + }); + }), + MenuItem( + label: localizations.yellow, + onClick: (_) { + setState(() { + highlightColor = Colors.yellow.shade600; + }); + }), + MenuItem( + label: localizations.blue, + onClick: (_) { + setState(() { + highlightColor = Colors.blue; + }); + }), + MenuItem( + label: localizations.green, + onClick: (_) { + setState(() { + highlightColor = Colors.green; + }); + }), + MenuItem( + label: localizations.gray, + onClick: (_) { + setState(() { + highlightColor = Colors.grey; + }); + }), + MenuItem.separator(), + MenuItem( + label: localizations.reset, + onClick: (_) { + setState(() { + highlightColor = null; + }); + }), ], ); } diff --git a/lib/ui/desktop/toolbar/setting/setting.dart b/lib/ui/desktop/toolbar/setting/setting.dart index dd8d6d5..dbf99fa 100644 --- a/lib/ui/desktop/toolbar/setting/setting.dart +++ b/lib/ui/desktop/toolbar/setting/setting.dart @@ -37,15 +37,6 @@ class _SettingState extends State { super.initState(); } - Widget item(String text, {VoidCallback? onPressed}) { - return MenuItemButton( - trailingIcon: const Icon(Icons.arrow_right), - onPressed: onPressed, - child: Padding( - padding: const EdgeInsets.only(left: 10, right: 5), - child: Text(text, style: const TextStyle(fontSize: 14)))); - } - @override Widget build(BuildContext context) { var surfaceTintColor = @@ -76,16 +67,13 @@ class _SettingState extends State { ); } - PopupMenuItem menuItem(String title, {GestureTapCallback? onTap}) { - return PopupMenuItem( - child: ListTile( - title: Text(title), - dense: true, - hoverColor: Colors.transparent, - focusColor: Colors.transparent, - trailing: const Icon(Icons.arrow_right), - onTap: onTap, - )); + Widget item(String text, {VoidCallback? onPressed}) { + return MenuItemButton( + trailingIcon: const Icon(Icons.arrow_right), + onPressed: onPressed, + child: Padding( + padding: const EdgeInsets.only(left: 10, right: 5), + child: Text(text, style: const TextStyle(fontSize: 14)))); } ///设置外部代理地址 diff --git a/lib/ui/mobile/menu.dart b/lib/ui/mobile/menu.dart index 068456c..1c85e4a 100644 --- a/lib/ui/mobile/menu.dart +++ b/lib/ui/mobile/menu.dart @@ -266,7 +266,7 @@ class MoreMenu extends StatelessWidget { itemBuilder: (BuildContext context) { return [ PopupMenuItem( - height: 35, + height: 32, child: ListTile( dense: true, title: Text(localizations.httpsProxy), @@ -279,7 +279,7 @@ class MoreMenu extends StatelessWidget { ); })), PopupMenuItem( - height: 35, + height: 32, child: ListTile( dense: true, leading: const Icon(Icons.qr_code_scanner_outlined), @@ -289,7 +289,7 @@ class MoreMenu extends StatelessWidget { }, )), PopupMenuItem( - height: 35, + height: 32, child: ListTile( dense: true, leading: const Icon(Icons.phone_iphone), @@ -303,7 +303,7 @@ class MoreMenu extends StatelessWidget { )), const PopupMenuDivider(height: 0), PopupMenuItem( - height: 35, + height: 32, child: ListTile( dense: true, leading: const Icon(Icons.share), diff --git a/lib/ui/mobile/mobile.dart b/lib/ui/mobile/mobile.dart index 07565a9..df9471d 100644 --- a/lib/ui/mobile/mobile.dart +++ b/lib/ui/mobile/mobile.dart @@ -228,16 +228,18 @@ class MobileHomeState extends State implements EventListener, Li '1. 历史记录支持自动缓存时间设置;\n' '2. 增加当前视图导出;\n' '3. 历史记录增加搜索;\n' - '4. Android返回键进入小窗口;\n' - '5. Android白名单应用列表展示隐藏图标应用;\n' - '6. 修复websocket暗黑主题展示不清楚;\n' + '4. 支持高亮请求;\n' + '5. Android返回键进入小窗口;\n' + '6. Android白名单应用列表展示隐藏图标应用;\n' + '7. 修复websocket暗黑主题展示不清楚;\n' : 'Tips:By default, HTTPS packet capture will not be enabled. Please install the certificate before enabling HTTPS packet capture。\n\n' '1. History support auto cache time setting;\n' '2. Add current view export;\n' '3. History Add Search;\n' - '4. Android Return key to enter the small window;\n' - '5. Android Whitelist application list display hidden icon applications;\n' - '6. Fix websocket dark theme display unclear;\n'; + '4. Supports highlighting requests;\n' + '5. Android Return key to enter the small window;\n' + '6. Android Whitelist application list display hidden icon applications;\n' + '7. Fix websocket dark theme display unclear;\n'; showAlertDialog(isCN ? '更新内容V1.0.8' : "Update content V1.0.8", content, () { widget.appConfiguration.upgradeNoticeV8 = false; widget.appConfiguration.flushConfig(); diff --git a/lib/ui/mobile/request/request.dart b/lib/ui/mobile/request/request.dart index d5a0fa9..ebb5464 100644 --- a/lib/ui/mobile/request/request.dart +++ b/lib/ui/mobile/request/request.dart @@ -41,6 +41,10 @@ class RequestRowState extends State { late HttpRequest request; HttpResponse? response; + bool selected = false; + + Color? highlightColor; //高亮颜色 + AppLocalizations get localizations => AppLocalizations.of(context)!; change(HttpResponse response) { @@ -70,6 +74,9 @@ class RequestRowState extends State { return ListTile( visualDensity: const VisualDensity(vertical: -4), minLeadingWidth: 5, + selected: selected, + textColor: highlightColor, + selectedColor: highlightColor, leading: getIcon(response), title: Text(title, overflow: TextOverflow.ellipsis, maxLines: 2, style: const TextStyle(fontSize: 14)), subtitle: Text.rich( @@ -81,7 +88,7 @@ class RequestRowState extends State { trailing: const Icon(Icons.chevron_right, size: 22), dense: true, contentPadding: const EdgeInsets.only(left: 3), - onLongPress: menu, + onLongPress: showMenu, onTap: () { Navigator.push( context, @@ -97,73 +104,148 @@ class RequestRowState extends State { }); } - ///菜单 - menu() { + showMenu() { + setState(() { + selected = true; + }); showModalBottomSheet( - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(10))), - context: context, - isScrollControlled: true, - enableDrag: true, - builder: (ctx) { - return Wrap(alignment: WrapAlignment.center, children: [ - menuItem(localizations.copyUrl, () => widget.request.requestUrl), - const Divider(thickness: 0.5, height: 5), - menuItem(localizations.copyCurl, () => curlRequest(widget.request)), - const Divider(thickness: 0.5, height: 5), - TextButton( - child: SizedBox(width: double.infinity, child: Text(localizations.repeat, textAlign: TextAlign.center)), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(10))), + context: context, + isScrollControlled: true, + enableDrag: true, + builder: (ctx) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Wrap( + children: [ + copyItem(), + const Divider(thickness: 0.3, height: 3), + repeatItem(), + const Divider(thickness: 0.3, height: 5), + ListTile( + dense: true, + title: Text(localizations.highlight, textAlign: TextAlign.center), + trailing: const Icon(Icons.chevron_right), + onTap: () { + //显示高亮菜单 + Navigator.of(context).pop(); + showHighlightMenu(); + }), + ListTile( + dense: true, + title: Text(localizations.favorite, textAlign: TextAlign.center), + trailing: const Icon(Icons.favorite), + onTap: () { + FavoriteStorage.addFavorite(widget.request); + FlutterToastr.show(localizations.addSuccess, context); + Navigator.of(context).pop(); + }, + ), + ListTile( + onTap: () { + widget.onRemove?.call(request); + FlutterToastr.show(localizations.deleteSuccess, context); + Navigator.of(context).pop(); + }, + dense: true, + title: Text(localizations.delete, textAlign: TextAlign.center), + trailing: const Icon(Icons.remove)), + Container( + color: Theme.of(context).hoverColor, + height: 8, + ), + ListTile( + dense: true, + onTap: () => Navigator.of(context).pop(), + title: Container( + height: 50, + width: double.infinity, + padding: const EdgeInsets.only(top: 10), + child: Text(localizations.cancel, textAlign: TextAlign.center)), + trailing: const Icon(Icons.cancel_presentation)), + ], + )); + }).then((value) => setState(() { + selected = false; + })); + } + + Widget copyItem() { + var dividerColor = Theme.of(context).dividerColor; + var styleFrom = OutlinedButton.styleFrom( + textStyle: const TextStyle(fontSize: 14), + side: BorderSide(width: 0.3, color: dividerColor), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))); + + return Wrap(alignment: WrapAlignment.center, children: [ + Container( + padding: const EdgeInsets.only(left: 15, top: 10, bottom: 5), + width: double.infinity, + child: Text(localizations.copy, textAlign: TextAlign.left, style: const TextStyle(fontSize: 12))), + SizedBox( + width: double.infinity, + child: Wrap(alignment: WrapAlignment.spaceAround, spacing: 15, children: [ + OutlinedButton( + onPressed: () { + Clipboard.setData(ClipboardData(text: widget.request.requestUrl)).then((value) { + FlutterToastr.show(localizations.copied, context); + Navigator.of(context).pop(); + }); + }, + style: styleFrom, + child: Text(localizations.copyUrl), + ), + OutlinedButton( + onPressed: () { + Clipboard.setData(ClipboardData(text: curlRequest(widget.request))).then((value) { + FlutterToastr.show(localizations.copied, context); + Navigator.of(context).pop(); + }); + }, + style: styleFrom, + child: Text(localizations.copyCurl)) + ])) + ]); + } + + Widget repeatItem() { + var dividerColor = Theme.of(context).dividerColor; + var styleFrom = OutlinedButton.styleFrom( + textStyle: const TextStyle(fontSize: 14), + side: BorderSide(width: 0.3, color: dividerColor), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))); + + return Wrap(alignment: WrapAlignment.center, children: [ + Container( + padding: const EdgeInsets.only(left: 15, top: 5, bottom: 5), + width: double.infinity, + child: Text(localizations.repeat, textAlign: TextAlign.left, style: const TextStyle(fontSize: 12))), + SizedBox( + width: double.infinity, + child: Wrap(alignment: WrapAlignment.spaceAround, spacing: 15, children: [ + OutlinedButton( onPressed: () { onRepeat(widget.request); Navigator.of(context).pop(); - }), - const Divider(thickness: 0.5, height: 5), - TextButton( - child: SizedBox( - width: double.infinity, child: Text(localizations.customRepeat, textAlign: TextAlign.center)), - onPressed: () => showCustomRepeat(widget.request)), - const Divider(thickness: 0.5, height: 5), - TextButton( - child: - SizedBox(width: double.infinity, child: Text(localizations.editRequest, textAlign: TextAlign.center)), - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => - MobileRequestEditor(request: widget.request, proxyServer: widget.proxyServer))); - }), - const Divider(thickness: 0.5, height: 5), - TextButton( - child: SizedBox(width: double.infinity, child: Text(localizations.favorite, textAlign: TextAlign.center)), - onPressed: () { - FavoriteStorage.addFavorite(widget.request); - FlutterToastr.show(localizations.addSuccess, context); - Navigator.of(context).pop(); - }), - const Divider(thickness: 0.5, height: 5), - TextButton( - child: SizedBox(width: double.infinity, child: Text(localizations.delete, textAlign: TextAlign.center)), - onPressed: () { - widget.onRemove?.call(request); - FlutterToastr.show(localizations.deleteSuccess, context); - Navigator.of(context).pop(); - }), - Container( - color: Theme.of(context).hoverColor, - height: 8, - ), - TextButton( - child: Container( - height: 55, - width: double.infinity, - padding: const EdgeInsets.only(top: 10), - child: Text(localizations.cancel, textAlign: TextAlign.center)), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ]); - }, - ); + }, + style: styleFrom, + child: Text(localizations.repeat), + ), + OutlinedButton( + onPressed: () => showCustomRepeat(widget.request), + style: styleFrom, + child: Text(localizations.customRepeat)), + OutlinedButton( + onPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => + MobileRequestEditor(request: widget.request, proxyServer: widget.proxyServer))); + }, + style: styleFrom, + child: Text(localizations.editRequest)) + ])) + ]); } //显示高级重发 @@ -183,14 +265,81 @@ class RequestRowState extends State { } } - Widget menuItem(String title, String Function() callback) { - return TextButton( - child: SizedBox(width: double.infinity, child: Text(title, textAlign: TextAlign.center)), - onPressed: () { - Clipboard.setData(ClipboardData(text: callback.call())).then((value) { - FlutterToastr.show(localizations.copied, context); - Navigator.of(context).pop(); - }); + void showHighlightMenu() { + showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(10))), + enableDrag: true, + builder: (BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Wrap( + children: [ + ListTile( + leading: const Icon(Icons.circle, color: Colors.red), + title: Text(localizations.red), + onTap: () { + setState(() { + highlightColor = Colors.red; + }); + Navigator.of(context).pop(); + }, + ), + ListTile( + leading: const Icon(Icons.circle, color: Colors.yellow), + title: Text(localizations.yellow), + onTap: () { + setState(() { + highlightColor = Colors.yellow.shade600; + }); + Navigator.of(context).pop(); + }, + ), + ListTile( + leading: const Icon(Icons.circle, color: Colors.blue), + title: Text(localizations.blue), + onTap: () { + setState(() { + highlightColor = Colors.blue; + }); + Navigator.of(context).pop(); + }, + ), + ListTile( + leading: const Icon(Icons.circle, color: Colors.green), + title: Text(localizations.green), + onTap: () { + setState(() { + highlightColor = Colors.green; + }); + Navigator.of(context).pop(); + }, + ), + ListTile( + leading: const Icon(Icons.circle, color: Colors.grey), + title: Text(localizations.gray), + onTap: () { + setState(() { + highlightColor = Colors.grey; + }); + Navigator.of(context).pop(); + }, + ), + const Divider(), + ListTile( + leading: const Icon(Icons.restart_alt), + title: Text(localizations.reset), + onTap: () { + setState(() { + highlightColor = null; + }); + Navigator.of(context).pop(); + }, + ), + const SizedBox(height: 10) + ], + ), + ); }); } } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index b5fee3b..c6f7be7 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -21,6 +22,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) flutter_desktop_context_menu_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterDesktopContextMenuPlugin"); + flutter_desktop_context_menu_plugin_register_with_registrar(flutter_desktop_context_menu_registrar); g_autoptr(FlPluginRegistrar) flutter_js_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterJsPlugin"); flutter_js_plugin_register_with_registrar(flutter_js_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 4791c1f..81c7476 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_multi_window file_selector_linux + flutter_desktop_context_menu flutter_js proxy_manager screen_retriever diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index dba7c8a..4d1e4a5 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,6 +7,7 @@ import Foundation import desktop_multi_window import file_selector_macos +import flutter_desktop_context_menu import flutter_js import path_provider_foundation import proxy_manager @@ -18,6 +19,7 @@ import window_manager func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterMultiWindowPlugin.register(with: registry.registrar(forPlugin: "FlutterMultiWindowPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FlutterDesktopContextMenuPlugin.register(with: registry.registrar(forPlugin: "FlutterDesktopContextMenuPlugin")) FlutterJsPlugin.register(with: registry.registrar(forPlugin: "FlutterJsPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) ProxyManagerPlugin.register(with: registry.registrar(forPlugin: "ProxyManagerPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 581d077..8b32330 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -158,10 +158,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.1.2" file: dependency: transitive description: @@ -190,18 +190,18 @@ packages: dependency: transitive description: name: file_selector_android - sha256: a2d50f9de59861605b866467a55d681a0ca7bc108129c0bd33e74fa602dd0249 + sha256: "1cd66575f063b689e041aec836905ba7be18d76c9f0634d0d75daec825f67095" url: "https://pub.flutter-io.cn" source: hosted - version: "0.5.0+5" + version: "0.5.0+7" file_selector_ios: dependency: transitive description: name: file_selector_ios - sha256: "2f48db7e338b2255101c35c604b7ca5ab588dce032db7fc418a2fe5f28da63f8" + sha256: b015154e6d9fddbc4d08916794df170b44531798c8dd709a026df162d07ad81d url: "https://pub.flutter-io.cn" source: hosted - version: "0.5.1+7" + version: "0.5.1+8" file_selector_linux: dependency: transitive description: @@ -222,10 +222,10 @@ packages: dependency: transitive description: name: file_selector_platform_interface - sha256: "0aa47a725c346825a2bd396343ce63ac00bda6eff2fbc43eabe99737dede8262" + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b url: "https://pub.flutter-io.cn" source: hosted - version: "2.6.1" + version: "2.6.2" file_selector_web: dependency: transitive description: @@ -242,6 +242,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.9.3+1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -263,6 +271,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.3.1" + flutter_desktop_context_menu: + dependency: "direct main" + description: + name: flutter_desktop_context_menu + sha256: "31bd0f8d26a807abc3904f0300433c4a1cd0d071a944c1d8b10b1bb8b5e7e5f0" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.0" flutter_highlight: dependency: transitive description: @@ -346,10 +362,10 @@ packages: dependency: transitive description: name: http - sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.2" + version: "1.2.0" http_parser: dependency: transitive description: @@ -370,10 +386,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: "4186c61b32f99e60f011f7160e32c89a758ae9b1d0c6d28e2c02ef0382300e2b" url: "https://pub.flutter-io.cn" source: hosted - version: "0.6.7" + version: "0.7.0" json_annotation: dependency: transitive description: @@ -466,18 +482,18 @@ packages: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.4" + version: "1.0.5" mocktail: dependency: transitive description: name: mocktail - sha256: f603ebd85a576e5914870b02e5839fc5d0243b867bf710651cf239a28ebb365e + sha256: c4b5007d91ca4f67256e720cb1b6d704e79a510183a12fa551021f652577dce6 url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.2" + version: "1.0.3" path: dependency: transitive description: @@ -506,10 +522,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.flutter-io.cn" source: hosted - version: "2.3.1" + version: "2.3.2" path_provider_linux: dependency: transitive description: @@ -522,10 +538,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -554,10 +570,10 @@ packages: dependency: transitive description: name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.flutter-io.cn" source: hosted - version: "3.7.3" + version: "3.7.4" proxy_manager: dependency: "direct main" description: @@ -610,10 +626,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd + sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900" url: "https://pub.flutter-io.cn" source: hosted - version: "7.2.1" + version: "7.2.2" share_plus_platform_interface: dependency: transitive description: @@ -719,18 +735,18 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: c0766a55ab42cefaa728cabc951e82919ab41a3a4fee0aaa96176ca82da8cc51 + sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" url: "https://pub.flutter-io.cn" source: hosted - version: "6.2.1" + version: "6.2.2" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "46b81e3109cbb2d6b81702ad3077540789a3e74e22795eb9f0b7d494dbaa72ea" + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" url: "https://pub.flutter-io.cn" source: hosted - version: "6.2.2" + version: "6.2.4" url_launcher_linux: dependency: transitive description: @@ -751,10 +767,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: f099b552bd331eacd69affed7ff2f23bfa6b0cb825b629edf3d844375a7501ad + sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.1" + version: "2.3.1" url_launcher_web: dependency: transitive description: @@ -775,10 +791,10 @@ packages: dependency: transitive description: name: uuid - sha256: bb55f38968b9427ce5dcdb8aaaa41049282195e0cfa4cf48593572fa3d1f36bc + sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 url: "https://pub.flutter-io.cn" source: hosted - version: "4.3.1" + version: "4.3.3" vector_math: dependency: transitive description: @@ -843,10 +859,10 @@ packages: dependency: transitive description: name: web - sha256: edc8a9573dd8c5a83a183dae1af2b6fd4131377404706ca4e5420474784906fa + sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05" url: "https://pub.flutter-io.cn" source: hosted - version: "0.4.0" + version: "0.4.2" win32: dependency: transitive description: @@ -859,10 +875,10 @@ packages: dependency: "direct main" description: name: window_manager - sha256: dcc865277f26a7dad263a47d0e405d77e21f12cb71f30333a52710a408690bd7 + sha256: b3c895bdf936c77b83c5254bec2e6b3f066710c1f89c38b20b8acc382b525494 url: "https://pub.flutter-io.cn" source: hosted - version: "0.3.7" + version: "0.3.8" xdg_directories: dependency: transitive description: @@ -872,5 +888,5 @@ packages: source: hosted version: "1.0.4" sdks: - dart: ">=3.2.0 <4.0.0" + dart: ">=3.3.0-279.1.beta <4.0.0" flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index 61f7bfa..5daa2f8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,7 @@ dependencies: basic_utils: ^5.7.0 logger: ^2.0.1 date_format: ^2.0.7 - window_manager: ^0.3.7 + window_manager: ^0.3.8 desktop_multi_window: git: url: https://gitee.com/wanghongenpin/flutter-plugins.git @@ -37,6 +37,7 @@ dependencies: flutter_js: ^0.8.0 flutter_code_editor: file_picker: ^6.1.1 + flutter_desktop_context_menu: ^0.2.0 video_player: git: url: https://github.com/icapps/plugins.git diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 41f8a63..5101675 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("DesktopMultiWindowPlugin")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); + FlutterDesktopContextMenuPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterDesktopContextMenuPlugin")); FlutterJsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterJsPlugin")); ProxyManagerPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index c64635a..b78b3a9 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_multi_window file_selector_windows + flutter_desktop_context_menu flutter_js proxy_manager screen_retriever