├── .editorconfig
├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── .metadata
├── .vscode
└── launch.json
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ ├── libs
│ │ └── .gitkeep
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── cn
│ │ │ │ └── mapleafgo
│ │ │ │ └── clash_for_flutter
│ │ │ │ ├── BaseService.kt
│ │ │ │ ├── ClashService.kt
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── darwer_img.jpg
├── icon.ico
├── icon.png
└── logo_64.png
├── build.yaml
├── distribute_options.yaml
├── docs
├── .nojekyll
├── README.md
├── images
│ ├── connect_page.png
│ ├── home_page.png
│ ├── icon.ico
│ ├── log_page.png
│ ├── profile_page.png
│ ├── proxy_page.png
│ └── settings_page.png
└── index.html
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
├── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
└── RunnerTests
│ └── RunnerTests.swift
├── lib
├── app
│ ├── app_module.dart
│ ├── app_widget.dart
│ ├── bean
│ │ ├── clash_for_me_config_bean.dart
│ │ ├── config_bean.dart
│ │ ├── connection_bean.dart
│ │ ├── group_bean.dart
│ │ ├── history_bean.dart
│ │ ├── log_bean.dart
│ │ ├── net_speed.dart
│ │ ├── profile_base_bean.dart
│ │ ├── profile_file_bean.dart
│ │ ├── profile_url_bean.dart
│ │ ├── provider_bean.dart
│ │ ├── proxies_bean.dart
│ │ ├── proxy_bean.dart
│ │ ├── proxy_providers_bean.dart
│ │ ├── sub_userinfo_bean.dart
│ │ └── tun_bean.dart
│ ├── component
│ │ ├── drawer_component.dart
│ │ ├── loading_component.dart
│ │ └── sys_app_bar.dart
│ ├── enum
│ │ └── type_enum.dart
│ ├── exceptions
│ │ └── message_exception.dart
│ ├── pages
│ │ ├── connections
│ │ │ ├── connection_bean.dart
│ │ │ ├── connections_module.dart
│ │ │ └── connections_page.dart
│ │ ├── home
│ │ │ ├── home_module.dart
│ │ │ └── home_page.dart
│ │ ├── index
│ │ │ ├── index_module.dart
│ │ │ ├── index_page_desktop.dart
│ │ │ ├── index_page_mobile.dart
│ │ │ ├── init_page.dart
│ │ │ └── tray_controller.dart
│ │ ├── logs
│ │ │ ├── logs_module.dart
│ │ │ └── logs_page.dart
│ │ ├── profiles
│ │ │ ├── profile_item.dart
│ │ │ ├── profiles_controller.dart
│ │ │ ├── profiles_module.dart
│ │ │ └── profiles_page.dart
│ │ ├── proxys
│ │ │ ├── model
│ │ │ │ ├── proxie_show_bean.dart
│ │ │ │ ├── proxys_model.dart
│ │ │ │ └── proxys_model.g.dart
│ │ │ ├── proxys_controller.dart
│ │ │ ├── proxys_module.dart
│ │ │ └── proxys_page.dart
│ │ ├── router.dart
│ │ └── settings
│ │ │ ├── settings_module.dart
│ │ │ └── settings_page.dart
│ ├── source
│ │ ├── app_config.dart
│ │ ├── app_config.g.dart
│ │ ├── core_config.dart
│ │ ├── core_config.g.dart
│ │ ├── logs_subscription.dart
│ │ └── request.dart
│ └── utils
│ │ ├── clash_custom_messages.dart
│ │ ├── constants.dart
│ │ └── utils.dart
├── clash_generated_bindings.dart
├── core_control.dart
├── main.dart
└── main.mapper.g.dart
├── linux
├── .gitignore
├── CMakeLists.txt
├── core
│ └── .gitkeep
├── flutter
│ ├── CMakeLists.txt
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugin_registrant.h
│ └── generated_plugins.cmake
├── main.cc
├── my_application.cc
├── my_application.h
└── packaging
│ └── appimage
│ └── make_config.yaml
├── macos
├── .gitignore
├── Flutter
│ ├── Flutter-Debug.xcconfig
│ ├── Flutter-Release.xcconfig
│ └── GeneratedPluginRegistrant.swift
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── app_icon_1024.png
│ │ │ ├── app_icon_128.png
│ │ │ ├── app_icon_16.png
│ │ │ ├── app_icon_256.png
│ │ │ ├── app_icon_32.png
│ │ │ ├── app_icon_512.png
│ │ │ └── app_icon_64.png
│ ├── Base.lproj
│ │ └── MainMenu.xib
│ ├── Configs
│ │ ├── AppInfo.xcconfig
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── Warnings.xcconfig
│ ├── DebugProfile.entitlements
│ ├── Info.plist
│ ├── MainFlutterWindow.swift
│ └── Release.entitlements
└── packaging
│ └── dmg
│ └── make_config.yaml
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
└── windows
├── .gitignore
├── CMakeLists.txt
├── core
└── .gitkeep
├── flutter
├── CMakeLists.txt
├── generated_plugin_registrant.cc
├── generated_plugin_registrant.h
└── generated_plugins.cmake
├── packaging
└── exe
│ └── make_config.yaml
└── runner
├── CMakeLists.txt
├── Runner.rc
├── flutter_window.cpp
├── flutter_window.h
├── main.cpp
├── resource.h
├── resources
└── app_icon.ico
├── runner.exe.manifest
├── utils.cpp
├── utils.h
├── win32_window.cpp
└── win32_window.h
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = true
9 | max_line_length = 120
10 | tab_width = 4
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | build/
34 | core/dist/
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Android Studio will place build artifacts here
43 | /android/app/debug
44 | /android/app/profile
45 | /android/app/release
46 |
47 | /appimage-build/
48 | /AppDir/
49 |
50 | libclash.*
51 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
8 | channel: stable
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
17 | base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
18 | - platform: android
19 | create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
20 | base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
21 | - platform: ios
22 | create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
23 | base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
24 | - platform: linux
25 | create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
26 | base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
27 | - platform: macos
28 | create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
29 | base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
30 | - platform: windows
31 | create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
32 | base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
33 |
34 | # User provided section
35 |
36 | # List of Local paths (relative to this file) that should be
37 | # ignored by the migrate tool.
38 | #
39 | # Files that are not part of the templates will be ignored by default.
40 | unmanaged_files:
41 | - 'lib/main.dart'
42 | - 'ios/Runner.xcodeproj/project.pbxproj'
43 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // 使用 IntelliSense 了解相关属性。
3 | // 悬停以查看现有属性的描述。
4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "clash-for-flutter",
9 | "request": "launch",
10 | "type": "dart"
11 | },
12 | {
13 | "name": "clash-for-flutter (profile mode)",
14 | "request": "launch",
15 | "type": "dart",
16 | "flutterMode": "profile"
17 | },
18 | {
19 | "name": "clash-for-flutter (release mode)",
20 | "request": "launch",
21 | "type": "dart",
22 | "flutterMode": "release"
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 MapLeafGo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Clash for Flutter
2 |
3 | 这是一个 **Clash** 的多平台客户端,支持 windows、linux、macos、android、~~ios~~。
4 |
5 | > [使用说明](https://mapleafgo.github.io/clash-for-flutter)
6 |
7 | ## 界面
8 |
9 | 
10 |
11 | 
12 |
13 | 
14 |
15 | 
16 |
17 | 
18 |
19 | 
20 |
21 | ## 开发、打包说明
22 |
23 | - 基础环境
24 |
25 | `Flutter v3.16+`
26 |
27 | > 对目标平台时,需要参照 Flutter 官方文档进行对应平台的环境搭建。如 Android 开发时,需要 Android-SDK
28 |
29 | > `Linux`环境下 [tray_manager](https://github.com/leanflutter/tray_manager) 需要 `libayatana-appindicator3-dev`
30 |
31 | - 下载内核
32 |
33 | 从 https://github.com/mapleafgo/cff-core/releases/latest 下载对应平台需要的内核,
34 | 然后将解压出来的内核文件移动到对应的路径,各平台路径如下:
35 |
36 | ```shell
37 | # windows
38 | windows/core/libclash.dll
39 | # linux
40 | linux/core/libclash.so
41 | # android
42 | android/app/libs/libclash.aar
43 | # macos
44 | macos/Frameworks/libclash.dylib
45 | # ios
46 | ios/Frameworks/libclash.xcframework
47 | ```
48 |
49 | > 注意:解压出来的文件,仅保留所需的后缀名文件即可,且将其改名为路径的文件名
50 |
51 | > 内核是在 Clash v1.18.0 (非premium) 的基础上进行二次开发的,仅加入了 tun 模式(参照 Meta 进行)
52 |
53 | - 编译项目
54 |
55 | ```shell
56 | # 1. 获取项目依赖
57 | $ flutter pub get
58 | # 2. 生成 .g.dart 文件
59 | $ dart run build_runner build --delete-conflicting-outputs
60 |
61 | # 3. 运行项目 (linux)
62 | $ flutter run -d linux
63 | # 3. 运行项目 (windows)
64 | $ flutter run -d windows
65 | # 3. 运行项目 (android)
66 | $ flutter run -d android
67 | # 3. 运行项目 (macos)
68 | $ flutter run -d macos
69 | ```
70 |
71 | - 打包项目
72 |
73 | 该项目用 [flutter_distributor](https://distributor.leanflutter.org/) 打包,打包步骤看 `flutter_distributor` 的官方文档吧
74 |
75 | ## 主要技术
76 |
77 | - [Go](https://go.dev/)
78 | - [Clash](https://github.com/Dreamacro/clash)
79 | - [Flutter](https://flutter.dev)
80 | - [tray_manager](https://github.com/leanflutter/tray_manager)
81 | - [window_manager](https://github.com/leanflutter/window_manager)
82 | - [proxy_manager](https://github.com/Kingtous/proxy_manager)
83 | - [flutter_modular](https://github.com/Flutterando/modular)
84 | - [dio](https://github.com/cfug/dio)
85 | - [flutter_distributor](https://distributor.leanflutter.org/)
86 |
87 | ## 写在后面
88 |
89 | 自 1.0.0 版本开始,本软件全面从之前的 Go-Flutter 迁移到了官方 Flutter
90 | 版本。迁移中部分参考了 [Fclash](https://github.com/Kingtous/Fclash) 非常感谢!
91 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at
17 | # https://dart-lang.github.io/linter/lints/index.html.
18 | #
19 | # Instead of disabling a lint rule for the entire project in the
20 | # section below, it can also be suppressed for a single line of code
21 | # or a specific dart file by using the `// ignore: name_of_lint` and
22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
23 | # producing the lint.
24 | rules:
25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27 |
28 | # Additional information about this file can be found at
29 | # https://dart.dev/guides/language/analysis-options
30 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | id "dev.flutter.flutter-gradle-plugin"
5 | }
6 |
7 | def localProperties = new Properties()
8 | def localPropertiesFile = rootProject.file('local.properties')
9 | if (localPropertiesFile.exists()) {
10 | localPropertiesFile.withReader('UTF-8') { reader ->
11 | localProperties.load(reader)
12 | }
13 | }
14 |
15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
16 | if (flutterVersionCode == null) {
17 | flutterVersionCode = '1'
18 | }
19 |
20 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
21 | if (flutterVersionName == null) {
22 | flutterVersionName = '1.0'
23 | }
24 |
25 | android {
26 | namespace "cn.mapleafgo.clash_for_flutter"
27 | compileSdkVersion flutter.compileSdkVersion
28 | ndkVersion flutter.ndkVersion
29 |
30 | compileOptions {
31 | sourceCompatibility JavaVersion.VERSION_1_8
32 | targetCompatibility JavaVersion.VERSION_1_8
33 | }
34 |
35 | kotlinOptions {
36 | jvmTarget = '1.8'
37 | }
38 |
39 | sourceSets {
40 | main.java.srcDirs += 'src/main/kotlin'
41 | }
42 |
43 | defaultConfig {
44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45 | applicationId "cn.mapleafgo.clash_for_flutter"
46 | // You can update the following values to match your application needs.
47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
48 | minSdkVersion 29
49 | targetSdkVersion flutter.targetSdkVersion
50 | versionCode flutterVersionCode.toInteger()
51 | versionName flutterVersionName
52 | }
53 |
54 | buildTypes {
55 | release {
56 | // TODO: Add your own signing config for the release build.
57 | // Signing with the debug keys for now, so `flutter run --release` works.
58 | signingConfig signingConfigs.debug
59 | }
60 | }
61 | }
62 |
63 | flutter {
64 | source '../..'
65 | }
66 |
67 | dependencies {
68 | implementation files('libs/libclash.aar')
69 | }
70 |
--------------------------------------------------------------------------------
/android/app/libs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/android/app/libs/.gitkeep
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
18 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
43 |
44 |
45 |
46 |
47 |
49 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/cn/mapleafgo/clash_for_flutter/BaseService.kt:
--------------------------------------------------------------------------------
1 | package cn.mapleafgo.clash_for_flutter
2 |
3 | import android.app.NotificationChannel
4 | import android.app.NotificationManager
5 | import android.app.Service
6 | import android.content.Intent
7 | import android.net.VpnService
8 | import android.os.Binder
9 | import android.os.IBinder
10 | import android.os.ParcelFileDescriptor
11 | import androidx.core.app.NotificationCompat
12 |
13 | open class BaseService : VpnService() {
14 | companion object {
15 | val ACTION_CONNECT = "cn.mapleafgo.clash_for_flutter.START"
16 | val ACTION_CLASH = "cn.mapleafgo.clash_for_flutter.CLASH"
17 | val ACTION_DISCONNECT = "cn.mapleafgo.clash_for_flutter.STOP"
18 | }
19 |
20 | private val binder = BaseBinder()
21 |
22 | private val notifyID = 1
23 | private val notifyChannelID = "vpn"
24 | private val notifyChannelName = "VPN服务状态"
25 | private var notificationManager: NotificationManager? = null
26 |
27 | override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
28 | return START_NOT_STICKY
29 | }
30 |
31 | inner class BaseBinder : Binder() {
32 | fun getService(): BaseService = this@BaseService
33 | }
34 |
35 | override fun onBind(intent: Intent?): IBinder? {
36 | return binder
37 | }
38 |
39 | protected fun startForeground() {
40 | notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
41 |
42 | val channel = NotificationChannel(notifyChannelID, notifyChannelName, NotificationManager.IMPORTANCE_DEFAULT)
43 | notificationManager?.createNotificationChannel(channel)
44 |
45 | val notification = NotificationCompat.Builder(this, notifyChannelID)
46 | .setSmallIcon(R.mipmap.ic_launcher)
47 | .setContentTitle("Clash for Flutter")
48 | .setContentText("已在后台启动服务")
49 | .setPriority(NotificationCompat.PRIORITY_DEFAULT)
50 | .build()
51 | startForeground(notifyID, notification)
52 | }
53 |
54 | open fun setupVpnServe() {
55 | throw RuntimeException("Stub!")
56 | }
57 |
58 | open fun setupClashServe(): Boolean {
59 | throw RuntimeException("Stub!")
60 | }
61 |
62 | open fun closeVpnService() {
63 | notificationManager?.cancel(notifyID)
64 | }
65 |
66 | override fun onDestroy() {
67 | closeVpnService()
68 | }
69 |
70 | override fun onRevoke() {
71 | closeVpnService()
72 | }
73 | }
74 |
75 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/cn/mapleafgo/clash_for_flutter/ClashService.kt:
--------------------------------------------------------------------------------
1 | package cn.mapleafgo.clash_for_flutter
2 |
3 | import android.app.Service
4 | import android.os.ParcelFileDescriptor
5 | import android.util.Log
6 | import cn.mapleafgo.mobile.Mobile
7 |
8 | class ClashService : BaseService() {
9 | private var tun: ParcelFileDescriptor? = null
10 | private var mtu = 1500
11 | private var isRunning = false
12 |
13 | private fun setupTun() {
14 | tun = Builder()
15 | .setMtu(mtu)
16 | .addDnsServer("8.8.8.8")
17 | .addDnsServer("114.114.114.114")
18 | .addRoute("0.0.0.0", 0)
19 | .addAddress("198.18.0.1", 30)
20 | .addDisallowedApplication(packageName)
21 | .establish() ?: throw Exception("启动隧道失败")
22 | }
23 |
24 | override fun setupVpnServe() {
25 | setupTun()
26 | Mobile.operateTun(true, tun?.detachFd()!!, mtu)
27 | Log.i("ClashService", "开启VPN服务")
28 | startForeground()
29 | }
30 |
31 | override fun closeVpnService() {
32 | Mobile.operateTun(false, 0, 0)
33 | tun?.close()
34 | stopForeground(Service.STOP_FOREGROUND_REMOVE)
35 | Log.i("ClashService", "停止VPN服务")
36 | super.closeVpnService()
37 | }
38 |
39 | override fun setupClashServe(): Boolean {
40 | if (!isRunning) {
41 | isRunning = Mobile.startService()
42 | Log.i("ClashService", "开启Clash服务状态: $isRunning")
43 | }
44 | return isRunning
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/cn/mapleafgo/clash_for_flutter/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package cn.mapleafgo.clash_for_flutter
2 |
3 | import android.content.ComponentName
4 | import android.content.Intent
5 | import android.content.ServiceConnection
6 | import android.net.VpnService
7 | import android.os.Bundle
8 | import android.os.IBinder
9 | import cn.mapleafgo.mobile.Mobile
10 | import io.flutter.embedding.android.FlutterActivity
11 | import io.flutter.plugin.common.MethodChannel
12 |
13 | class MainActivity : FlutterActivity() {
14 | private val CHANNEL = "cn.mapleafgo/socks_vpn_plugin"
15 | private val REQUEST_CODE = 0
16 |
17 | private lateinit var cService: BaseService
18 | private var cBound: Boolean = false
19 |
20 | private val connection = object : ServiceConnection {
21 | override fun onServiceConnected(className: ComponentName, service: IBinder) {
22 | val binder = service as BaseService.BaseBinder
23 | cService = binder.getService()
24 | cBound = true
25 | }
26 |
27 | override fun onServiceDisconnected(arg0: ComponentName) {
28 | cBound = false
29 | }
30 | }
31 |
32 | override fun onCreate(savedInstanceState: Bundle?) {
33 | super.onCreate(savedInstanceState)
34 | Intent(this, ClashService::class.java).also { intent -> bindService(intent, connection, BIND_AUTO_CREATE) }
35 | MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
36 | when (call.method) {
37 | "startVpn" -> {
38 | val intent = VpnService.prepare(this)
39 | if (intent != null) {
40 | startActivityForResult(intent, REQUEST_CODE);
41 | result.success(false)
42 | } else {
43 | onActivityResult(REQUEST_CODE, RESULT_OK, null);
44 | result.success(true)
45 | }
46 | }
47 |
48 | "stopVpn" -> {
49 | if (cBound) {
50 | cService.closeVpnService()
51 | }
52 | result.success(cBound)
53 | }
54 |
55 | "startService" -> {
56 | if (cBound) {
57 | val b = cService.setupClashServe()
58 | result.success(b)
59 | } else {
60 | result.success(cBound)
61 | }
62 | }
63 |
64 | "setConfig" -> {
65 | val config = call.argument("config")
66 | result.success(Mobile.setConfig(config))
67 | }
68 |
69 | "setHomeDir" -> {
70 | val dir = call.argument("dir")
71 | result.success(Mobile.setHomeDir(dir))
72 | }
73 |
74 | "startRust" -> {
75 | val addr = call.argument("addr")
76 | result.success(Mobile.startRust(addr))
77 | }
78 |
79 | "verifyMMDB" -> {
80 | val path = call.argument("path")
81 | result.success(Mobile.verifyMMDB(path))
82 | }
83 |
84 | else -> {
85 | result.notImplemented()
86 | }
87 | }
88 | }
89 | }
90 |
91 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
92 | super.onActivityResult(requestCode, resultCode, data)
93 | if (requestCode == REQUEST_CODE && resultCode == RESULT_OK && cBound) {
94 | cService.setupVpnServe()
95 | }
96 | }
97 |
98 | override fun onDestroy() {
99 | super.onDestroy()
100 | unbindService(connection)
101 | cBound = false
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.7.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
10 | }
11 | }
12 |
13 | allprojects {
14 | repositories {
15 | google()
16 | mavenCentral()
17 | }
18 | }
19 |
20 | rootProject.buildDir = '../build'
21 | subprojects {
22 | project.buildDir = "${rootProject.buildDir}/${project.name}"
23 | }
24 | subprojects {
25 | project.evaluationDependsOn(':app')
26 | }
27 |
28 | tasks.register("clean", Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
6 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }
9 | settings.ext.flutterSdkPath = flutterSdkPath()
10 |
11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
12 |
13 | repositories {
14 | google()
15 | mavenCentral()
16 | gradlePluginPortal()
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
21 | }
22 | }
23 |
24 | plugins {
25 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
26 | id "com.android.application" version '7.4.2' apply false
27 | }
28 |
29 | include ":app"
30 |
--------------------------------------------------------------------------------
/assets/darwer_img.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/assets/darwer_img.jpg
--------------------------------------------------------------------------------
/assets/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/assets/icon.ico
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/assets/icon.png
--------------------------------------------------------------------------------
/assets/logo_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/assets/logo_64.png
--------------------------------------------------------------------------------
/build.yaml:
--------------------------------------------------------------------------------
1 | targets:
2 | $default:
3 | builders:
4 | dart_json_mapper:
5 | generate_for:
6 | - lib/main.dart
7 |
8 | # This part is needed to tell original reflectable builder to stay away
9 | # it overrides default options for reflectable builder to an **empty** set of files
10 | reflectable:
11 | generate_for:
12 | - no/files
13 |
--------------------------------------------------------------------------------
/distribute_options.yaml:
--------------------------------------------------------------------------------
1 | output: dist/
2 | releases:
3 | - name: windows-dev
4 | jobs:
5 | - name: release-dev-windows
6 | package:
7 | platform: windows
8 | target: exe
9 | publish:
10 | target: github
11 | args:
12 | repo-owner: mapleafgo
13 | repo-name: clash-for-flutter
14 | - name: linux-dev
15 | jobs:
16 | - name: release-dev-linux
17 | package:
18 | platform: linux
19 | target: appimage
20 | publish:
21 | target: github
22 | args:
23 | repo-owner: mapleafgo
24 | repo-name: clash-for-flutter
25 | - name: macos-dev
26 | jobs:
27 | - name: release-dev-macos
28 | package:
29 | platform: macos
30 | target: dmg
31 | publish:
32 | target: github
33 | args:
34 | repo-owner: mapleafgo
35 | repo-name: clash-for-flutter
36 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Clash for Flutter
2 |
3 | > 该软件是 Clash 的多平台端实现,使用[Flutter](https://flutter.dev/)开发。支持 Windows、Linux、MacOS、Android、~~IOS~~
4 |
5 | ### 下载
6 |
7 | 当前下载页面都只提供了 64 位的安装包[releases](https://github.com/mapleafgo/clash-for-flutter/releases/latest)
8 | ,由于当前是我自己手动在各个平台打包,所以做不到每个版本都提供的了安装包
9 |
10 | - Linux:
11 |
12 | linux 安装包目前打包的为`appimage`的,这种包各个发行版都能直接使用
13 |
14 | - Windows:
15 |
16 | windows 提供的是`msi`包
17 |
18 | - MacOS:
19 |
20 | macos 提供的是`dmg`包
21 |
22 | ### 开始使用
23 |
24 | 该软件目前主要操作就三个,订阅、开启代理、切换代理节点。如下
25 |
26 | - #### 订阅
27 |
28 | 订阅页可以说是一切的源头,因为所有的代理节点地址都得通过订阅获取。
29 |
30 | 
31 |
32 | 这是已有订阅的界面,**在没有订阅或未选择订阅时是无法开启代理的**,添加订阅只需点击右下角的`+`
33 | 按钮。在弹出的窗口中输入订阅地址或选择本地文件
34 |
35 | > 需要说明的是,当前**暂时不未支持自动更新订阅**,需手动在此页更新订阅
36 |
37 | - #### 开启代理
38 |
39 | 在已选择订阅的情况下,只需在本页点击开启即可。
40 |
41 | 
42 |
43 | > 当前代理使用的是 PAC 自动设置代理的方式,在各平台通用。这种方式有一定的局限性,因为不是所有程序都会走代理,浏览器是没问题
44 |
45 | - #### 切换代理节点
46 |
47 | 
48 |
49 | 此页就是最常用的页面了,经常使用的 **切换节点、测延迟(右下角按钮)** 都在此页。
50 |
51 | 可能很多人对页面头的几个列表有疑问,这个的话,是订阅配置带过来的。是 Clash 的代理组,它是与规则搭配使用,可以做到对每个
52 | IP、每个地址进行代理配置,具体可查看[Clash 的文档](https://github.com/Dreamacro/clash/wiki/configuration#proxy-groups)
53 | 。这个功能我们软件当前不负责维护,只提供基本的节点切换
54 |
55 | - #### 设置
56 |
57 | 
58 |
59 | 设置页主要提供切换端口、和几个 Clash 的设置,后期可能会加入软件的一些功能
60 |
61 | - 代理端口
62 |
63 | 对于代理端口,默认为 7890 (设置为 0 表示不开启)
64 |
65 | 至于 Redir 和 Tproxy 的代理,目前我没用到过,都是默认为 0 的状态,这里就引入 Clash 官方的话来解释这两个吧
66 | ```yaml
67 | # Transparent proxy server port for Linux and macOS (Redirect TCP and TProxy UDP)
68 | redir-port: 7892
69 |
70 | # Transparent proxy server port for Linux (TProxy TCP and TProxy UDP)
71 | tproxy-port: 7893
72 | ```
73 |
74 | - 允许局域网访问
75 |
76 | 这个可以让服务暴露在局域网中,局域网中的其它设备可以接入当前的代理
77 |
78 | - IPv6
79 |
80 | 开启 IPv6 的支持
81 |
82 | ```yaml
83 | # 代理模式
84 | # rule: rule-based packet routing
85 | # global: all packets will be forwarded to a single endpoint
86 | # direct: directly forward the packets to the Internet
87 | mode: rule
88 |
89 | # 输出日志等级
90 | # info / warning / error / debug / silent
91 | log-level: info
92 | ```
93 |
--------------------------------------------------------------------------------
/docs/images/connect_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/docs/images/connect_page.png
--------------------------------------------------------------------------------
/docs/images/home_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/docs/images/home_page.png
--------------------------------------------------------------------------------
/docs/images/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/docs/images/icon.ico
--------------------------------------------------------------------------------
/docs/images/log_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/docs/images/log_page.png
--------------------------------------------------------------------------------
/docs/images/profile_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/docs/images/profile_page.png
--------------------------------------------------------------------------------
/docs/images/proxy_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/docs/images/proxy_page.png
--------------------------------------------------------------------------------
/docs/images/settings_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/docs/images/settings_page.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Clash for Flutter
6 |
7 |
8 |
12 |
13 |
17 |
18 |
19 |
20 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mapleafgo/clash-for-flutter/3313fa4936202219af63f5fb04b299c33fc86d25/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Clash for Flutter
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | clash_for_flutter
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | CFBundleURLTypes
32 |
33 |
34 | CFBundleTypeRole
35 | Editor
36 | CFBundleURLName
37 |
38 | CFBundleURLSchemes
39 |
40 | clash
41 |
42 |
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UISupportedInterfaceOrientations~ipad
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationPortraitUpsideDown
54 | UIInterfaceOrientationLandscapeLeft
55 | UIInterfaceOrientationLandscapeRight
56 |
57 | CADisableMinimumFrameDurationOnPhone
58 |
59 | UIApplicationSupportsIndirectInputEvents
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/lib/app/app_module.dart:
--------------------------------------------------------------------------------
1 | import 'package:clash_for_flutter/app/pages/index/index_module.dart';
2 | import 'package:clash_for_flutter/app/source/app_config.dart';
3 | import 'package:clash_for_flutter/app/source/core_config.dart';
4 | import 'package:clash_for_flutter/app/source/logs_subscription.dart';
5 | import 'package:clash_for_flutter/app/source/request.dart';
6 | import 'package:flutter_modular/flutter_modular.dart';
7 |
8 | class AppModule extends Module {
9 | @override
10 | void binds(i) {
11 | i.addSingleton(Request.new);
12 | i.addSingleton(LogsSubscription.new);
13 | i.addSingleton(AppConfig.new);
14 | i.addSingleton(CoreConfig.new);
15 | }
16 |
17 | @override
18 | void routes(r) {
19 | r.module("/", module: IndexModule());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/app/app_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:asuka/asuka.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_localizations/flutter_localizations.dart';
4 | import 'package:flutter_modular/flutter_modular.dart';
5 |
6 | class AppWidget extends StatefulWidget {
7 | const AppWidget({super.key});
8 |
9 | @override
10 | State createState() => _AppWidgetState();
11 | }
12 |
13 | class _AppWidgetState extends State {
14 | @override
15 | Widget build(BuildContext context) {
16 | var app = MaterialApp.router(
17 | title: "Clash for Flutter",
18 | localizationsDelegates: GlobalMaterialLocalizations.delegates,
19 | supportedLocales: const [Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: "CN")],
20 | locale: const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: "CN"),
21 | theme: ThemeData(
22 | useMaterial3: true,
23 | primarySwatch: Colors.blue,
24 | ),
25 | routerConfig: Modular.routerConfig,
26 | builder: Asuka.builder,
27 | // navigatorObservers: [Asuka.asukaHeroController],
28 | );
29 | Modular.setObservers([Asuka.asukaHeroController]);
30 | return app;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/app/bean/clash_for_me_config_bean.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'dart:io';
3 |
4 | import 'package:clash_for_flutter/app/bean/profile_base_bean.dart';
5 | import 'package:clash_for_flutter/app/utils/constants.dart';
6 | import 'package:dart_json_mapper/dart_json_mapper.dart';
7 |
8 | /// 软件配置
9 | @JsonSerializable()
10 | class ClashForMeConfig {
11 | static final File _file = File("${Constants.homeDir.path}${Constants.clashForMe}");
12 |
13 | /// 选择的配置文件
14 | @JsonProperty(name: "selected-file")
15 | String? selectedFile;
16 |
17 | /// 源配置
18 | List profiles;
19 |
20 | /// mmdb 下载地址
21 | @JsonProperty(name: "mmdb-url")
22 | String mmdbUrl;
23 |
24 | /// 延迟测试地址
25 | @JsonProperty(name: "delay-test-url")
26 | String delayTestUrl;
27 |
28 | /// 是否以 Tun 模式运行
29 | @JsonProperty(name: "tun-if")
30 | bool? tunIf;
31 |
32 | ClashForMeConfig({
33 | this.selectedFile,
34 | required this.profiles,
35 | required this.mmdbUrl,
36 | required this.delayTestUrl,
37 | this.tunIf,
38 | });
39 |
40 | ClashForMeConfig copyWith({
41 | String? selectedFile,
42 | List? profiles,
43 | String? mmdbUrl,
44 | String? delayTestUrl,
45 | bool? tunIf,
46 | }) {
47 | var config = ClashForMeConfig(
48 | selectedFile: selectedFile ?? this.selectedFile,
49 | profiles: profiles ?? this.profiles,
50 | mmdbUrl: mmdbUrl ?? this.mmdbUrl,
51 | delayTestUrl: delayTestUrl ?? this.delayTestUrl,
52 | tunIf: tunIf ?? this.tunIf,
53 | );
54 | // 对当前选择的订阅进行优化
55 | var selectElements = config.profiles.where((e) => e.file == config.selectedFile);
56 | if (selectElements.isEmpty) {
57 | if (config.profiles.isEmpty) {
58 | config.selectedFile = null;
59 | } else {
60 | config.selectedFile = config.profiles.first.file;
61 | }
62 | }
63 | return config;
64 | }
65 |
66 | Future saveFile() {
67 | return _file.create(recursive: true).then((file) => file.writeAsString(JsonMapper.serialize(this)));
68 | }
69 |
70 | factory ClashForMeConfig.defaultConfig() => ClashForMeConfig(
71 | profiles: [],
72 | mmdbUrl: DefaultConfigValue.mmdbUrl,
73 | delayTestUrl: DefaultConfigValue.delayTestUrl,
74 | );
75 |
76 | factory ClashForMeConfig.formFile() {
77 | var clashForMeFile = _file;
78 | if (clashForMeFile.existsSync()) {
79 | Map cfm = json.decode(clashForMeFile.readAsStringSync());
80 |
81 | // 对必填项赋予默认值
82 | cfm.putIfAbsent("mmdb-url", () => DefaultConfigValue.mmdbUrl);
83 | cfm.putIfAbsent("delay-test-url", () => DefaultConfigValue.delayTestUrl);
84 |
85 | return JsonMapper.fromMap(cfm)!;
86 | }
87 | return ClashForMeConfig.defaultConfig();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/lib/app/bean/config_bean.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:clash_for_flutter/app/bean/tun_bean.dart';
4 | import 'package:clash_for_flutter/app/enum/type_enum.dart';
5 | import 'package:clash_for_flutter/app/utils/constants.dart';
6 | import 'package:dart_json_mapper/dart_json_mapper.dart';
7 | import 'package:settings_yaml/settings_yaml.dart';
8 |
9 | @JsonSerializable()
10 | class Config {
11 | static final String _path = "${Constants.homeDir.path}${Constants.clashConfig}";
12 |
13 | @JsonProperty(name: "mixed-port")
14 | int? mixedPort;
15 | @JsonProperty(name: "redir-port")
16 | int? redirPort;
17 | @JsonProperty(name: "tproxy-port")
18 | int? tproxyPort;
19 | @JsonProperty(name: "allow-lan")
20 | bool? allowLan;
21 | @JsonProperty(name: "mode")
22 | Mode? mode;
23 | @JsonProperty(name: "log-level")
24 | LogLevel? logLevel;
25 | @JsonProperty(name: "ipv6")
26 | bool? ipv6;
27 | @JsonProperty(name: "tun")
28 | Tun? tun;
29 |
30 | get tunEnable => tun?.enable;
31 |
32 | Config({
33 | this.mixedPort,
34 | this.redirPort,
35 | this.tproxyPort,
36 | this.allowLan,
37 | this.mode,
38 | this.logLevel,
39 | this.ipv6,
40 | this.tun,
41 | });
42 |
43 | Future saveFile() {
44 | var yaml = SettingsYaml.load(pathToSettings: _path);
45 | if (redirPort != null) (yaml["redir-port"] = redirPort);
46 | if (tproxyPort != null) (yaml["tproxy-port"] = tproxyPort);
47 | if (mixedPort != null) (yaml["mixed-port"] = mixedPort);
48 | if (allowLan != null) (yaml["allow-lan"] = allowLan);
49 | if (mode != null) (yaml["mode"] = mode?.value);
50 | if (logLevel != null) (yaml["log-level"] = logLevel?.value);
51 | if (ipv6 != null) (yaml["ipv6"] = ipv6);
52 | return yaml.save();
53 | }
54 |
55 | Config copyWith({
56 | int? redirPort,
57 | int? tproxyPort,
58 | int? mixedPort,
59 | bool? allowLan,
60 | Mode? mode,
61 | LogLevel? logLevel,
62 | bool? ipv6,
63 | }) {
64 | return Config(
65 | redirPort: redirPort ?? this.redirPort,
66 | tproxyPort: tproxyPort ?? this.tproxyPort,
67 | mixedPort: mixedPort ?? this.mixedPort,
68 | allowLan: allowLan ?? this.allowLan,
69 | mode: mode ?? this.mode,
70 | logLevel: logLevel ?? this.logLevel,
71 | ipv6: ipv6 ?? this.ipv6,
72 | );
73 | }
74 |
75 | Config copy(Config? that) {
76 | that ??= this;
77 | return Config(
78 | redirPort: that.redirPort,
79 | tproxyPort: that.tproxyPort,
80 | mixedPort: that.mixedPort,
81 | allowLan: that.allowLan,
82 | mode: that.mode,
83 | logLevel: that.logLevel,
84 | ipv6: that.ipv6,
85 | tun: that.tun,
86 | );
87 | }
88 |
89 | static bool? fileExist() => File(_path).existsSync();
90 |
91 | factory Config.defaultConfig() => Config(mixedPort: 7890);
92 | }
93 |
--------------------------------------------------------------------------------
/lib/app/bean/connection_bean.dart:
--------------------------------------------------------------------------------
1 | import 'package:dart_json_mapper/dart_json_mapper.dart';
2 |
3 | @JsonSerializable()
4 | class Connection {
5 | String id;
6 | int upload;
7 | int download;
8 | String start;
9 | List chains;
10 | String rule;
11 | String rulePayload;
12 | Metadata metadata;
13 |
14 | Connection({
15 | required this.id,
16 | required this.upload,
17 | required this.download,
18 | required this.start,
19 | required this.chains,
20 | required this.rule,
21 | required this.rulePayload,
22 | required this.metadata,
23 | });
24 |
25 | Connection.empty()
26 | : this(
27 | id: "",
28 | upload: 0,
29 | download: 0,
30 | start: "",
31 | chains: [],
32 | rule: "",
33 | rulePayload: "",
34 | metadata: Metadata(
35 | network: "",
36 | type: "",
37 | host: "",
38 | processPath: "",
39 | sourceIP: "",
40 | sourcePort: "",
41 | destinationIP: "",
42 | destinationPort: "",
43 | dnsMode: "",
44 | specialProxy: "",
45 | ),
46 | );
47 | }
48 |
49 | @JsonSerializable()
50 | class Metadata {
51 | String network;
52 | String type;
53 | String host;
54 | String processPath;
55 | String sourceIP;
56 | String sourcePort;
57 | String destinationIP;
58 | String destinationPort;
59 | String dnsMode;
60 | String specialProxy;
61 |
62 | Metadata({
63 | required this.network,
64 | required this.type,
65 | required this.host,
66 | required this.processPath,
67 | required this.sourceIP,
68 | required this.sourcePort,
69 | required this.destinationIP,
70 | required this.destinationPort,
71 | required this.dnsMode,
72 | required this.specialProxy,
73 | });
74 | }
75 |
76 | @JsonSerializable()
77 | class Snapshot {
78 | int uploadTotal;
79 | int downloadTotal;
80 | List connections;
81 |
82 | Snapshot({
83 | required this.uploadTotal,
84 | required this.downloadTotal,
85 | required this.connections,
86 | });
87 |
88 | Snapshot.empty() : this(uploadTotal: 0, downloadTotal: 0, connections: []);
89 | }
90 |
--------------------------------------------------------------------------------
/lib/app/bean/group_bean.dart:
--------------------------------------------------------------------------------
1 | import 'package:clash_for_flutter/app/bean/history_bean.dart';
2 | import 'package:dart_json_mapper/dart_json_mapper.dart';
3 | import '../enum/type_enum.dart';
4 |
5 | /// 分组代理项
6 | @JsonSerializable()
7 | class Group {
8 | String name;
9 | GroupType type;
10 | List all;
11 | String now;
12 | List? history;
13 |
14 | Group({
15 | required this.name,
16 | required this.type,
17 | required this.all,
18 | required this.now,
19 | });
20 | }
21 |
--------------------------------------------------------------------------------
/lib/app/bean/history_bean.dart:
--------------------------------------------------------------------------------
1 | import 'package:dart_json_mapper/dart_json_mapper.dart';
2 |
3 | @JsonSerializable()
4 | class History {
5 | String time;
6 | int delay;
7 |
8 | History({required this.time, required this.delay});
9 | }
10 |
--------------------------------------------------------------------------------
/lib/app/bean/log_bean.dart:
--------------------------------------------------------------------------------
1 | import 'package:clash_for_flutter/app/enum/type_enum.dart';
2 | import 'package:dart_json_mapper/dart_json_mapper.dart';
3 |
4 | @JsonSerializable()
5 | class LogData {
6 | DateTime? time;
7 | LogLevel type;
8 | String payload;
9 |
10 | LogData({
11 | this.time,
12 | required this.type,
13 | required this.payload,
14 | });
15 | }
16 |
--------------------------------------------------------------------------------
/lib/app/bean/net_speed.dart:
--------------------------------------------------------------------------------
1 | import 'package:dart_json_mapper/dart_json_mapper.dart';
2 |
3 | @JsonSerializable()
4 | class NetSpeed {
5 | int up = 0;
6 | int down = 0;
7 | }
8 |
--------------------------------------------------------------------------------
/lib/app/bean/profile_base_bean.dart:
--------------------------------------------------------------------------------
1 | import 'package:clash_for_flutter/app/enum/type_enum.dart';
2 | import 'package:dart_json_mapper/dart_json_mapper.dart';
3 |
4 | /// 配置基本参数
5 | @JsonSerializable()
6 | @Json(discriminatorProperty: 'type')
7 | abstract class ProfileBase {
8 | /// 保存的文件名
9 | String file;
10 |
11 | /// 名称
12 | String name;
13 |
14 | /// 配置类型
15 | ProfileType type;
16 |
17 | /// 更新的时间
18 | DateTime time;
19 |
20 | ProfileBase({
21 | required this.name,
22 | required this.file,
23 | required this.type,
24 | required this.time,
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/lib/app/bean/profile_file_bean.dart:
--------------------------------------------------------------------------------
1 | import 'package:clash_for_flutter/app/bean/profile_base_bean.dart';
2 | import 'package:clash_for_flutter/app/enum/type_enum.dart';
3 | import 'package:dart_json_mapper/dart_json_mapper.dart';
4 |
5 | /// 配置(文件)
6 | @JsonSerializable()
7 | @Json(discriminatorValue: ProfileType.FILE)
8 | class ProfileFile extends ProfileBase {
9 | /// 链接地址
10 | String? path;
11 |
12 | ProfileFile({
13 | required super.file,
14 | required super.name,
15 | required super.time,
16 | this.path,
17 | }) : super(type: ProfileType.FILE);
18 |
19 | factory ProfileFile.defaultBean({
20 | required String file,
21 | required String name,
22 | required DateTime time,
23 | }) =>
24 | ProfileFile(file: file, name: name, time: time);
25 |
26 | factory ProfileFile.emptyBean() =>
27 | ProfileFile(file: "", name: "", time: DateTime.now());
28 | }
29 |
--------------------------------------------------------------------------------
/lib/app/bean/profile_url_bean.dart:
--------------------------------------------------------------------------------
1 | import 'package:clash_for_flutter/app/bean/profile_base_bean.dart';
2 | import 'package:clash_for_flutter/app/bean/sub_userinfo_bean.dart';
3 | import 'package:clash_for_flutter/app/enum/type_enum.dart';
4 | import 'package:dart_json_mapper/dart_json_mapper.dart';
5 |
6 | /// 配置(URL)
7 | @JsonSerializable()
8 | @Json(discriminatorValue: ProfileType.URL)
9 | class ProfileURL extends ProfileBase {
10 | /// 链接地址
11 | String url;
12 |
13 | /// 更新间隔(h)
14 | int interval;
15 |
16 | @JsonProperty(name: "sub-userinfo")
17 | SubUserinfo? userinfo;
18 |
19 | ProfileURL({
20 | required super.file,
21 | required super.name,
22 | required super.time,
23 | required this.url,
24 | required this.interval,
25 | this.userinfo,
26 | }) : super(type: ProfileType.URL);
27 |
28 | factory ProfileURL.defaultBean({
29 | required String url,
30 | required String file,
31 | required String name,
32 | required DateTime time,
33 | }) =>
34 | ProfileURL(url: url, file: file, name: name, time: time, interval: 0);
35 |
36 | factory ProfileURL.emptyBean() => ProfileURL(
37 | url: "", file: "", name: "", time: DateTime.now(), interval: 0);
38 | }
39 |
--------------------------------------------------------------------------------
/lib/app/bean/provider_bean.dart:
--------------------------------------------------------------------------------
1 | import 'package:clash_for_flutter/app/enum/type_enum.dart';
2 | import 'package:dart_json_mapper/dart_json_mapper.dart';
3 | import 'group_bean.dart';
4 | import 'proxy_bean.dart';
5 |
6 | @JsonSerializable()
7 | class Provider {
8 | String name;
9 | @JsonProperty(converter: ProviderProxiesConverter())
10 | List proxies;
11 | String type;
12 | VehicleType vehicleType;
13 | String? updatedAt;
14 |
15 | Provider({
16 | required this.name,
17 | required this.proxies,
18 | required this.type,
19 | required this.vehicleType,
20 | this.updatedAt,
21 | });
22 | }
23 |
24 | class ProviderProxiesConverter implements ICustomConverter> {
25 | const ProviderProxiesConverter() : super();
26 |
27 | @override
28 | List fromJSON(jsonValue, [DeserializationContext? context]) {
29 | return jsonValue
30 | .map(
31 | (e) => GroupTypeValue.valueList.contains(e["type"])
32 | ? JsonMapper.fromMap(e)
33 | : JsonMapper.fromMap(e),
34 | )
35 | .toList();
36 | }
37 |
38 | @override
39 | toJSON(List object, [SerializationContext? context]) {
40 | return object.map((e) => e.toJson()).toList();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/app/bean/proxies_bean.dart:
--------------------------------------------------------------------------------
1 | import '../enum/type_enum.dart';
2 | import 'package:dart_json_mapper/dart_json_mapper.dart';
3 |
4 | import 'group_bean.dart';
5 | import 'proxy_bean.dart';
6 |
7 | @JsonSerializable()
8 | class Proxies {
9 | @JsonProperty(converter: ProxiesConverter())
10 | Map proxies;
11 |
12 | Proxies({required this.proxies});
13 | }
14 |
15 | class ProxiesConverter implements ICustomConverter