diff --git a/android/app/build.gradle b/android/app/build.gradle index dff8580..eca5950 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -51,7 +51,7 @@ android { applicationId "com.network.proxy" ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64' } // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion 21 + minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion multiDexEnabled true versionCode flutterVersionCode.toInteger() @@ -88,4 +88,4 @@ flutter { } dependencies { -} \ No newline at end of file +} diff --git a/assets/icon_foreground.png b/assets/icon_foreground.png new file mode 100644 index 0000000..12c1487 Binary files /dev/null and b/assets/icon_foreground.png differ diff --git a/lib/main.dart b/lib/main.dart index cc714f8..ef0c256 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -64,7 +64,7 @@ void main(List args) async { minimumSize: const Size(1000, 600), size: windowSize, center: true, - titleBarStyle: Platform.isMacOS ? TitleBarStyle.hidden : TitleBarStyle.normal); + titleBarStyle: TitleBarStyle.hidden ); Offset? windowPosition = appConfiguration.windowPosition; diff --git a/lib/network/channel/channel.dart b/lib/network/channel/channel.dart index e00ef33..091983c 100644 --- a/lib/network/channel/channel.dart +++ b/lib/network/channel/channel.dart @@ -170,9 +170,9 @@ class Channel { await Future.delayed(const Duration(milliseconds: 150)); } isOpen = false; - if (!isWriting) { - await _socket.flush(); - } + // if (!isWriting) { + // await _socket.flush(); + // } await _socket.close(); _socket.destroy(); } diff --git a/lib/network/channel/network.dart b/lib/network/channel/network.dart index 2531324..7888c69 100644 --- a/lib/network/channel/network.dart +++ b/lib/network/channel/network.dart @@ -208,7 +208,7 @@ class Server extends Network { Channel? remoteChannel = channelContext.serverChannel; - if (HostFilter.filter(hostAndPort.host) || !configuration.enableSsl) { + if (!isHttp || HostFilter.filter(hostAndPort.host) || !configuration.enableSsl) { remoteChannel = remoteChannel ?? await channelContext.connectServerChannel(hostAndPort, RelayHandler(channel)); relay(channel, remoteChannel); channel.dispatcher.channelRead(channelContext, channel, data); diff --git a/lib/ui/desktop/request/model/search_model.dart b/lib/ui/component/model/search_model.dart similarity index 100% rename from lib/ui/desktop/request/model/search_model.dart rename to lib/ui/component/model/search_model.dart diff --git a/lib/ui/desktop/request/search_condition.dart b/lib/ui/component/search_condition.dart similarity index 99% rename from lib/ui/desktop/request/search_condition.dart rename to lib/ui/component/search_condition.dart index 2fec892..bfbafaa 100644 --- a/lib/ui/desktop/request/search_condition.dart +++ b/lib/ui/component/search_condition.dart @@ -19,9 +19,10 @@ import 'package:get/get.dart'; import 'package:proxypin/l10n/app_localizations.dart'; import 'package:proxypin/network/http/content_type.dart'; import 'package:proxypin/network/http/http.dart'; -import 'package:proxypin/ui/desktop/request/model/search_model.dart'; import 'package:proxypin/utils/lang.dart'; +import 'model/search_model.dart'; + /// @author wanghongen /// 2023/8/6 class SearchConditions extends StatefulWidget { diff --git a/lib/ui/desktop/desktop.dart b/lib/ui/desktop/desktop.dart index 25f7d6d..dd1d2e6 100644 --- a/lib/ui/desktop/desktop.dart +++ b/lib/ui/desktop/desktop.dart @@ -14,6 +14,8 @@ * limitations under the License. */ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:proxypin/l10n/app_localizations.dart'; import 'package:proxypin/network/bin/configuration.dart'; @@ -32,6 +34,7 @@ import 'package:proxypin/ui/desktop/left_menus/history.dart'; import 'package:proxypin/ui/desktop/left_menus/navigation.dart'; import 'package:proxypin/ui/desktop/request/list.dart'; import 'package:proxypin/ui/desktop/toolbar/toolbar.dart'; +import 'package:proxypin/ui/desktop/widgets/windows_toolbar.dart'; import 'package:proxypin/utils/listenable_list.dart'; import '../app_update/app_update_repository.dart'; @@ -111,9 +114,16 @@ class _DesktopHomePagePageState extends State implements EventL return Scaffold( appBar: Tab( child: Container( + padding: EdgeInsets.only(bottom: 2.5), + margin: EdgeInsets.only(bottom: 2.5), decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: Theme.of(context).dividerColor.withOpacity(0.25), width: 0.2))), - child: Toolbar(proxyServer, requestListStateKey, sideNotifier: _selectIndex), + color: Theme.of(context).brightness == Brightness.dark ? null : Color(0xFFF9F9F9), + border: Border( + bottom: BorderSide( + color: Theme.of(context).dividerColor.withOpacity(0.3), width: Platform.isMacOS ? 0.2 : 0.55))), + child: Platform.isMacOS + ? Toolbar(proxyServer, requestListStateKey) + : WindowsToolbar(title: Toolbar(proxyServer, requestListStateKey)), )), body: Row( children: [ diff --git a/lib/ui/desktop/request/domians.dart b/lib/ui/desktop/request/domians.dart index 8e4532c..f771eaa 100644 --- a/lib/ui/desktop/request/domians.dart +++ b/lib/ui/desktop/request/domians.dart @@ -33,11 +33,12 @@ import 'package:proxypin/network/http/http_client.dart'; import 'package:proxypin/ui/component/transition.dart'; import 'package:proxypin/ui/component/utils.dart'; import 'package:proxypin/ui/content/panel.dart'; -import 'package:proxypin/ui/desktop/request/model/search_model.dart'; import 'package:proxypin/ui/desktop/request/request.dart'; import 'package:proxypin/utils/keyword_highlight.dart'; import 'package:proxypin/utils/listenable_list.dart'; +import '../../component/model/search_model.dart'; + /// 左侧域名 /// @author wanghongen /// 2023/10/8 @@ -78,7 +79,7 @@ class DomainWidgetState extends State with AutomaticKeepAliveClientM bool sortDesc = true; - changeState() { + void changeState() { if (!changing) { changing = true; Future.delayed(const Duration(milliseconds: 500), () { diff --git a/lib/ui/desktop/request/list.dart b/lib/ui/desktop/request/list.dart index a751711..a33e027 100644 --- a/lib/ui/desktop/request/list.dart +++ b/lib/ui/desktop/request/list.dart @@ -27,13 +27,13 @@ import 'package:proxypin/network/http/http.dart'; import 'package:proxypin/network/http/http_client.dart'; import 'package:proxypin/ui/component/widgets.dart'; import 'package:proxypin/ui/content/panel.dart'; -import 'package:proxypin/ui/desktop/request/model/search_model.dart'; import 'package:proxypin/ui/desktop/request/request_sequence.dart'; import 'package:proxypin/ui/desktop/request/search.dart'; import 'package:proxypin/utils/har.dart'; import 'package:proxypin/utils/lang.dart'; import 'package:proxypin/utils/listenable_list.dart'; +import '../../component/model/search_model.dart'; import 'domians.dart'; /// @author wanghongen diff --git a/lib/ui/desktop/request/request_sequence.dart b/lib/ui/desktop/request/request_sequence.dart index 356cd05..62cfa1f 100644 --- a/lib/ui/desktop/request/request_sequence.dart +++ b/lib/ui/desktop/request/request_sequence.dart @@ -21,11 +21,12 @@ import 'package:proxypin/network/bin/configuration.dart'; import 'package:proxypin/network/bin/server.dart'; import 'package:proxypin/network/http/http.dart'; import 'package:proxypin/ui/component/utils.dart'; -import 'package:proxypin/ui/desktop/request/model/search_model.dart'; import 'package:proxypin/ui/desktop/request/request.dart'; import 'package:proxypin/utils/keyword_highlight.dart'; import 'package:proxypin/utils/listenable_list.dart'; +import '../../component/model/search_model.dart'; + ///请求序列 列表 /// @author wanghongen class RequestSequence extends StatefulWidget { diff --git a/lib/ui/desktop/request/search.dart b/lib/ui/desktop/request/search.dart index fcedde4..5c44da9 100644 --- a/lib/ui/desktop/request/search.dart +++ b/lib/ui/desktop/request/search.dart @@ -16,8 +16,9 @@ import 'package:flutter/material.dart'; import 'package:proxypin/l10n/app_localizations.dart'; import 'package:proxypin/network/http/content_type.dart'; -import 'package:proxypin/ui/desktop/request/model/search_model.dart'; -import 'package:proxypin/ui/desktop/request/search_condition.dart'; +import 'package:proxypin/ui/component/search_condition.dart'; + +import '../../component/model/search_model.dart'; /// @author wanghongen /// 2023/10/8 diff --git a/lib/ui/desktop/toolbar/toolbar.dart b/lib/ui/desktop/toolbar/toolbar.dart index f118623..0201967 100644 --- a/lib/ui/desktop/toolbar/toolbar.dart +++ b/lib/ui/desktop/toolbar/toolbar.dart @@ -33,9 +33,8 @@ import '../request/list.dart'; class Toolbar extends StatefulWidget { final ProxyServer proxyServer; final GlobalKey requestListStateKey; - final ValueNotifier sideNotifier; - const Toolbar(this.proxyServer, this.requestListStateKey, {super.key, required this.sideNotifier}); + const Toolbar(this.proxyServer, this.requestListStateKey, {super.key}); @override State createState() { @@ -53,7 +52,6 @@ class _ToolbarState extends State { } bool onKeyEvent(KeyEvent event) { - if (HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.escape)) { if (ModalRoute.of(context)?.isCurrent == false) { Navigator.maybePop(context); @@ -82,48 +80,34 @@ class _ToolbarState extends State { @override Widget build(BuildContext context) { - return Row( - children: [ - Padding(padding: EdgeInsets.only(left: Platform.isMacOS ? 80 : 30)), - SocketLaunch(proxyServer: widget.proxyServer, startup: widget.proxyServer.configuration.startup), - const Padding(padding: EdgeInsets.only(left: 18)), - IconButton( - tooltip: localizations.clear, - icon: const Icon(Icons.cleaning_services_outlined, size: 21), - onPressed: () { - widget.requestListStateKey.currentState?.clean(); - }), - const Padding(padding: EdgeInsets.only(left: 18)), - SslWidget(proxyServer: widget.proxyServer), // SSL配置 - const Padding(padding: EdgeInsets.only(left: 18)), - Setting(proxyServer: widget.proxyServer), // 设置 - const Padding(padding: EdgeInsets.only(left: 18)), - IconButton( - tooltip: localizations.mobileConnect, - icon: const Icon(Icons.phone_iphone, size: 21), - onPressed: () async { - final ips = await localIps(readCache: false); - phoneConnect(ips, widget.proxyServer.port); - }), - const Expanded(child: SizedBox()), //自动扩展挤压 - ValueListenableBuilder( - valueListenable: widget.sideNotifier, - builder: (_, sideIndex, __) => IconButton( - icon: Icon(Icons.space_dashboard, size: 20, color: sideIndex >= 0 ? Colors.blueGrey : Colors.grey), - onPressed: () { - if (widget.sideNotifier.value >= 0) { - widget.sideNotifier.value = -1; - } else { - widget.sideNotifier.value = 0; - } - }, - )), //右对齐 - const Padding(padding: EdgeInsets.only(left: 30)), - ], - ); + return Row(children: [ + Padding(padding: EdgeInsets.only(left: Platform.isMacOS ? 80 : 20)), + SocketLaunch(proxyServer: widget.proxyServer, startup: widget.proxyServer.configuration.startup), + const Padding(padding: EdgeInsets.only(left: 18)), + IconButton( + tooltip: localizations.clear, + icon: const Icon(Icons.cleaning_services_outlined, size: 21), + onPressed: () { + widget.requestListStateKey.currentState?.clean(); + }), + const Padding(padding: EdgeInsets.only(left: 18)), + SslWidget(proxyServer: widget.proxyServer), // SSL配置 + const Padding(padding: EdgeInsets.only(left: 18)), + Setting(proxyServer: widget.proxyServer), // 设置 + const Padding(padding: EdgeInsets.only(left: 18)), + IconButton( + tooltip: localizations.mobileConnect, + icon: const Icon(Icons.phone_iphone, size: 21), + onPressed: () async { + final ips = await localIps(readCache: false); + phoneConnect(ips, widget.proxyServer.port); + }), + + const Padding(padding: EdgeInsets.only(left: 30)), + ]); } - phoneConnect(List hosts, int port) { + void phoneConnect(List hosts, int port) { showDialog( context: context, builder: (context) { diff --git a/lib/ui/desktop/widgets/windows_toolbar.dart b/lib/ui/desktop/widgets/windows_toolbar.dart new file mode 100644 index 0000000..0ac65ba --- /dev/null +++ b/lib/ui/desktop/widgets/windows_toolbar.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:window_manager/window_manager.dart'; + +class WindowsToolbar extends StatefulWidget { + final Widget? title; + + const WindowsToolbar({ + super.key, + this.title, + }); + + @override + State createState() => _WindowsToolbarState(); +} + +class _WindowsToolbarState extends State with WindowListener { + @override + void initState() { + windowManager.addListener(this); + super.initState(); + } + + @override + void dispose() { + windowManager.removeListener(this); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Row( + children: [ + SizedBox(width: 7), + Padding( + padding: EdgeInsets.only(top: 2), + child: Center( + child: Image.asset( + 'assets/icon_foreground.png', + width: 32, + ))), + Expanded( + child: DragToMoveArea( + child: widget.title ?? Container(), + )), + WindowCaptionButton.minimize( + brightness: Theme.brightnessOf(context), + onPressed: () async { + bool isMinimized = await windowManager.isMinimized(); + if (isMinimized) { + windowManager.restore(); + } else { + windowManager.minimize(); + } + }), + FutureBuilder( + future: windowManager.isMaximized(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data == true) { + return WindowCaptionButton.unmaximize( + brightness: Theme.brightnessOf(context), + onPressed: () { + windowManager.unmaximize(); + }, + ); + } + return WindowCaptionButton.maximize( + brightness: Theme.brightnessOf(context), + onPressed: () { + windowManager.maximize(); + }, + ); + }), + WindowCaptionButton.close( + brightness: Theme.brightnessOf(context), + onPressed: () { + windowManager.close(); + }), + ], + ); + } + + @override + void onWindowMaximize() { + setState(() {}); + } + + @override + void onWindowUnmaximize() { + setState(() {}); + } +} diff --git a/lib/ui/mobile/request/list.dart b/lib/ui/mobile/request/list.dart index ada3e4d..b3a4f7a 100644 --- a/lib/ui/mobile/request/list.dart +++ b/lib/ui/mobile/request/list.dart @@ -22,7 +22,6 @@ import 'package:proxypin/network/bin/server.dart'; import 'package:proxypin/network/channel/channel.dart'; import 'package:proxypin/network/channel/channel_context.dart'; import 'package:proxypin/network/http/http.dart'; -import 'package:proxypin/ui/desktop/request/model/search_model.dart'; import 'package:proxypin/ui/mobile/request/domians.dart'; import 'package:proxypin/ui/mobile/request/request_sequence.dart'; import 'package:proxypin/utils/har.dart'; @@ -30,6 +29,8 @@ import 'package:proxypin/utils/listenable_list.dart'; import 'package:proxypin/utils/platform.dart'; import 'package:share_plus/share_plus.dart'; +import '../../component/model/search_model.dart'; + /// 请求列表 /// @author wanghongen class RequestListWidget extends StatefulWidget { diff --git a/lib/ui/mobile/request/request_sequence.dart b/lib/ui/mobile/request/request_sequence.dart index 6ad97d0..d377efb 100644 --- a/lib/ui/mobile/request/request_sequence.dart +++ b/lib/ui/mobile/request/request_sequence.dart @@ -3,11 +3,12 @@ import 'dart:collection'; import 'package:flutter/material.dart'; import 'package:proxypin/network/bin/server.dart'; import 'package:proxypin/network/http/http.dart'; -import 'package:proxypin/ui/desktop/request/model/search_model.dart'; import 'package:proxypin/ui/mobile/request/request.dart'; import 'package:proxypin/utils/keyword_highlight.dart'; import 'package:proxypin/utils/listenable_list.dart'; +import '../../component/model/search_model.dart'; + ///请求序列 列表 ///@author wanghongen class RequestSequence extends StatefulWidget { diff --git a/lib/ui/mobile/request/search.dart b/lib/ui/mobile/request/search.dart index c4da396..d31b366 100644 --- a/lib/ui/mobile/request/search.dart +++ b/lib/ui/mobile/request/search.dart @@ -14,8 +14,9 @@ * limitations under the License. */ import 'package:flutter/material.dart'; -import 'package:proxypin/ui/desktop/request/model/search_model.dart'; -import 'package:proxypin/ui/desktop/request/search_condition.dart'; +import 'package:proxypin/ui/component/search_condition.dart'; + +import '../../component/model/search_model.dart'; class MobileSearch extends StatefulWidget { final Function(SearchModel searchModel)? onSearch; diff --git a/lib/ui/toolbox/toolbox.dart b/lib/ui/toolbox/toolbox.dart index 0499739..c6adb06 100644 --- a/lib/ui/toolbox/toolbox.dart +++ b/lib/ui/toolbox/toolbox.dart @@ -99,7 +99,7 @@ class _ToolboxState extends State { child: const Column( children: [Icon(Icons.format_bold_outlined), SizedBox(height: 3), Text('Base64')]), )), - const SizedBox(width: 15), + const SizedBox(width: 10), InkWell( onTap: () => encodeWindow(EncoderType.unicode, context), child: Container( @@ -107,7 +107,7 @@ class _ToolboxState extends State { child: const Column( children: [Icon(Icons.format_underline_outlined), SizedBox(height: 3), Text('Unicode')]), )), - const SizedBox(width: 15), + const SizedBox(width: 10), InkWell( onTap: () => encodeWindow(EncoderType.md5, context), child: Container( @@ -188,7 +188,7 @@ class _ToolboxState extends State { )); } - httpRequest() async { + Future httpRequest() async { if (Platforms.isMobile()) { Navigator.of(context) .push(MaterialPageRoute(builder: (context) => MobileRequestEditor(proxyServer: widget.proxyServer))); diff --git a/pubspec.yaml b/pubspec.yaml index a84b441..6865572 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,4 +64,5 @@ flutter: - assets/certs/ca.crt - assets/certs/ca_key.pem - assets/icon.png + - assets/icon_foreground.png - assets/js/ \ No newline at end of file