Fix macos performance issue
Support custom global-ua Update core Optimize some details
@@ -0,0 +1,28 @@
|
|||||||
|
# Agent Configuration Model
|
||||||
|
|
||||||
|
Use the smallest durable surface that matches the job.
|
||||||
|
|
||||||
|
## Surfaces
|
||||||
|
|
||||||
|
- `AGENTS.md`: auto-loaded repository entry point. Keep it small and reserve it for always-on rules, routing, and high-priority expectations.
|
||||||
|
- `.agents/*.md`: human- and agent-readable reference docs linked from `AGENTS.md`. Use these for detailed project context, commands, architecture, and conventions.
|
||||||
|
- `.agents/skills/*/SKILL.md`: repo-scoped Codex skills. Use these for repeatable workflows that should be discoverable by name and description.
|
||||||
|
- `.codex/config.toml`: trusted project Codex settings such as MCP, hooks, sandbox, approval, or model defaults.
|
||||||
|
- `.codex/rules/*.rules`: command permission rules for running commands outside the sandbox. Do not mix these with coding conventions in `.agents/rules.md`.
|
||||||
|
- `.codex/hooks.json` or `.codex/config.toml` hooks: lifecycle automation such as prompt checks, command validation, or final verification gates.
|
||||||
|
|
||||||
|
## Placement Rules
|
||||||
|
|
||||||
|
- Put stable team conventions in `AGENTS.md` only when every task must see them without opening another file.
|
||||||
|
- Put detailed explanations in `.agents/*.md` and link them from `AGENTS.md`.
|
||||||
|
- Put reusable task workflows in `.agents/skills/<skill-name>/SKILL.md`.
|
||||||
|
- Put mechanical enforcement in linters, tests, hooks, or `.codex/rules`; do not rely on prose when tooling can enforce the rule.
|
||||||
|
- Keep user-specific preferences out of the repository. They belong in user-level Codex configuration or user-level skills.
|
||||||
|
|
||||||
|
## Skill Authoring Rules
|
||||||
|
|
||||||
|
- Use lowercase hyphenated names.
|
||||||
|
- Start descriptions with `Use when...`.
|
||||||
|
- Describe trigger conditions in the description, not the workflow.
|
||||||
|
- Keep `SKILL.md` lean; link to `.agents/*.md` for large reference material.
|
||||||
|
- Add scripts only when deterministic behavior is needed repeatedly.
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
# Architecture
|
||||||
|
|
||||||
|
## Core Integration
|
||||||
|
|
||||||
|
The Go proxy core in `core/` operates in two modes.
|
||||||
|
|
||||||
|
Android lib mode:
|
||||||
|
|
||||||
|
- Go core is compiled as a C shared library, `libclash.so`, through `go build -buildmode=c-shared` with CGO.
|
||||||
|
- Flutter calls it via FFI through the `service` plugin.
|
||||||
|
- Dart-side implementation: `lib/core/lib.dart` (`CoreLib`).
|
||||||
|
|
||||||
|
Desktop core mode:
|
||||||
|
|
||||||
|
- Go core runs as a separate process with `CGO_ENABLED=0`.
|
||||||
|
- Flutter communicates via JSON over socket, using a Unix socket on macOS/Linux and TCP on Windows.
|
||||||
|
- Dart-side implementation: `lib/core/service.dart` (`CoreService`).
|
||||||
|
|
||||||
|
`lib/core/controller.dart` (`CoreController`) selects the implementation based on platform. `lib/core/interface.dart` defines the shared `CoreHandlerInterface`.
|
||||||
|
|
||||||
|
Key Go core files:
|
||||||
|
|
||||||
|
- `core/hub.go`: handler functions.
|
||||||
|
- `core/action.go`: dispatch.
|
||||||
|
- `core/lib.go`: CGO exports.
|
||||||
|
- `core/server.go`: socket server.
|
||||||
|
|
||||||
|
## State Management
|
||||||
|
|
||||||
|
Provider files in `lib/providers/`:
|
||||||
|
|
||||||
|
- `app.dart`: runtime/UI state, logs, traffic, delays, loading, navigation.
|
||||||
|
- `config.dart`: persistent config providers, app settings, theme, VPN, proxy style.
|
||||||
|
- `state.dart`: derived/computed providers, navigation, proxy, tray, color scheme.
|
||||||
|
- `action.dart`: business logic notifiers, setup, backup, core lifecycle, proxy selection.
|
||||||
|
- `database.dart`: Drift database provider wrappers.
|
||||||
|
|
||||||
|
`globalState` in `lib/state.dart` is a singleton holding app lifecycle, timers, theme, and start/stop state. Providers are generated into `lib/providers/generated/`.
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
The app uses Drift/SQLite in `lib/database/`. Current schema version is 2.
|
||||||
|
|
||||||
|
Tables:
|
||||||
|
|
||||||
|
- `Profiles`
|
||||||
|
- `Scripts`
|
||||||
|
- `Rules`
|
||||||
|
- `ProfileRuleLinks` (`profile_rule_mapping`)
|
||||||
|
- `ProxyGroups`
|
||||||
|
- `IconRecords` (`icon_records`)
|
||||||
|
|
||||||
|
Rule scenes distinguish global added rules, profile added rules, profile custom rules, and disabled links. Rule and proxy-group ordering use fractional indexing.
|
||||||
|
|
||||||
|
Generated Drift output lives in `lib/database/generated/database.g.dart`. After schema changes, run code generation and add or update focused database tests under `test/database/` when converter or migration behavior changes.
|
||||||
|
|
||||||
|
## Manager Stack
|
||||||
|
|
||||||
|
Managers are nested `InheritedWidget`/`StatefulWidget` components in `lib/application.dart`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
AppEnvManager > StatusManager > ThemeManager
|
||||||
|
> [Desktop: WindowManager > TrayManager > HotKeyManager > ProxyManager]
|
||||||
|
> ConnectivityManager > CoreManager > AppStateManager
|
||||||
|
> [Mobile: AndroidManager > VpnManager | Desktop: WindowHeaderContainer]
|
||||||
|
```
|
||||||
|
|
||||||
|
Each manager in `lib/manager/` handles a specific platform concern. Desktop-only managers are conditionally inserted.
|
||||||
|
|
||||||
|
## Core Controller and Actions
|
||||||
|
|
||||||
|
`lib/core/controller.dart` (`CoreController`) is a singleton facade over `CoreHandlerInterface`. Public methods delegate to the platform-specific interface, either Android FFI or desktop socket. It has an `@visibleForTesting` constructor and `resetInstance()` for test injection.
|
||||||
|
|
||||||
|
Business logic lives in Riverpod notifier classes in `lib/providers/action.dart`:
|
||||||
|
|
||||||
|
- `CommonAction`: update check and common UI operations.
|
||||||
|
- `SetupAction`: config setup and TUN management.
|
||||||
|
- `BackupAction`: backup/restore with WebDAV sync.
|
||||||
|
- `CoreAction`: core lifecycle, init, connect, restart, shutdown.
|
||||||
|
- `SystemAction`: system integration, tray, exit, brightness.
|
||||||
|
- `StoreAction`: profile storage operations.
|
||||||
|
- `ThemeAction`: theme state updates.
|
||||||
|
- `ProxiesAction`: group management and proxy selection.
|
||||||
|
- `ProfilesAction`: profile CRUD, auto-update, import.
|
||||||
|
|
||||||
|
## Platform Managers
|
||||||
|
|
||||||
|
Desktop:
|
||||||
|
|
||||||
|
- `WindowManager`
|
||||||
|
- `TrayManager`
|
||||||
|
- `HotKeyManager`
|
||||||
|
- `ProxyManager`
|
||||||
|
|
||||||
|
Mobile:
|
||||||
|
|
||||||
|
- `AndroidManager`
|
||||||
|
- `TileManager`
|
||||||
|
- `VpnManager`
|
||||||
|
|
||||||
|
Shared:
|
||||||
|
|
||||||
|
- `ConnectivityManager`
|
||||||
|
- `CoreManager`
|
||||||
|
- `AppStateManager`
|
||||||
|
- `StatusManager`
|
||||||
|
- `ThemeManager`
|
||||||
|
|
||||||
|
## Build System
|
||||||
|
|
||||||
|
`setup.dart` is the release build orchestrator:
|
||||||
|
|
||||||
|
1. On Windows, pre-builds Go core via `dart run build_tool windows` and reads `core_sha256.json`.
|
||||||
|
2. Writes `env.json` (`APP_ENV`).
|
||||||
|
3. Passes SHA256 as `--dart-define=CORE_SHA256=$val`, embedded at compile time for Windows.
|
||||||
|
4. Activates `flutter_distributor` for packaging.
|
||||||
|
|
||||||
|
Go core building is handled by `build_tool`, a standalone Dart CLI in `plugins/setup/buildkit/build_tool/`.
|
||||||
|
|
||||||
|
Platform build hooks inside `flutter build` trigger `build_tool` automatically:
|
||||||
|
|
||||||
|
- macOS: podspec script phase, `build_pod.sh`, `build_tool macos`.
|
||||||
|
- Linux: CMake include, `buildkit/cmake/buildkit.cmake`, `build_tool linux`.
|
||||||
|
- Windows: CMake include, `buildkit/cmake/buildkit.cmake`, `build_tool windows`. Debug passes `--dev` via `CMAKE_BUILD_TYPE`.
|
||||||
|
- Android: Gradle include, `buildkit/gradle/plugin.gradle`, `build_tool android`.
|
||||||
|
|
||||||
|
Windows helper auth:
|
||||||
|
|
||||||
|
- Release: Core SHA256 is embedded in both the Flutter app and the Rust helper. The app pings the helper and verifies the token matches.
|
||||||
|
- Debug: The Rust helper skips token verification when built in debug mode, so `flutter run` works without the SHA256 flow.
|
||||||
|
|
||||||
|
`plugins/setup/` is an FFI plugin that exists only as a build harness. It carries no Dart API, only platform build hooks that trigger Go compilation. Windows builds also compile a Rust helper in `services/helper/` through `RustBuilder`.
|
||||||
|
|
||||||
|
Build configuration defaults live in `build_tool/lib/src/options.dart` and can be overridden via `build_config.yaml`.
|
||||||
|
|
||||||
|
Architecture detection is automatic. The `--description` flag passed to `flutter_distributor` adds arch suffixes to artifact names, such as `FlClash-0.8.93-macos-arm64.dmg`.
|
||||||
|
|
||||||
|
## Local Plugins
|
||||||
|
|
||||||
|
- `setup`: build harness FFI plugin.
|
||||||
|
- `proxy`: system proxy configuration.
|
||||||
|
- `rust_api`: Flutter Rust Bridge FFI plugin.
|
||||||
|
- `tray_manager`: system tray fork/customization.
|
||||||
|
- `wifi_ssid`: Wi-Fi SSID detection.
|
||||||
|
- `window_ext`: window extensions.
|
||||||
|
- `flutter_distributor`: app packaging/distribution.
|
||||||
|
|
||||||
|
## Rust Helper Service
|
||||||
|
|
||||||
|
`services/helper/` is a Windows-only privileged helper for starting the core as admin and managing TUN. It is built with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo build --release --features windows-service
|
||||||
|
```
|
||||||
|
|
||||||
|
It uses token-based auth with the Flutter app.
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
# Commands
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Update submodules first. The ClashMeta Go core lives in `core/Clash.Meta/`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
Full package build, including Go core, Flutter, and packaging, runs through `setup.dart`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dart setup.dart macos
|
||||||
|
dart setup.dart linux
|
||||||
|
dart setup.dart windows
|
||||||
|
dart setup.dart android
|
||||||
|
```
|
||||||
|
|
||||||
|
Build only the Go core and skip Flutter packaging:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make core-macos
|
||||||
|
make core-linux
|
||||||
|
make core-windows
|
||||||
|
make core-android
|
||||||
|
```
|
||||||
|
|
||||||
|
Pass `ARCH` or `TARGET_PLATFORM` through `make` when needed, for example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make core-macos ARCH=arm64
|
||||||
|
make core-android TARGET_PLATFORM=android-arm64
|
||||||
|
```
|
||||||
|
|
||||||
|
The Makefile wraps `plugins/setup/buildkit/run_build_tool.sh`; prefer the `make` entry points unless debugging the build tool itself.
|
||||||
|
|
||||||
|
## Flutter Development
|
||||||
|
|
||||||
|
The project is pinned with FVM.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fvm flutter pub get
|
||||||
|
fvm flutter run
|
||||||
|
fvm flutter test
|
||||||
|
```
|
||||||
|
|
||||||
|
Plain Flutter also works when the global SDK matches project constraints:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flutter pub get
|
||||||
|
flutter run
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `flutter test`, not `dart test`, because models pull in Flutter types.
|
||||||
|
|
||||||
|
## Code Generation
|
||||||
|
|
||||||
|
Run code generation after modifying models, providers, or database schema:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dart run build_runner build --delete-conflicting-outputs
|
||||||
|
dart run build_runner watch
|
||||||
|
```
|
||||||
|
|
||||||
|
Code generation covers:
|
||||||
|
|
||||||
|
- Riverpod providers through `riverpod_generator`.
|
||||||
|
- Models through `freezed` and `json_serializable`.
|
||||||
|
- Database tables through `drift_dev`.
|
||||||
|
|
||||||
|
Generated output paths, configured in `build.yaml`:
|
||||||
|
|
||||||
|
- `lib/models/generated/*.g.dart`, `*.freezed.dart`.
|
||||||
|
- `lib/providers/generated/*.g.dart`.
|
||||||
|
- `lib/database/generated/*.g.dart`.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Tests use `package:test/test.dart` for pure Dart logic and `flutter_test` for provider and widget tests. `mocktail` is the mocking framework.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flutter test test/models/
|
||||||
|
flutter test test/core/
|
||||||
|
flutter test test/providers/
|
||||||
|
flutter test test/common/
|
||||||
|
flutter test test/database/
|
||||||
|
flutter test test/widgets/
|
||||||
|
flutter test test/setup_test.dart
|
||||||
|
flutter test plugins/proxy/test/proxy_test.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
Root `flutter test` only discovers the root package's `test/` directory by default. Include bundled plugin Dart tests by passing paths explicitly, or run `flutter test` from that plugin package directory. Native plugin tests under platform folders are not run by `flutter test`.
|
||||||
|
|
||||||
|
## Verify
|
||||||
|
|
||||||
|
CI runs these in order:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flutter pub get
|
||||||
|
flutter analyze --no-fatal-infos
|
||||||
|
flutter test --reporter expanded
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `flutter analyze` locally before committing when practical.
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Project Context
|
||||||
|
|
||||||
|
FlClash is a multi-platform proxy client based on ClashMeta (mihomo), built with Flutter. It supports Android, Windows, macOS, and Linux, using a Material You design with Surfboard-like UI.
|
||||||
|
|
||||||
|
## Version Notes
|
||||||
|
|
||||||
|
- `.fvmrc` pins Flutter 3.35.7 for local development.
|
||||||
|
- CI uses Flutter 3.41.9. These may diverge; trust CI as the source of truth for release builds.
|
||||||
|
- Dart SDK constraint: `>=3.8.0 <4.0.0`.
|
||||||
|
|
||||||
|
## Build Dependencies
|
||||||
|
|
||||||
|
Linux:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install libayatana-appindicator3-dev libkeybinder-3.0-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows:
|
||||||
|
|
||||||
|
- GCC and Inno Setup.
|
||||||
|
- `ANDROID_NDK` env var for Android builds.
|
||||||
|
|
||||||
|
macOS:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g appdmg
|
||||||
|
```
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Rules
|
||||||
|
|
||||||
|
These are repository coding and testing conventions. Codex command permission rules belong in `.codex/rules/*.rules`; see `.agents/agent-config.md` before adding those.
|
||||||
|
|
||||||
|
## Dart and Flutter Style
|
||||||
|
|
||||||
|
`analysis_options.yaml` enforces these non-default rules:
|
||||||
|
|
||||||
|
- `prefer_single_quotes: true`: always use single quotes.
|
||||||
|
- `require_trailing_commas: true`: use trailing commas in multi-line argument lists.
|
||||||
|
- `sort_child_properties_last: true`: `child:` must be the last named parameter.
|
||||||
|
- `avoid_print: true`: do not use `print()` calls.
|
||||||
|
- `prefer_const_constructors: true` and `prefer_const_declarations: true`.
|
||||||
|
- `prefer_final_locals: true` and `prefer_final_in_for_each: true`.
|
||||||
|
- `always_declare_return_types: true`.
|
||||||
|
|
||||||
|
Generated directories are excluded from analysis:
|
||||||
|
|
||||||
|
- `build/**`
|
||||||
|
- `lib/l10n/intl/**`
|
||||||
|
- `lib/**/generated/**`
|
||||||
|
- `plugins/**`
|
||||||
|
|
||||||
|
## Testing Rules
|
||||||
|
|
||||||
|
Use `CoreController.test(mock)` to inject a mocked `CoreHandlerInterface`. Call `CoreController.resetInstance()` in `tearDown` to clean up the singleton between tests.
|
||||||
|
|
||||||
|
Register fallback values for freezed params used with `any()` matchers.
|
||||||
|
|
||||||
|
Use `ProviderContainer` directly for simple Riverpod provider tests. The generated Riverpod `update()` method takes a callback:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
notifier.update((state) => newValue);
|
||||||
|
```
|
||||||
|
|
||||||
|
When testing freezed models with nested objects, always round-trip through `jsonEncode` and `jsonDecode`. Direct `fromJson(toJson())` fails for nested freezed types because `toJson()` stores child objects directly instead of maps.
|
||||||
|
|
||||||
|
## Generated Code
|
||||||
|
|
||||||
|
Do not manually edit generated files under:
|
||||||
|
|
||||||
|
- `lib/models/generated/`
|
||||||
|
- `lib/providers/generated/`
|
||||||
|
- `lib/database/generated/`
|
||||||
|
- `lib/l10n/intl/`
|
||||||
|
|
||||||
|
After schema, model, or provider changes, run build generation and include focused tests when behavior changes.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Agent Skills
|
||||||
|
|
||||||
|
Repo-scoped Codex skills live under `.agents/skills/*/SKILL.md`. Codex can discover these by skill `name` and `description`, then load the full instructions only when a task matches.
|
||||||
|
|
||||||
|
## Available Repo Skills
|
||||||
|
|
||||||
|
- `localization`: hardcoded UI text scans, ARB updates, locale generation, and localization verification.
|
||||||
|
- `provider-tests`: Riverpod provider, notifier, and state-management tests.
|
||||||
|
- `ui-work`: Flutter UI, widgets, Material You styling, navigation surfaces, and user-facing interactions.
|
||||||
|
- `core-platform`: core integration, platform managers, Go core communication, desktop/mobile behavior, and Windows helper flow.
|
||||||
|
|
||||||
|
## Authoring Notes
|
||||||
|
|
||||||
|
- Add new repeatable workflows as `.agents/skills/<skill-name>/SKILL.md`.
|
||||||
|
- Keep skill descriptions trigger-focused and start them with `Use when...`.
|
||||||
|
- Keep long reference material in `.agents/*.md`; skills should link to it instead of duplicating it.
|
||||||
|
- Put command permission rules in `.codex/rules/*.rules`, not in this file.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
name: core-platform
|
||||||
|
description: Use when changing FlClash core integration, platform managers, Go core communication, desktop/mobile platform behavior, or Windows helper flow.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Core And Platform
|
||||||
|
|
||||||
|
## When To Use
|
||||||
|
|
||||||
|
Use this for changes touching `lib/core/`, `lib/manager/`, `core/`, `services/helper/`, build hooks, system proxy, tray, VPN, TUN, or platform-specific desktop/mobile behavior.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Identify which boundary owns the behavior:
|
||||||
|
- Android lib mode: `lib/core/lib.dart`.
|
||||||
|
- Desktop process/socket mode: `lib/core/service.dart`.
|
||||||
|
- Shared facade: `lib/core/controller.dart` and `lib/core/interface.dart`.
|
||||||
|
- Platform lifecycle: `lib/manager/`.
|
||||||
|
2. Route feature code through `CoreController` and `CoreHandlerInterface`; avoid direct calls to platform implementations outside their boundary.
|
||||||
|
3. Keep desktop and mobile paths explicit.
|
||||||
|
4. For action-layer behavior, inspect `lib/providers/action.dart` and relevant generated providers.
|
||||||
|
5. Add or update shared Dart tests for logic that can be isolated.
|
||||||
|
6. Manually verify native behavior when automated coverage is not practical.
|
||||||
|
|
||||||
|
## Reference Files
|
||||||
|
|
||||||
|
Read `.agents/architecture.md` for the current core modes, manager stack, build hooks, local plugins, and Windows helper notes.
|
||||||
|
|
||||||
|
## Pitfalls
|
||||||
|
|
||||||
|
- Debug Windows helper auth differs from release token verification.
|
||||||
|
- `plugins/setup/` is a build harness, not a Dart API plugin.
|
||||||
|
- Build hooks can trigger Go or Rust compilation indirectly through Flutter platform builds.
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
name: localization
|
||||||
|
description: Use when changing FlClash UI text, scanning for hardcoded Chinese strings, updating ARB localization, or fixing generated locale output in this repository.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Localization
|
||||||
|
|
||||||
|
## When To Use
|
||||||
|
|
||||||
|
Use this for localization work inside `/Users/Shared/follow/FlClash`, especially hardcoded UI text in `lib/`, ARB updates, missing translations, or generated `lib/l10n/` output that does not match source ARB values.
|
||||||
|
|
||||||
|
Do not use this for README translation sync or manual edits to generated localization Dart.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Confirm `pubspec.yaml` still uses `flutter_intl`, source ARBs under `arb/`, and generated output under `lib/l10n/`.
|
||||||
|
2. Scan user-facing Dart text before opening many files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rg -n "[\\p{Han}]" lib -g '!lib/l10n/intl/**' -g '!lib/**/generated/**'
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Inspect the smallest relevant call sites and nearby ARB keys.
|
||||||
|
4. Add or update every source ARB:
|
||||||
|
- `arb/intl_en.arb`
|
||||||
|
- `arb/intl_zh_CN.arb`
|
||||||
|
- `arb/intl_ja.arb`
|
||||||
|
- `arb/intl_ru.arb`
|
||||||
|
5. Replace inline strings with existing project accessors:
|
||||||
|
- Widgets with `BuildContext`: `context.appLocalizations.key` from `common.dart`.
|
||||||
|
- Controllers/providers/non-widget code: `currentAppLocalizations.key` from `app_localizations.dart`.
|
||||||
|
6. Regenerate:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dart run intl_utils:generate
|
||||||
|
```
|
||||||
|
|
||||||
|
7. Verify changed Dart files with `flutter analyze` when practical.
|
||||||
|
8. Re-run the Han-text scan for targeted strings.
|
||||||
|
|
||||||
|
## Pitfalls
|
||||||
|
|
||||||
|
- If ja/ru still show English, fix ja/ru source ARB values and regenerate. Do not edit generated Dart.
|
||||||
|
- Ignore `lib/l10n/intl/**` and `lib/**/generated/**` during text scans.
|
||||||
|
- If generator or analyzer hits local cache permission friction, rerun serially before treating it as a code issue.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
name: provider-tests
|
||||||
|
description: Use when adding or updating FlClash Riverpod provider tests, notifier tests, or state-management tests in this repository.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Provider Tests
|
||||||
|
|
||||||
|
## When To Use
|
||||||
|
|
||||||
|
Use this for tests under `test/providers/` or any change that validates Riverpod providers, generated notifiers, app state defaults, or provider interactions.
|
||||||
|
|
||||||
|
For broader test expansion, pair this with `.agents/rules.md` and `.agents/commands.md`.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Read the provider under test and its generated public API before writing assertions.
|
||||||
|
2. Use `ProviderContainer` directly when no widget tree is needed.
|
||||||
|
3. Dispose containers in teardown or with `addTearDown(container.dispose)`.
|
||||||
|
4. Prefer generated notifier APIs over implementation details. Generated `update()` takes a callback:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
notifier.update((state) => newValue);
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Mock external dependencies with `mocktail`; register fallback values for freezed params used with `any()`.
|
||||||
|
6. Keep tests focused on behavior: defaults, state transitions, persistence boundaries, and side effects.
|
||||||
|
7. Run the narrowest relevant test first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flutter test test/providers/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pitfalls
|
||||||
|
|
||||||
|
- Do not use `dart test`; FlClash models and provider tests may depend on Flutter types.
|
||||||
|
- Re-check source defaults before asserting them; provider defaults can drift.
|
||||||
|
- If async provider timing matters, wait on provider futures or state changes instead of fixed sleeps.
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
name: ui-work
|
||||||
|
description: Use when changing FlClash Flutter UI, widgets, screens, Material You styling, navigation surfaces, or user-facing interactions.
|
||||||
|
---
|
||||||
|
|
||||||
|
# UI Work
|
||||||
|
|
||||||
|
## When To Use
|
||||||
|
|
||||||
|
Use this for user-facing Flutter UI changes in `lib/`, including widgets, screens, navigation surfaces, settings rows, dialogs, and interaction behavior.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Locate existing nearby widgets and reuse their patterns before adding new abstractions.
|
||||||
|
2. Follow current Material You and Surfboard-like visual conventions.
|
||||||
|
3. Use existing providers, notifiers, and helpers where possible.
|
||||||
|
4. Keep `child:` last in widget constructors.
|
||||||
|
5. Prefer `const` constructors and final locals.
|
||||||
|
6. Localize user-facing text through ARB; use `localization` when text changes are non-trivial.
|
||||||
|
7. Add focused widget tests when behavior changes, especially for rendering states, taps, scrolling, and empty/error states.
|
||||||
|
8. Run targeted verification:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flutter analyze
|
||||||
|
flutter test test/widgets/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pitfalls
|
||||||
|
|
||||||
|
- Do not introduce a new visual system for one screen.
|
||||||
|
- Do not manually edit generated localization or provider files.
|
||||||
|
- Avoid broad layout rewrites unless the requested change requires them.
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
Scan `lib/` for hardcoded Chinese strings and internationalize them following the project's ARB conventions.
|
|
||||||
|
|
||||||
## Instructions
|
|
||||||
|
|
||||||
You are performing i18n extraction for a Flutter project that uses the Flutter Intl plugin with ARB files.
|
|
||||||
|
|
||||||
### Project localization context
|
|
||||||
|
|
||||||
- **ARB files**: `arb/intl_en.arb`, `arb/intl_zh_CN.arb`, `arb/intl_ja.arb`, `arb/intl_ru.arb`
|
|
||||||
- **Key conventions**: camelCase, flat keys (no nesting, no `@` metadata), semantic naming
|
|
||||||
- Short labels: `rule`, `global`, `direct`, `edit`, `confirm`
|
|
||||||
- Descriptive suffix `Desc`: `themeDesc`, `tunDesc`, `logsDesc`
|
|
||||||
- Validation suffix: `profileNameNullValidationDesc`
|
|
||||||
- **Generated code**: `lib/l10n/l10n.dart` (DO NOT edit generated files)
|
|
||||||
- **Access patterns**:
|
|
||||||
- In widgets with BuildContext: `context.appLocalizations.key` (import `common.dart`)
|
|
||||||
- In controllers/providers/non-widget code: `currentAppLocalizations.key` (import `app_localizations.dart`)
|
|
||||||
|
|
||||||
### Step 1: Find hardcoded Chinese strings
|
|
||||||
|
|
||||||
Use Grep to search `lib/` for Chinese characters. The regex pattern for Chinese characters is `[\x{4e00}-\x{9fff}]`.
|
|
||||||
|
|
||||||
Important filters:
|
|
||||||
- **Exclude** `lib/l10n/` (generated localization files)
|
|
||||||
- **Exclude** lines that already use `appLocalizations` or `currentAppLocalizations`
|
|
||||||
- **Exclude** false positives that are NOT Chinese text:
|
|
||||||
- Arrow symbols: `↑` `↓` `←` `→` (Unicode arrows, not CJK)
|
|
||||||
- Middle dot: `·` (U+00B7, not CJK)
|
|
||||||
- Command symbol: `⌘` (U+2318, not CJK)
|
|
||||||
- Other CJK punctuation that is used as UI symbols, not translatable text
|
|
||||||
|
|
||||||
For each match, read the surrounding context (5-10 lines) to understand:
|
|
||||||
- What the string represents (label, error message, tooltip, dialog text, etc.)
|
|
||||||
- Whether it's inside a widget (has `BuildContext` available) or non-widget code
|
|
||||||
- Whether it appears in a `Text()`, `TextSpan()`, `title:`, `label:`, or other text position
|
|
||||||
|
|
||||||
### Step 2: Generate ARB keys
|
|
||||||
|
|
||||||
For each hardcoded Chinese string:
|
|
||||||
|
|
||||||
1. **Choose a key name** following project conventions:
|
|
||||||
- Use the Chinese meaning to derive an English camelCase key
|
|
||||||
- Keep it concise: `createConfig` not `createAConfigurationForTheProfile`
|
|
||||||
- Use `Desc` suffix for descriptive/explanatory text
|
|
||||||
- Use existing similar keys as reference (check `arb/intl_en.arb` for patterns)
|
|
||||||
|
|
||||||
2. **Determine the English translation** (the value for `intl_en.arb`)
|
|
||||||
|
|
||||||
3. **Determine the Chinese translation** (the value for `intl_zh_CN.arb`) — this is the original hardcoded string
|
|
||||||
|
|
||||||
4. **For ja and ru**: use the English translation as a placeholder (translators will fill these in later)
|
|
||||||
|
|
||||||
### Step 3: Update ARB files
|
|
||||||
|
|
||||||
For each new key, add it to all 4 ARB files. Read each ARB file first to find the right insertion point (alphabetical order is not required, but appending near the end is clean).
|
|
||||||
|
|
||||||
Format: add a new line like `"keyName": "value",` before the closing `}`.
|
|
||||||
|
|
||||||
### Step 4: Replace hardcoded strings in Dart files
|
|
||||||
|
|
||||||
Replace each hardcoded Chinese string with the appropriate localization call:
|
|
||||||
|
|
||||||
- If inside a widget BuildContext: `context.appLocalizations.keyName`
|
|
||||||
- If in controller/provider code: `currentAppLocalizations.keyName`
|
|
||||||
|
|
||||||
Ensure the correct import exists:
|
|
||||||
- For `context.appLocalizations`: the file should import `common.dart` (check if it already does)
|
|
||||||
- For `currentAppLocalizations`: the file should import `app_localizations.dart` (check if it already does)
|
|
||||||
|
|
||||||
If the file uses string interpolation (e.g., `'创建 $name 配置'`), convert to the ARB parameterized format:
|
|
||||||
- In ARB: `"keyName": "Create $name config"`
|
|
||||||
- In Dart: `currentAppLocalizations.keyName(name)`
|
|
||||||
|
|
||||||
### Step 5: Report changes
|
|
||||||
|
|
||||||
After all modifications, output a summary:
|
|
||||||
1. List each file modified and what changed
|
|
||||||
2. List each new ARB key added with its translations
|
|
||||||
3. Remind the user to run code generation if needed:
|
|
||||||
```
|
|
||||||
dart run build_runner build --delete-conflicting-outputs
|
|
||||||
```
|
|
||||||
or trigger Flutter Intl regeneration in their IDE.
|
|
||||||
|
|
||||||
### Important notes
|
|
||||||
|
|
||||||
- Only extract strings that are user-facing UI text. Do NOT extract:
|
|
||||||
- Comments (lines starting with `//`)
|
|
||||||
- Log messages (unless they appear in the UI)
|
|
||||||
- Variable names or identifiers
|
|
||||||
- String literals used as keys/identifiers (not displayed to users)
|
|
||||||
- If a Chinese string is split across multiple lines or concatenations, merge them into a single ARB entry
|
|
||||||
- If a string contains dynamic content (variables, URLs), use ARB parameter syntax `$variableName`
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# CodeGraph data files — local to each machine, not for committing.
|
||||||
|
# Ignore everything in .codegraph/ except this file itself, so transient
|
||||||
|
# files (the database, daemon.pid, sockets, logs) never show up in git.
|
||||||
|
*
|
||||||
|
!.gitignore
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"codegraph": {
|
||||||
|
"type": "stdio",
|
||||||
|
"command": "codegraph",
|
||||||
|
"args": [
|
||||||
|
"serve",
|
||||||
|
"--mcp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
cask "flclash" do
|
||||||
|
version "VERSION"
|
||||||
|
|
||||||
|
on_macos do
|
||||||
|
arch arm: "arm64", intel: "amd64"
|
||||||
|
|
||||||
|
sha256 arm: "ARM_SHA256",
|
||||||
|
intel: "AMD_SHA256"
|
||||||
|
|
||||||
|
url "https://github.com/chen08209/FlClash/releases/download/v#{version}/FlClash-#{version}-macos-#{arch}.dmg"
|
||||||
|
end
|
||||||
|
|
||||||
|
name "FlClash"
|
||||||
|
desc "Multi-platform proxy client based on ClashMeta"
|
||||||
|
homepage "https://github.com/chen08209/FlClash"
|
||||||
|
|
||||||
|
livecheck do
|
||||||
|
url :url
|
||||||
|
strategy :github_latest
|
||||||
|
end
|
||||||
|
|
||||||
|
depends_on :macos
|
||||||
|
|
||||||
|
app "FlClash.app"
|
||||||
|
|
||||||
|
postflight do
|
||||||
|
system_command "xattr",
|
||||||
|
args: ["-rd", "com.apple.quarantine", "#{appdir}/FlClash.app"]
|
||||||
|
end
|
||||||
|
|
||||||
|
uninstall quit: "com.follow.clash"
|
||||||
|
|
||||||
|
zap trash: [
|
||||||
|
"~/Library/Application Support/com.follow.clash",
|
||||||
|
"~/Library/Caches/com.follow.clash",
|
||||||
|
"~/Library/Preferences/com.follow.clash.plist",
|
||||||
|
"~/Library/Saved Application State/com.follow.clash.savedState",
|
||||||
|
]
|
||||||
|
end
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-linux-amd64.AppImage"><img src="https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux"> </a><br>
|
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-linux-amd64.AppImage"><img src="https://img.shields.io/badge/AppImage-x64-f84e29.svg?logo=linux"> </a><br>
|
||||||
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-linux-amd64.deb"><img src="https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian"> </a><br>
|
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-linux-amd64.deb"><img src="https://img.shields.io/badge/DebPackage-x64-FF9966.svg?logo=debian"> </a><br>
|
||||||
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-linux-amd64.deb"><img src="https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat"> </a>
|
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-linux-amd64.rpm"><img src="https://img.shields.io/badge/RpmPackage-x64-F1B42F.svg?logo=redhat"> </a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ on:
|
|||||||
- 'v*'
|
- 'v*'
|
||||||
env:
|
env:
|
||||||
IS_STABLE: ${{ !contains(github.ref, '-') }}
|
IS_STABLE: ${{ !contains(github.ref, '-') }}
|
||||||
|
FLUTTER_VERSION: '3.44.4'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@@ -21,7 +22,7 @@ jobs:
|
|||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: stable
|
channel: stable
|
||||||
flutter-version: 3.41.9
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||||
cache: true
|
cache: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -63,6 +64,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Setup rust
|
- name: Setup rust
|
||||||
if: startsWith(matrix.os, 'windows-11-arm')
|
if: startsWith(matrix.os, 'windows-11-arm')
|
||||||
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
Invoke-WebRequest -Uri "https://win.rustup.rs/aarch64" -OutFile rustup-init.exe
|
Invoke-WebRequest -Uri "https://win.rustup.rs/aarch64" -OutFile rustup-init.exe
|
||||||
.\rustup-init.exe -y --default-toolchain stable
|
.\rustup-init.exe -y --default-toolchain stable
|
||||||
@@ -79,14 +81,16 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "${{ secrets.KEYSTORE }}" | base64 --decode > android/app/keystore.jks
|
echo "${{ secrets.KEYSTORE }}" | base64 --decode > android/app/keystore.jks
|
||||||
echo "${{ secrets.SERVICE_JSON }}" | base64 --decode > android/app/google-services.json
|
echo "${{ secrets.SERVICE_JSON }}" | base64 --decode > android/app/google-services.json
|
||||||
echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/local.properties
|
{
|
||||||
echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> android/local.properties
|
echo "keyAlias=${{ secrets.KEY_ALIAS }}"
|
||||||
echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/local.properties
|
echo "storePassword=${{ secrets.STORE_PASSWORD }}"
|
||||||
|
echo "keyPassword=${{ secrets.KEY_PASSWORD }}"
|
||||||
|
} >> android/local.properties
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.24.0'
|
go-version: '1.26.4'
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
core/go.sum
|
core/go.sum
|
||||||
|
|
||||||
@@ -95,20 +99,18 @@ jobs:
|
|||||||
run: git config --global core.longpaths true
|
run: git config --global core.longpaths true
|
||||||
|
|
||||||
- name: Setup Flutter
|
- name: Setup Flutter
|
||||||
if: ${{ !(startsWith(matrix.os, 'windows-11-arm') || startsWith(matrix.os, 'ubuntu-24.04-arm')) }}
|
|
||||||
uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
channel: stable
|
|
||||||
flutter-version: 3.41.9
|
|
||||||
cache: true
|
|
||||||
- name: Setup Flutter With Other
|
|
||||||
if: startsWith(matrix.os, 'windows-11-arm') || startsWith(matrix.os, 'ubuntu-24.04-arm')
|
|
||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: master
|
channel: master
|
||||||
flutter-version: 3.44.0-0.1.pre
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||||
cache: true
|
cache: true
|
||||||
|
|
||||||
|
- name: Setup Xcode
|
||||||
|
if: startsWith(matrix.platform,'macos')
|
||||||
|
run: |
|
||||||
|
sudo xcode-select -s /Applications/Xcode_26.3.app || sudo xcode-select -s /Applications/Xcode_26.2.app
|
||||||
|
xcodebuild -version
|
||||||
|
|
||||||
- name: Setup NDK
|
- name: Setup NDK
|
||||||
if: startsWith(matrix.platform,'android')
|
if: startsWith(matrix.platform,'android')
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@@ -133,17 +135,18 @@ jobs:
|
|||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
||||||
changelog:
|
changelog:
|
||||||
|
if: ${{ !contains(github.ref, '-') }}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [ build ]
|
needs: [ build ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
if: ${{ env.IS_STABLE == 'true' }}
|
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: refs/heads/main
|
ref: refs/heads/main
|
||||||
- name: Generate
|
- name: Generate
|
||||||
if: ${{ env.IS_STABLE == 'true' }}
|
|
||||||
run: |
|
run: |
|
||||||
last_ver=$(grep -m1 '^## ' CHANGELOG.md 2>/dev/null | sed 's/^## //')
|
last_ver=$(grep -m1 '^## ' CHANGELOG.md 2>/dev/null | sed 's/^## //')
|
||||||
|
|
||||||
@@ -167,7 +170,6 @@ jobs:
|
|||||||
mv "$temp" CHANGELOG.md
|
mv "$temp" CHANGELOG.md
|
||||||
|
|
||||||
- name: Commit
|
- name: Commit
|
||||||
if: ${{ env.IS_STABLE == 'true' }}
|
|
||||||
run: |
|
run: |
|
||||||
git add CHANGELOG.md
|
git add CHANGELOG.md
|
||||||
if ! git diff --cached --quiet; then
|
if ! git diff --cached --quiet; then
|
||||||
@@ -175,8 +177,7 @@ jobs:
|
|||||||
git config --local user.email "chen08209@gmail.com"
|
git config --local user.email "chen08209@gmail.com"
|
||||||
git config --local user.name "chen08209"
|
git config --local user.name "chen08209"
|
||||||
git commit -m "Update changelog"
|
git commit -m "Update changelog"
|
||||||
git push
|
if git push; then
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "Push succeeded"
|
echo "Push succeeded"
|
||||||
else
|
else
|
||||||
echo "Push failed"
|
echo "Push failed"
|
||||||
@@ -188,7 +189,8 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
upload:
|
upload:
|
||||||
permissions: write-all
|
permissions:
|
||||||
|
contents: write
|
||||||
needs: [ build ]
|
needs: [ build ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
services:
|
services:
|
||||||
@@ -251,7 +253,7 @@ jobs:
|
|||||||
if: ${{ env.IS_STABLE == 'true' }}
|
if: ${{ env.IS_STABLE == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
cd ./dist
|
cd ./dist
|
||||||
sha256sum * > SHA256SUMS
|
sha256sum ./* > SHA256SUMS
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
if: ${{ env.IS_STABLE == 'true' }}
|
if: ${{ env.IS_STABLE == 'true' }}
|
||||||
@@ -260,6 +262,35 @@ jobs:
|
|||||||
files: ./dist/*
|
files: ./dist/*
|
||||||
body_path: './release.md'
|
body_path: './release.md'
|
||||||
|
|
||||||
|
- name: Create Homebrew Cask Source Dir
|
||||||
|
if: ${{ env.IS_STABLE == 'true' }}
|
||||||
|
run: |
|
||||||
|
version=$(echo "${{ github.ref_name }}" | sed 's/^v//')
|
||||||
|
arm_sha=$(sha256sum "./dist/FlClash-${version}-macos-arm64.dmg" | awk '{print $1}')
|
||||||
|
amd_sha=$(sha256sum "./dist/FlClash-${version}-macos-amd64.dmg" | awk '{print $1}')
|
||||||
|
|
||||||
|
mkdir -p ./brew/Casks
|
||||||
|
sed \
|
||||||
|
-e "s|VERSION|$version|g" \
|
||||||
|
-e "s|ARM_SHA256|$arm_sha|g" \
|
||||||
|
-e "s|AMD_SHA256|$amd_sha|g" \
|
||||||
|
./.github/homebrew_cask_template.rb > ./brew/Casks/flclash.rb
|
||||||
|
|
||||||
|
- name: Push to Homebrew tap
|
||||||
|
if: ${{ env.IS_STABLE == 'true' }}
|
||||||
|
uses: cpina/github-action-push-to-another-repository@v1.7.2
|
||||||
|
env:
|
||||||
|
SSH_DEPLOY_KEY: ${{ secrets.HOMEBREW_SSH_DEPLOY_KEY }}
|
||||||
|
with:
|
||||||
|
source-directory: ./brew/
|
||||||
|
destination-github-username: chen08209
|
||||||
|
destination-repository-name: homebrew-tap
|
||||||
|
user-name: 'chen08029'
|
||||||
|
user-email: 'chen08209@gmail.com'
|
||||||
|
target-branch: main
|
||||||
|
commit-message: Update Homebrew cask from ${{ github.ref_name }}
|
||||||
|
target-directory: /
|
||||||
|
|
||||||
- name: Create Fdroid Source Dir
|
- name: Create Fdroid Source Dir
|
||||||
if: ${{ env.IS_STABLE == 'true' }}
|
if: ${{ env.IS_STABLE == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
@@ -276,8 +307,8 @@ jobs:
|
|||||||
source-directory: ./tmp/
|
source-directory: ./tmp/
|
||||||
destination-github-username: chen08209
|
destination-github-username: chen08209
|
||||||
destination-repository-name: FlClash-fdroid-repo
|
destination-repository-name: FlClash-fdroid-repo
|
||||||
user-name: 'github-actions[bot]'
|
user-name: 'chen08029'
|
||||||
user-email: 'github-actions[bot]@users.noreply.github.com'
|
user-email: 'chen08209@gmail.com'
|
||||||
target-branch: main
|
target-branch: main
|
||||||
commit-message: Update from ${{ github.ref_name }}
|
commit-message: Update from ${{ github.ref_name }}
|
||||||
target-directory: /tmp/
|
target-directory: /tmp/
|
||||||
|
|||||||
@@ -2,13 +2,3 @@
|
|||||||
path = core/Clash.Meta
|
path = core/Clash.Meta
|
||||||
url = git@github.com:chen08209/Clash.Meta.git
|
url = git@github.com:chen08209/Clash.Meta.git
|
||||||
branch = FlClash
|
branch = FlClash
|
||||||
[submodule "plugins/flutter_distributor"]
|
|
||||||
path = plugins/flutter_distributor
|
|
||||||
url = git@github.com:chen08209/flutter_distributor.git
|
|
||||||
branch = FlClash
|
|
||||||
[submodule "plugins/tray_manager"]
|
|
||||||
path = plugins/tray_manager
|
|
||||||
url = git@github.com:chen08209/tray_manager.git
|
|
||||||
branch = main
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"codegraph": {
|
||||||
|
"type": "stdio",
|
||||||
|
"command": "codegraph",
|
||||||
|
"args": [
|
||||||
|
"serve",
|
||||||
|
"--mcp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
repos:
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: dart-format
|
||||||
|
name: dart format
|
||||||
|
entry: dart format
|
||||||
|
language: system
|
||||||
|
files: \.dart$
|
||||||
|
- id: flutter-analyze
|
||||||
|
name: flutter analyze
|
||||||
|
entry: flutter analyze --no-fatal-infos
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
|
files: \.dart$
|
||||||
|
- id: flutter-test
|
||||||
|
name: flutter test
|
||||||
|
entry: flutter test --reporter expanded
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
|
files: \.dart$
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"lsp": {
|
||||||
|
"gopls": {
|
||||||
|
"binary": {
|
||||||
|
"env": {
|
||||||
|
"CGO_ENABLED": "0",
|
||||||
|
// "GOOS": "android",
|
||||||
|
// "GOARCH": "arm64",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,233 +1,35 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
|
|
||||||
This file provides guidance for AI coding agents working with code in this repository.
|
This file is the entry point for AI coding agents working in this repository. Keep it small: detailed guidance lives under
|
||||||
|
`.agents/`, and discoverable repo skills live under `.agents/skills/*/SKILL.md`.
|
||||||
|
|
||||||
## Project Overview
|
## Start Here
|
||||||
|
|
||||||
FlClash is a multi-platform proxy client based on ClashMeta (mihomo), built with Flutter. Supports Android, Windows,
|
Read these files before making changes:
|
||||||
macOS, and Linux. Material You design with Surfboard-like UI.
|
|
||||||
|
|
||||||
## Common Development Commands
|
- [.agents/project.md](.agents/project.md): project overview, versions, and build dependencies.
|
||||||
|
- [.agents/commands.md](.agents/commands.md): build, development, code generation, and test commands.
|
||||||
|
- [.agents/rules.md](.agents/rules.md): lint, testing, generated-code, and workflow rules.
|
||||||
|
|
||||||
### Building
|
Read these only when the task touches their area:
|
||||||
|
|
||||||
```bash
|
- [.agents/architecture.md](.agents/architecture.md): core integration, providers, database, managers, build system, and
|
||||||
# Update submodules first (ClashMeta Go core lives in core/Clash.Meta/)
|
local plugins.
|
||||||
git submodule update --init --recursive
|
- [.agents/agent-config.md](.agents/agent-config.md): how to choose between `AGENTS.md`, `.agents`, skills, Codex config,
|
||||||
|
command rules, and hooks.
|
||||||
|
- [.agents/skills.md](.agents/skills.md): index of repo-scoped skills in `.agents/skills/`.
|
||||||
|
|
||||||
# Full package build (Go core + Flutter + packaging) via setup.dart
|
## Highest Priority Rules
|
||||||
dart setup.dart macos
|
|
||||||
dart setup.dart linux
|
|
||||||
dart setup.dart windows
|
|
||||||
dart setup.dart android
|
|
||||||
|
|
||||||
# Build only the Go core (skip Flutter packaging)
|
- Use `flutter test`, not `dart test`, because models pull in Flutter types.
|
||||||
bash plugins/setup/buildkit/run_build_tool.sh macos
|
- Run code generation after modifying models, providers, or database schema.
|
||||||
bash plugins/setup/buildkit/run_build_tool.sh linux
|
- Do not manually edit generated files.
|
||||||
bash plugins/setup/buildkit/run_build_tool.sh windows
|
- Follow `analysis_options.yaml`, especially single quotes, trailing commas, `child:` last, no `print()`, const/final
|
||||||
bash plugins/setup/buildkit/run_build_tool.sh android
|
preferences, and declared return types.
|
||||||
```
|
- For CI parity, verify with `flutter pub get`, `flutter analyze --no-fatal-infos`, and
|
||||||
|
`flutter test --reporter expanded` when practical.
|
||||||
|
|
||||||
### Flutter Development
|
## Repo Skills
|
||||||
|
|
||||||
```bash
|
Use repo skills from `.agents/skills/` when a task matches their descriptions. Current skills cover localization,
|
||||||
# Project is pinned with FVM (.fvmrc currently uses Flutter 3.35.7)
|
provider tests, UI work, and core/platform changes.
|
||||||
fvm flutter pub get
|
|
||||||
fvm flutter run
|
|
||||||
fvm flutter test
|
|
||||||
|
|
||||||
# Plain Flutter also works when your global SDK matches the project constraints
|
|
||||||
flutter pub get
|
|
||||||
flutter run # Run on connected device/desktop
|
|
||||||
flutter test # Run all tests (use flutter test, not dart test — models pull in Flutter types)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Code Generation
|
|
||||||
|
|
||||||
Required after modifying models, providers, or database schema:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dart run build_runner build --delete-conflicting-outputs
|
|
||||||
dart run build_runner watch # Continuous regeneration
|
|
||||||
```
|
|
||||||
|
|
||||||
Code generation covers: Riverpod providers (`riverpod_generator`), models (`freezed`, `json_serializable`), and database
|
|
||||||
tables (`drift_dev`).
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
Tests use `package:test/test.dart` for pure Dart logic (common utils, models) and `flutter_test` for provider/widget tests.
|
|
||||||
`mocktail` is the mocking framework.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
flutter test test/models/ # Model serialization & extension round-trip tests
|
|
||||||
flutter test test/core/ # CoreController tests (mocked CoreHandlerInterface)
|
|
||||||
flutter test test/providers/ # Riverpod provider tests (config & app state notifiers)
|
|
||||||
flutter test test/common/ # Utility function tests (utils, string, iterable, fixed, etc.)
|
|
||||||
flutter test test/database/ # Database type converter tests
|
|
||||||
flutter test test/widgets/ # Widget-level rendering/interaction tests
|
|
||||||
flutter test test/setup_test.dart
|
|
||||||
flutter test plugins/proxy/test/proxy_test.dart # Dart tests for bundled plugin packages
|
|
||||||
```
|
|
||||||
|
|
||||||
Root `flutter test` only discovers the root package's `test/` directory by default. Include bundled plugin Dart tests by
|
|
||||||
passing their paths explicitly, or run `flutter test` from that plugin package directory. Native plugin tests under
|
|
||||||
platform folders (for example Windows C++ tests) are not run by `flutter test`.
|
|
||||||
|
|
||||||
**Mocking `CoreHandlerInterface`:** Use `CoreController.test(mock)` to inject a mock interface. Call
|
|
||||||
`CoreController.resetInstance()` in `tearDown` to clean up the singleton between tests. Remember to
|
|
||||||
`registerFallbackValue()` for freezed params used with `any()` matchers.
|
|
||||||
|
|
||||||
**Provider tests:** Use `ProviderContainer` directly (no widget tree needed for simple notifiers). The Riverpod
|
|
||||||
generated `update()` method takes a callback: `notifier.update((state) => newValue)`.
|
|
||||||
|
|
||||||
**Model round-trip tests:** Always go through `jsonEncode`/`jsonDecode` when testing freezed models with
|
|
||||||
nested objects — `toJson()` stores child objects directly (not as maps), so direct `fromJson(toJson())`
|
|
||||||
fails for nested freezed types.
|
|
||||||
|
|
||||||
### Build Dependencies
|
|
||||||
|
|
||||||
**Linux:** `sudo apt-get install libayatana-appindicator3-dev libkeybinder-3.0-dev`
|
|
||||||
|
|
||||||
**Windows:** GCC and Inno Setup. `ANDROID_NDK` env var for Android builds.
|
|
||||||
|
|
||||||
**macOS:** `npm install -g appdmg` for DMG creation.
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Core Integration (Go ClashMeta <-> Flutter)
|
|
||||||
|
|
||||||
This is the most important architectural concept. The Go proxy core (`core/`) operates in two modes:
|
|
||||||
|
|
||||||
- **Android (lib mode):** Go core compiled as C shared library (`libclash.so`) via `go build -buildmode=c-shared` with
|
|
||||||
CGO. Flutter calls it via FFI through the `service` plugin. Dart-side: `lib/core/lib.dart` (`CoreLib` class).
|
|
||||||
|
|
||||||
- **Desktop (core mode):** Go core runs as a separate process with `CGO_ENABLED=0`. Flutter communicates via
|
|
||||||
JSON-over-socket (Unix socket on macOS/Linux, TCP on Windows). Dart-side: `lib/core/service.dart` (`CoreService`
|
|
||||||
class).
|
|
||||||
|
|
||||||
`lib/core/controller.dart` (`CoreController`) selects the implementation based on platform. `lib/core/interface.dart`
|
|
||||||
defines the shared `CoreHandlerInterface`.
|
|
||||||
|
|
||||||
Go core key files: `core/hub.go` (handler functions), `core/action.go` (dispatch), `core/lib.go` (CGO exports),
|
|
||||||
`core/server.go` (socket server).
|
|
||||||
|
|
||||||
### State Management (Riverpod)
|
|
||||||
|
|
||||||
Provider files in `lib/providers/`:
|
|
||||||
|
|
||||||
- `app.dart` - Runtime/UI state (logs, traffic, delays, loading, navigation)
|
|
||||||
- `config.dart` - Persistent config providers (app settings, theme, VPN, proxy style)
|
|
||||||
- `state.dart` - Derived/computed providers (navigation, proxy, tray, color scheme)
|
|
||||||
- `action.dart` - Business logic notifiers (setup, backup, core lifecycle, proxy selection)
|
|
||||||
- `database.dart` - Drift database provider wrappers
|
|
||||||
|
|
||||||
`globalState` (`lib/state.dart`) is a singleton holding app lifecycle, timers, theme, and the start/stop state.
|
|
||||||
Providers are generated into `lib/providers/generated/`.
|
|
||||||
|
|
||||||
### Database (Drift/SQLite)
|
|
||||||
|
|
||||||
Type-safe SQLite via Drift in `lib/database/`. Current schema version is 2. Tables are `Profiles`, `Scripts`, `Rules`,
|
|
||||||
`ProfileRuleLinks` (`profile_rule_mapping`), `ProxyGroups`, and `IconRecords` (`icon_records`). Rule scenes distinguish
|
|
||||||
global added rules, profile added rules, profile custom rules, and disabled links. Uses fractional indexing for rule and
|
|
||||||
proxy-group ordering.
|
|
||||||
|
|
||||||
Generated Drift output lives in `lib/database/generated/database.g.dart`. After schema changes, run code generation and
|
|
||||||
add/update focused database tests under `test/database/` when converter or migration behavior changes.
|
|
||||||
|
|
||||||
### Manager Stack (Widget Tree)
|
|
||||||
|
|
||||||
Managers are nested InheritedWidgets/StatefulWidgets in `lib/application.dart`:
|
|
||||||
|
|
||||||
```
|
|
||||||
AppEnvManager > StatusManager > ThemeManager
|
|
||||||
> [Desktop: WindowManager > TrayManager > HotKeyManager > ProxyManager]
|
|
||||||
> ConnectivityManager > CoreManager > AppStateManager
|
|
||||||
> [Mobile: AndroidManager > VpnManager | Desktop: WindowHeaderContainer]
|
|
||||||
```
|
|
||||||
|
|
||||||
Each manager in `lib/manager/` handles a specific platform concern. Desktop-only managers are conditionally inserted.
|
|
||||||
|
|
||||||
### Core Controller + Actions
|
|
||||||
|
|
||||||
`lib/core/controller.dart` (`CoreController`) is a singleton facade over `CoreHandlerInterface`. All 25+ public methods
|
|
||||||
delegate to the platform-specific interface (Android FFI or desktop socket). Has `@visibleForTesting` constructor and
|
|
||||||
`resetInstance()` for test injection.
|
|
||||||
|
|
||||||
Business logic lives in Riverpod notifier classes in `lib/providers/action.dart` (~960 lines, should be split):
|
|
||||||
|
|
||||||
- `CommonAction` — update check, common UI operations
|
|
||||||
- `SetupAction` — config setup, TUN management
|
|
||||||
- `BackupAction` — backup/restore with WebDAV sync
|
|
||||||
- `CoreAction` — core lifecycle (init, connect, restart, shutdown)
|
|
||||||
- `SystemAction` — system integration (tray, exit, brightness)
|
|
||||||
- `StoreAction` — profile storage operations
|
|
||||||
- `ThemeAction` — theme state updates
|
|
||||||
- `ProxiesAction` — group management, proxy selection
|
|
||||||
- `ProfilesAction` — profile CRUD, auto-update, import
|
|
||||||
|
|
||||||
### Platform Managers (`lib/manager/`)
|
|
||||||
|
|
||||||
Desktop: `WindowManager`, `TrayManager`, `HotKeyManager`, `ProxyManager`
|
|
||||||
Mobile: `AndroidManager`, `TileManager`, `VpnManager`
|
|
||||||
Shared: `ConnectivityManager`, `CoreManager`, `AppStateManager`, `StatusManager`, `ThemeManager`
|
|
||||||
|
|
||||||
### Build System
|
|
||||||
|
|
||||||
`setup.dart` (project root) is the release build orchestrator:
|
|
||||||
|
|
||||||
1. On Windows, pre-builds Go core via `dart run build_tool windows` and reads `core_sha256.json`
|
|
||||||
2. Writes `env.json` (APP_ENV)
|
|
||||||
3. Passes SHA256 as `--dart-define=CORE_SHA256=$val` (compile-time embedded, secure; Windows only)
|
|
||||||
4. Activates `flutter_distributor` for packaging
|
|
||||||
|
|
||||||
Go core building is handled by `build_tool`, a standalone Dart CLI in `plugins/setup/buildkit/build_tool/`.
|
|
||||||
Platform build hooks inside `flutter build` trigger `build_tool` automatically:
|
|
||||||
|
|
||||||
- **macOS:** podspec script phase → `build_pod.sh` → `build_tool macos`
|
|
||||||
- **Linux:** CMake include → `buildkit/cmake/buildkit.cmake` → `build_tool linux`
|
|
||||||
- **Windows:** CMake include → `buildkit/cmake/buildkit.cmake` → `build_tool windows` (debug: `--dev` via `CMAKE_BUILD_TYPE`)
|
|
||||||
- **Android:** Gradle include → `buildkit/gradle/plugin.gradle` → `build_tool android`
|
|
||||||
|
|
||||||
**Windows helper auth (release):** Core SHA256 is embedded in both the Flutter app (`--dart-define`) and the Rust
|
|
||||||
helper (`TOKEN` env var during cargo build). The Dart app pings the helper and verifies the token matches.
|
|
||||||
|
|
||||||
**Windows helper auth (debug):** The Rust helper skips token verification when built in debug mode
|
|
||||||
(`cfg!(debug_assertions)`), so `flutter run` works without any SHA256 dance.
|
|
||||||
|
|
||||||
`plugins/setup/` is an FFI plugin that exists solely as a build harness — it carries no Dart API, only platform build hooks
|
|
||||||
(podspec, CMake, Gradle) that trigger Go compilation. Windows builds also compile a Rust helper (`services/helper/`) via
|
|
||||||
`RustBuilder`.
|
|
||||||
|
|
||||||
Build configuration defaults live in `build_tool/lib/src/options.dart` and can be overridden via `build_config.yaml`
|
|
||||||
in the project root.
|
|
||||||
|
|
||||||
Architecture detection is automatic (host arch via `uname -m` on Unix, `PROCESSOR_ARCHITECTURE` on Windows). The
|
|
||||||
`--description` flag passed to flutter_distributor adds arch suffix to artifact names (e.g.,
|
|
||||||
`FlClash-0.8.93-macos-arm64.dmg`).
|
|
||||||
|
|
||||||
### Local Plugins (`plugins/`)
|
|
||||||
|
|
||||||
- `setup` - Build harness FFI plugin (triggers Go/Rust compilation per platform)
|
|
||||||
- `proxy` - System proxy configuration
|
|
||||||
- `rust_api` - Flutter Rust Bridge FFI plugin (named pipe / local socket communication)
|
|
||||||
- `tray_manager` - System tray (forked/custom)
|
|
||||||
- `wifi_ssid` - Wi-Fi SSID detection
|
|
||||||
- `window_ext` - Window extensions
|
|
||||||
- `flutter_distributor` - App packaging/distribution
|
|
||||||
|
|
||||||
### Rust Helper Service (`services/helper/`)
|
|
||||||
|
|
||||||
Windows-only privileged helper for starting the core as admin and managing TUN. Built with
|
|
||||||
`cargo build --release --features windows-service`. Token-based auth with Flutter app.
|
|
||||||
|
|
||||||
### Localization
|
|
||||||
|
|
||||||
ARB files in `arb/`. Generated via `flutter_intl` into `lib/l10n/`. Use `AppLocalizations.of(context)!` for strings.
|
|
||||||
|
|
||||||
**Supported locales:** `en`, `zh_CN`, `ja`, `ru`
|
|
||||||
|
|
||||||
**Access patterns:**
|
|
||||||
|
|
||||||
- In widgets with BuildContext: `context.appLocalizations.key` (import `common.dart`)
|
|
||||||
- In controllers/providers/non-widget code: `currentAppLocalizations.key` (import `app_localizations.dart`)
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
# CLAUDE.md - Claude Code instructions
|
# CLAUDE.md
|
||||||
|
|
||||||
Please read AGENTS.md for all project guidelines and conventions.
|
This repository uses [AGENTS.md](AGENTS.md) as the canonical agent entry point.
|
||||||
|
Read that file first, then follow the `.agents/` references it routes to.
|
||||||
@AGENTS.md
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
SHELL := /bin/bash
|
||||||
|
|
||||||
|
PLATFORM ?= macos
|
||||||
|
BUILDKIT := plugins/setup/buildkit/run_build_tool.sh
|
||||||
|
ARCH_ARG := $(if $(ARCH),--arch $(ARCH),)
|
||||||
|
TARGET_PLATFORM_ARG := $(if $(TARGET_PLATFORM),--target-platform $(TARGET_PLATFORM),)
|
||||||
|
|
||||||
|
.PHONY: help submodules core core-macos core-linux core-windows core-android
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo 'make core # build macOS core by default'
|
||||||
|
@echo 'make core PLATFORM=linux ARCH=amd64'
|
||||||
|
@echo 'make core-macos ARCH=arm64'
|
||||||
|
@echo 'make core-android ARCH=arm64'
|
||||||
|
@echo 'make core-android TARGET_PLATFORM=android-arm64'
|
||||||
|
|
||||||
|
submodules:
|
||||||
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
core:
|
||||||
|
bash $(BUILDKIT) $(PLATFORM) $(ARCH_ARG) $(TARGET_PLATFORM_ARG)
|
||||||
|
|
||||||
|
core-macos:
|
||||||
|
$(MAKE) core PLATFORM=macos
|
||||||
|
|
||||||
|
core-linux:
|
||||||
|
$(MAKE) core PLATFORM=linux
|
||||||
|
|
||||||
|
core-windows:
|
||||||
|
$(MAKE) core PLATFORM=windows
|
||||||
|
|
||||||
|
core-android:
|
||||||
|
$(MAKE) core PLATFORM=android
|
||||||
@@ -61,6 +61,13 @@ Support the following actions
|
|||||||
|
|
||||||
<a href="https://chen08209.github.io/FlClash-fdroid-repo/repo?fingerprint=789D6D32668712EF7672F9E58DEEB15FBD6DCEEC5AE7A4371EA72F2AAE8A12FD"><img alt="Get it on F-Droid" src="snapshots/get-it-on-fdroid.svg" width="200px"/></a> <a href="https://github.com/chen08209/FlClash/releases"><img alt="Get it on GitHub" src="snapshots/get-it-on-github.svg" width="200px"/></a>
|
<a href="https://chen08209.github.io/FlClash-fdroid-repo/repo?fingerprint=789D6D32668712EF7672F9E58DEEB15FBD6DCEEC5AE7A4371EA72F2AAE8A12FD"><img alt="Get it on F-Droid" src="snapshots/get-it-on-fdroid.svg" width="200px"/></a> <a href="https://github.com/chen08209/FlClash/releases"><img alt="Get it on GitHub" src="snapshots/get-it-on-github.svg" width="200px"/></a>
|
||||||
|
|
||||||
|
### Homebrew
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew tap chen08209/tap
|
||||||
|
brew install --cask flclash
|
||||||
|
```
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
1. Update submodules
|
1. Update submodules
|
||||||
@@ -129,4 +136,4 @@ The easiest way to support developers is to click on the star (⭐) at the top o
|
|||||||
<a href="https://api.star-history.com/svg?repos=chen08209/FlClash&Date">
|
<a href="https://api.star-history.com/svg?repos=chen08209/FlClash&Date">
|
||||||
<img alt="start" width=50% src="https://api.star-history.com/svg?repos=chen08209/FlClash&Date"/>
|
<img alt="start" width=50% src="https://api.star-history.com/svg?repos=chen08209/FlClash&Date"/>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -61,6 +61,13 @@ on Mobile:
|
|||||||
|
|
||||||
<a href="https://chen08209.github.io/FlClash-fdroid-repo/repo?fingerprint=789D6D32668712EF7672F9E58DEEB15FBD6DCEEC5AE7A4371EA72F2AAE8A12FD"><img alt="Get it on F-Droid" src="snapshots/get-it-on-fdroid.svg" width="200px"/></a> <a href="https://github.com/chen08209/FlClash/releases"><img alt="Get it on GitHub" src="snapshots/get-it-on-github.svg" width="200px"/></a>
|
<a href="https://chen08209.github.io/FlClash-fdroid-repo/repo?fingerprint=789D6D32668712EF7672F9E58DEEB15FBD6DCEEC5AE7A4371EA72F2AAE8A12FD"><img alt="Get it on F-Droid" src="snapshots/get-it-on-fdroid.svg" width="200px"/></a> <a href="https://github.com/chen08209/FlClash/releases"><img alt="Get it on GitHub" src="snapshots/get-it-on-github.svg" width="200px"/></a>
|
||||||
|
|
||||||
|
### Homebrew
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew tap chen08209/tap
|
||||||
|
brew install --cask flclash
|
||||||
|
```
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
1. 更新 submodules
|
1. 更新 submodules
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ import java.util.Properties
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("kotlin-android")
|
|
||||||
id("dev.flutter.flutter-gradle-plugin")
|
id("dev.flutter.flutter-gradle-plugin")
|
||||||
id("com.google.gms.google-services")
|
id("com.google.gms.google-services")
|
||||||
id("com.google.firebase.crashlytics")
|
id("com.google.firebase.crashlytics")
|
||||||
}
|
}
|
||||||
|
|
||||||
val localPropertiesFile = rootProject.file("local.properties")
|
|
||||||
val localProperties = Properties().apply {
|
val localProperties = Properties().apply {
|
||||||
|
val localPropertiesFile = rootProject.file("local.properties")
|
||||||
if (localPropertiesFile.exists()) {
|
if (localPropertiesFile.exists()) {
|
||||||
localPropertiesFile.inputStream().use { load(it) }
|
localPropertiesFile.inputStream().use { load(it) }
|
||||||
}
|
}
|
||||||
@@ -106,4 +105,4 @@ dependencies {
|
|||||||
implementation(platform(libs.firebase.bom))
|
implementation(platform(libs.firebase.bom))
|
||||||
implementation(libs.firebase.crashlytics.ndk)
|
implementation(libs.firebase.crashlytics.ndk)
|
||||||
implementation(libs.firebase.analytics)
|
implementation(libs.firebase.analytics)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,25 @@ subprojects {
|
|||||||
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
||||||
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
project.evaluationDependsOn(":app")
|
project.evaluationDependsOn(":app")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
allprojects {
|
||||||
|
tasks.withType<JavaCompile>().configureEach {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17.toString()
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17.toString()
|
||||||
|
}
|
||||||
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
||||||
|
compilerOptions {
|
||||||
|
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tasks.register<Delete>("clean") {
|
tasks.register<Delete>("clean") {
|
||||||
delete(rootProject.layout.buildDirectory)
|
delete(rootProject.layout.buildDirectory)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.library")
|
id("com.android.library")
|
||||||
id("org.jetbrains.kotlin.android")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -42,4 +41,4 @@ dependencies {
|
|||||||
implementation(platform(libs.firebase.bom))
|
implementation(platform(libs.firebase.bom))
|
||||||
implementation(libs.firebase.crashlytics.ndk)
|
implementation(libs.firebase.crashlytics.ndk)
|
||||||
implementation(libs.firebase.analytics)
|
implementation(libs.firebase.analytics)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.library")
|
id("com.android.library")
|
||||||
id("org.jetbrains.kotlin.android")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
org.gradle.jvmargs=-Xmx4G
|
org.gradle.jvmargs=-Xmx4G
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
# This builtInKotlin flag was added automatically by Flutter migrator
|
||||||
|
android.builtInKotlin=false
|
||||||
|
# This newDsl flag was added automatically by Flutter migrator
|
||||||
|
android.newDsl=false
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
#agp = "8.10.1"
|
#agp = "8.10.1"
|
||||||
firebaseBom = "34.2.0"
|
firebaseBom = "34.15.0"
|
||||||
minSdk = "23"
|
minSdk = "23"
|
||||||
targetSdk = "36"
|
targetSdk = "36"
|
||||||
compileSdk = "36"
|
compileSdk = "36"
|
||||||
@@ -9,13 +9,12 @@ coreKtx = "1.17.0"
|
|||||||
annotationJvm = "1.9.1"
|
annotationJvm = "1.9.1"
|
||||||
coreSplashscreen = "1.0.1"
|
coreSplashscreen = "1.0.1"
|
||||||
gson = "2.13.1"
|
gson = "2.13.1"
|
||||||
kotlin = "2.2.10"
|
kotlin = "2.2.20"
|
||||||
smaliDexlib2 = "3.0.9"
|
smaliDexlib2 = "3.0.9"
|
||||||
firebaseCrashlyticsKtx = "20.0.1"
|
firebaseCrashlyticsKtx = "20.0.6"
|
||||||
firebaseCommonKtx = "22.0.0"
|
firebaseCommonKtx = "22.1.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
build-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
|
||||||
androidx-core = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
|
androidx-core = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
|
||||||
annotation-jvm = { module = "androidx.annotation:annotation-jvm", version.ref = "annotationJvm" }
|
annotation-jvm = { module = "androidx.annotation:annotation-jvm", version.ref = "annotationJvm" }
|
||||||
core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" }
|
core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" }
|
||||||
@@ -25,4 +24,4 @@ firebase-crashlytics-ndk = { module = "com.google.firebase:firebase-crashlytics-
|
|||||||
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||||
smali-dexlib2 = { module = "com.android.tools.smali:smali-dexlib2", version.ref = "smaliDexlib2" }
|
smali-dexlib2 = { module = "com.android.tools.smali:smali-dexlib2", version.ref = "smaliDexlib2" }
|
||||||
firebase-crashlytics-ktx = { group = "com.google.firebase", name = "firebase-crashlytics-ktx", version.ref = "firebaseCrashlyticsKtx" }
|
firebase-crashlytics-ktx = { group = "com.google.firebase", name = "firebase-crashlytics-ktx", version.ref = "firebaseCrashlyticsKtx" }
|
||||||
firebase-common-ktx = { group = "com.google.firebase", name = "firebase-common-ktx", version.ref = "firebaseCommonKtx" }
|
firebase-common-ktx = { group = "com.google.firebase", name = "firebase-common-ktx", version.ref = "firebaseCommonKtx" }
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-all.zip
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.library")
|
id("com.android.library")
|
||||||
id("org.jetbrains.kotlin.android")
|
|
||||||
id("kotlin-parcelize")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -45,4 +43,4 @@ dependencies {
|
|||||||
implementation(project(":common"))
|
implementation(project(":common"))
|
||||||
implementation(libs.gson)
|
implementation(libs.gson)
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,36 @@
|
|||||||
package com.follow.clash.service.models
|
package com.follow.clash.service.models
|
||||||
|
|
||||||
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.parcelize.Parcelize
|
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data class NotificationParams(
|
data class NotificationParams(
|
||||||
val title: String = "FlClash",
|
val title: String = "FlClash",
|
||||||
val stopText: String = "STOP",
|
val stopText: String = "STOP",
|
||||||
val onlyStatisticsProxy: Boolean = false,
|
val onlyStatisticsProxy: Boolean = false,
|
||||||
) : Parcelable
|
) : Parcelable {
|
||||||
|
constructor(parcel: Parcel) : this(
|
||||||
|
title = parcel.readString() ?: "FlClash",
|
||||||
|
stopText = parcel.readString() ?: "STOP",
|
||||||
|
onlyStatisticsProxy = parcel.readByte() != 0.toByte(),
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
|
parcel.writeString(title)
|
||||||
|
parcel.writeString(stopText)
|
||||||
|
parcel.writeByte(if (onlyStatisticsProxy) 1.toByte() else 0.toByte())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun describeContents(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object CREATOR : Parcelable.Creator<NotificationParams> {
|
||||||
|
override fun createFromParcel(parcel: Parcel): NotificationParams {
|
||||||
|
return NotificationParams(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<NotificationParams?> {
|
||||||
|
return arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,19 +1,45 @@
|
|||||||
package com.follow.clash.service.models
|
package com.follow.clash.service.models
|
||||||
|
|
||||||
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import com.follow.clash.common.AccessControlMode
|
import com.follow.clash.common.AccessControlMode
|
||||||
import kotlinx.parcelize.Parcelize
|
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data class AccessControlProps(
|
data class AccessControlProps(
|
||||||
val enable: Boolean,
|
val enable: Boolean,
|
||||||
val mode: AccessControlMode,
|
val mode: AccessControlMode,
|
||||||
val acceptList: List<String>,
|
val acceptList: List<String>,
|
||||||
val rejectList: List<String>,
|
val rejectList: List<String>,
|
||||||
) : Parcelable
|
) : Parcelable {
|
||||||
|
constructor(parcel: Parcel) : this(
|
||||||
|
enable = parcel.readByte() != 0.toByte(),
|
||||||
|
mode = AccessControlMode.valueOf(parcel.readString() ?: AccessControlMode.ACCEPT_SELECTED.name),
|
||||||
|
acceptList = parcel.createStringArrayList() ?: emptyList(),
|
||||||
|
rejectList = parcel.createStringArrayList() ?: emptyList(),
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
|
parcel.writeByte(if (enable) 1.toByte() else 0.toByte())
|
||||||
|
parcel.writeString(mode.name)
|
||||||
|
parcel.writeStringList(acceptList)
|
||||||
|
parcel.writeStringList(rejectList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun describeContents(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object CREATOR : Parcelable.Creator<AccessControlProps> {
|
||||||
|
override fun createFromParcel(parcel: Parcel): AccessControlProps {
|
||||||
|
return AccessControlProps(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<AccessControlProps?> {
|
||||||
|
return arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data class VpnOptions(
|
data class VpnOptions(
|
||||||
val enable: Boolean,
|
val enable: Boolean,
|
||||||
val port: Int,
|
val port: Int,
|
||||||
@@ -25,7 +51,59 @@ data class VpnOptions(
|
|||||||
val bypassDomain: List<String>,
|
val bypassDomain: List<String>,
|
||||||
val stack: String,
|
val stack: String,
|
||||||
val routeAddress: List<String>,
|
val routeAddress: List<String>,
|
||||||
) : Parcelable
|
) : Parcelable {
|
||||||
|
constructor(parcel: Parcel) : this(
|
||||||
|
enable = parcel.readByte() != 0.toByte(),
|
||||||
|
port = parcel.readInt(),
|
||||||
|
ipv6 = parcel.readByte() != 0.toByte(),
|
||||||
|
dnsHijacking = parcel.readByte() != 0.toByte(),
|
||||||
|
accessControlProps = readAccessControlProps(parcel),
|
||||||
|
allowBypass = parcel.readByte() != 0.toByte(),
|
||||||
|
systemProxy = parcel.readByte() != 0.toByte(),
|
||||||
|
bypassDomain = parcel.createStringArrayList() ?: emptyList(),
|
||||||
|
stack = parcel.readString() ?: "",
|
||||||
|
routeAddress = parcel.createStringArrayList() ?: emptyList(),
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
|
parcel.writeByte(if (enable) 1.toByte() else 0.toByte())
|
||||||
|
parcel.writeInt(port)
|
||||||
|
parcel.writeByte(if (ipv6) 1.toByte() else 0.toByte())
|
||||||
|
parcel.writeByte(if (dnsHijacking) 1.toByte() else 0.toByte())
|
||||||
|
parcel.writeParcelable(accessControlProps, flags)
|
||||||
|
parcel.writeByte(if (allowBypass) 1.toByte() else 0.toByte())
|
||||||
|
parcel.writeByte(if (systemProxy) 1.toByte() else 0.toByte())
|
||||||
|
parcel.writeStringList(bypassDomain)
|
||||||
|
parcel.writeString(stack)
|
||||||
|
parcel.writeStringList(routeAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun describeContents(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object CREATOR : Parcelable.Creator<VpnOptions> {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
private fun readAccessControlProps(parcel: Parcel): AccessControlProps {
|
||||||
|
return parcel.readParcelable<AccessControlProps>(
|
||||||
|
AccessControlProps::class.java.classLoader,
|
||||||
|
) ?: AccessControlProps(
|
||||||
|
enable = false,
|
||||||
|
mode = AccessControlMode.ACCEPT_SELECTED,
|
||||||
|
acceptList = emptyList(),
|
||||||
|
rejectList = emptyList(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createFromParcel(parcel: Parcel): VpnOptions {
|
||||||
|
return VpnOptions(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<VpnOptions?> {
|
||||||
|
return arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class CIDR(val address: InetAddress, val prefixLength: Int)
|
data class CIDR(val address: InetAddress, val prefixLength: Int)
|
||||||
|
|
||||||
@@ -80,4 +158,4 @@ fun String.toCIDR(): CIDR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return CIDR(address, prefixLength)
|
return CIDR(address, prefixLength)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||||
id("com.android.application") version "8.12.2" apply false
|
id("com.android.application") version "9.0.1" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "2.2.10" apply false
|
id("org.jetbrains.kotlin.android") version "2.4.0" apply false
|
||||||
id("com.google.gms.google-services") version ("4.3.15") apply false
|
id("com.google.gms.google-services") version ("4.5.0") apply false
|
||||||
id("com.google.firebase.crashlytics") version ("2.8.1") apply false
|
id("com.google.firebase.crashlytics") version ("3.0.7") apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,7 @@
|
|||||||
"app": "App",
|
"app": "App",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
"systemProxyDesc": "Attach HTTP proxy to VpnService",
|
"systemProxyDesc": "Attach HTTP proxy to VpnService",
|
||||||
|
"userAgent": "User-Agent",
|
||||||
"unifiedDelay": "Unified delay",
|
"unifiedDelay": "Unified delay",
|
||||||
"unifiedDelayDesc": "Remove extra delays such as handshaking",
|
"unifiedDelayDesc": "Remove extra delays such as handshaking",
|
||||||
"tcpConcurrent": "TCP concurrent",
|
"tcpConcurrent": "TCP concurrent",
|
||||||
@@ -537,5 +538,17 @@
|
|||||||
"editSsid": "Edit SSID",
|
"editSsid": "Edit SSID",
|
||||||
"authorized": "Authorized",
|
"authorized": "Authorized",
|
||||||
"tapToAuthorize": "Tap to authorize",
|
"tapToAuthorize": "Tap to authorize",
|
||||||
"suspended": "Suspended..."
|
"suspended": "Suspended...",
|
||||||
|
"geoOptions": "Geo Options",
|
||||||
|
"geoAutoUpdate": "Auto Update",
|
||||||
|
"geoAutoUpdateInterval": "Auto Update Interval",
|
||||||
|
"geoAutoUpdateIntervalTip": "Auto update interval must be greater than 0",
|
||||||
|
"hours": "hours",
|
||||||
|
"hoursCount": "{count} hours",
|
||||||
|
"geoResources": "Geo Resources",
|
||||||
|
"geoUpdating": "Updating {name}...",
|
||||||
|
"geoSkipped": "{name} skipped",
|
||||||
|
"geoUpdated": "{name} updated",
|
||||||
|
"secondsCount": "{count} seconds",
|
||||||
|
"entriesCount": "{count} entries"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,7 @@
|
|||||||
"app": "アプリ",
|
"app": "アプリ",
|
||||||
"general": "一般",
|
"general": "一般",
|
||||||
"systemProxyDesc": "HTTPプロキシをVpnServiceに接続",
|
"systemProxyDesc": "HTTPプロキシをVpnServiceに接続",
|
||||||
|
"userAgent": "ユーザーエージェント",
|
||||||
"unifiedDelay": "統一遅延",
|
"unifiedDelay": "統一遅延",
|
||||||
"unifiedDelayDesc": "ハンドシェイクなどの余分な遅延を削除",
|
"unifiedDelayDesc": "ハンドシェイクなどの余分な遅延を削除",
|
||||||
"tcpConcurrent": "TCP並列処理",
|
"tcpConcurrent": "TCP並列処理",
|
||||||
@@ -537,5 +538,17 @@
|
|||||||
"editSsid": "SSIDを編集",
|
"editSsid": "SSIDを編集",
|
||||||
"authorized": "許可済み",
|
"authorized": "許可済み",
|
||||||
"tapToAuthorize": "タップして許可",
|
"tapToAuthorize": "タップして許可",
|
||||||
"suspended": "一時停止中..."
|
"suspended": "一時停止中...",
|
||||||
|
"geoOptions": "Geoオプション",
|
||||||
|
"geoAutoUpdate": "自動更新",
|
||||||
|
"geoAutoUpdateInterval": "自動更新間隔",
|
||||||
|
"geoAutoUpdateIntervalTip": "自動更新間隔は0より大きくなければなりません",
|
||||||
|
"hours": "時間",
|
||||||
|
"hoursCount": "{count} 時間",
|
||||||
|
"geoResources": "Geoリソース",
|
||||||
|
"geoUpdating": "{name}を更新中...",
|
||||||
|
"geoSkipped": "{name} スキップ済み",
|
||||||
|
"geoUpdated": "{name} 更新済み",
|
||||||
|
"secondsCount": "{count} 秒",
|
||||||
|
"entriesCount": "{count} エントリ"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,7 @@
|
|||||||
"app": "Приложение",
|
"app": "Приложение",
|
||||||
"general": "Общие",
|
"general": "Общие",
|
||||||
"systemProxyDesc": "Прикрепить HTTP-прокси к VpnService",
|
"systemProxyDesc": "Прикрепить HTTP-прокси к VpnService",
|
||||||
|
"userAgent": "User-Agent",
|
||||||
"unifiedDelay": "Унифицированная задержка",
|
"unifiedDelay": "Унифицированная задержка",
|
||||||
"unifiedDelayDesc": "Убрать дополнительные задержки, такие как рукопожатие",
|
"unifiedDelayDesc": "Убрать дополнительные задержки, такие как рукопожатие",
|
||||||
"tcpConcurrent": "TCP параллелизм",
|
"tcpConcurrent": "TCP параллелизм",
|
||||||
@@ -537,5 +538,17 @@
|
|||||||
"editSsid": "Изменить SSID",
|
"editSsid": "Изменить SSID",
|
||||||
"authorized": "Разрешено",
|
"authorized": "Разрешено",
|
||||||
"tapToAuthorize": "Нажмите, чтобы разрешить",
|
"tapToAuthorize": "Нажмите, чтобы разрешить",
|
||||||
"suspended": "Приостановлено..."
|
"suspended": "Приостановлено...",
|
||||||
|
"geoOptions": "Настройки Geo",
|
||||||
|
"geoAutoUpdate": "Автообновление",
|
||||||
|
"geoAutoUpdateInterval": "Интервал автообновления",
|
||||||
|
"geoAutoUpdateIntervalTip": "Интервал автообновления должен быть больше 0",
|
||||||
|
"hours": "часов",
|
||||||
|
"hoursCount": "{count} часов",
|
||||||
|
"geoResources": "Ресурсы Geo",
|
||||||
|
"geoUpdating": "Обновление {name}...",
|
||||||
|
"geoSkipped": "{name} пропущено",
|
||||||
|
"geoUpdated": "{name} обновлено",
|
||||||
|
"secondsCount": "{count} секунд",
|
||||||
|
"entriesCount": "{count} записей"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,7 @@
|
|||||||
"app": "应用",
|
"app": "应用",
|
||||||
"general": "常规",
|
"general": "常规",
|
||||||
"systemProxyDesc": "设置系统代理",
|
"systemProxyDesc": "设置系统代理",
|
||||||
|
"userAgent": "用户代理",
|
||||||
"unifiedDelay": "统一延迟",
|
"unifiedDelay": "统一延迟",
|
||||||
"unifiedDelayDesc": "去除握手等额外延迟",
|
"unifiedDelayDesc": "去除握手等额外延迟",
|
||||||
"tcpConcurrent": "TCP并发",
|
"tcpConcurrent": "TCP并发",
|
||||||
@@ -537,5 +538,17 @@
|
|||||||
"editSsid": "编辑SSID",
|
"editSsid": "编辑SSID",
|
||||||
"authorized": "已授权",
|
"authorized": "已授权",
|
||||||
"tapToAuthorize": "点击授权",
|
"tapToAuthorize": "点击授权",
|
||||||
"suspended": "挂起中..."
|
"suspended": "挂起中...",
|
||||||
|
"geoOptions": "Geo 选项",
|
||||||
|
"geoAutoUpdate": "自动更新",
|
||||||
|
"geoAutoUpdateInterval": "自动更新间隔",
|
||||||
|
"geoAutoUpdateIntervalTip": "自动更新间隔必须大于0",
|
||||||
|
"hours": "小时",
|
||||||
|
"hoursCount": "{count} 小时",
|
||||||
|
"geoResources": "Geo 资源",
|
||||||
|
"geoUpdating": "正在更新 {name}...",
|
||||||
|
"geoSkipped": "{name} 已跳过",
|
||||||
|
"geoUpdated": "{name} 已更新",
|
||||||
|
"secondsCount": "{count} 秒",
|
||||||
|
"entriesCount": "{count} 个条目"
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="108" height="108" viewBox="54 54 132 132" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<title>status_1</title>
|
||||||
|
<defs>
|
||||||
|
<filter id="glow-shadow" x="-50%" y="-50%" width="200%" height="200%">
|
||||||
|
<feDropShadow dx="0" dy="5" stdDeviation="5" flood-color="#0F172A" flood-opacity="0.12"/>
|
||||||
|
</filter>
|
||||||
|
<path id="shape-top"
|
||||||
|
d="M60.65,89.6L154.18,35.6A18,18 107.59,0 1,178.77 42.19L178.77,42.19A18,18 107.59,0 1,172.18 66.78L78.65,120.78A18,18 106.67,0 1,54.06 114.19L54.06,114.19A18,18 106.67,0 1,60.65 89.6z"/>
|
||||||
|
<path id="shape-mid"
|
||||||
|
d="M84.65,131.17L131.42,104.17A18,18 107.83,0 1,156 110.76L156,110.76A18,18 107.83,0 1,149.42 135.35L102.65,162.35A18,18 106.67,0 1,78.06 155.76L78.06,155.76A18,18 106.67,0 1,84.65 131.17z"/>
|
||||||
|
<path id="shape-bot"
|
||||||
|
d="M108.65,172.74L108.65,172.74A18,18 116.03,0 1,133.24 179.33L133.24,179.33A18,18 116.03,0 1,126.65 203.92L126.65,203.92A18,18 116.03,0 1,102.06 197.33L102.06,197.33A18,18 116.03,0 1,108.65 172.74z"/>
|
||||||
|
<mask id="cutout-mask">
|
||||||
|
<rect x="0" y="0" width="240" height="240" fill="white"/>
|
||||||
|
<g transform="translate(9.12, 9.12) scale(0.924, 0.924)">
|
||||||
|
<g transform="translate(45.96154, 43.846153) scale(0.63461536, 0.63461536)">
|
||||||
|
<use href="#shape-top" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
<use href="#shape-mid" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
<use href="#shape-bot" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</mask>
|
||||||
|
<linearGradient id="ring-grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#B8C0CD"/>
|
||||||
|
<stop offset="100%" stop-color="#D7DCE6"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<circle cx="120" cy="120" r="56" fill="none" stroke="url(#ring-grad)" stroke-width="16" mask="url(#cutout-mask)"
|
||||||
|
opacity="0.9"/>
|
||||||
|
|
||||||
|
|
||||||
|
<g transform="translate(9.12, 9.12) scale(0.924, 0.924)" filter="url(#glow-shadow)">
|
||||||
|
<g transform="translate(45.96154, 43.846153) scale(0.63461536, 0.63461536)">
|
||||||
|
<use href="#shape-top" fill="#7E8798"/>
|
||||||
|
<use href="#shape-mid" fill="#687386"/>
|
||||||
|
<use href="#shape-bot" fill="#98A3B6"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="108" height="108" viewBox="54 54 132 132" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<title>status_2</title>
|
||||||
|
<defs>
|
||||||
|
<filter id="glow-shadow" x="-50%" y="-50%" width="200%" height="200%">
|
||||||
|
<feDropShadow dx="0" dy="5" stdDeviation="5" flood-color="#0F172A" flood-opacity="0.12"/>
|
||||||
|
</filter>
|
||||||
|
<path id="shape-top" d="M60.65,89.6L154.18,35.6A18,18 107.59,0 1,178.77 42.19L178.77,42.19A18,18 107.59,0 1,172.18 66.78L78.65,120.78A18,18 106.67,0 1,54.06 114.19L54.06,114.19A18,18 106.67,0 1,60.65 89.6z"/>
|
||||||
|
<path id="shape-mid" d="M84.65,131.17L131.42,104.17A18,18 107.83,0 1,156 110.76L156,110.76A18,18 107.83,0 1,149.42 135.35L102.65,162.35A18,18 106.67,0 1,78.06 155.76L78.06,155.76A18,18 106.67,0 1,84.65 131.17z"/>
|
||||||
|
<path id="shape-bot" d="M108.65,172.74L108.65,172.74A18,18 116.03,0 1,133.24 179.33L133.24,179.33A18,18 116.03,0 1,126.65 203.92L126.65,203.92A18,18 116.03,0 1,102.06 197.33L102.06,197.33A18,18 116.03,0 1,108.65 172.74z"/>
|
||||||
|
<mask id="cutout-mask">
|
||||||
|
<rect x="0" y="0" width="240" height="240" fill="white"/>
|
||||||
|
<g transform="translate(15.77, 15.77) scale(0.86856, 0.86856)">
|
||||||
|
<g transform="translate(45.96154, 43.846153) scale(0.63461536, 0.63461536)">
|
||||||
|
<use href="#shape-top" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
<use href="#shape-mid" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
<use href="#shape-bot" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</mask>
|
||||||
|
<linearGradient id="ring-grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#72B7FF"/>
|
||||||
|
<stop offset="100%" stop-color="#8066FF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<circle cx="120" cy="120" r="64" fill="none" stroke="url(#ring-grad)" stroke-width="4" opacity="0.55"/>
|
||||||
|
<circle cx="120" cy="120" r="54" fill="none" stroke="url(#ring-grad)" stroke-width="12" mask="url(#cutout-mask)" opacity="1"/>
|
||||||
|
|
||||||
|
<g transform="translate(15.77, 15.77) scale(0.86856, 0.86856)" filter="url(#glow-shadow)">
|
||||||
|
<g transform="translate(45.96154, 43.846153) scale(0.63461536, 0.63461536)">
|
||||||
|
<use href="#shape-top" fill="#6666FB"/>
|
||||||
|
<use href="#shape-mid" fill="#2F71C4"/>
|
||||||
|
<use href="#shape-bot" fill="#53B7F2"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="108" height="108" viewBox="54 54 132 132" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<title>status_3</title>
|
||||||
|
<defs>
|
||||||
|
<filter id="glow-shadow" x="-50%" y="-50%" width="200%" height="200%">
|
||||||
|
<feDropShadow dx="0" dy="5" stdDeviation="5" flood-color="#0F172A" flood-opacity="0.12"/>
|
||||||
|
</filter>
|
||||||
|
<path id="shape-top"
|
||||||
|
d="M60.65,89.6L154.18,35.6A18,18 107.59,0 1,178.77 42.19L178.77,42.19A18,18 107.59,0 1,172.18 66.78L78.65,120.78A18,18 106.67,0 1,54.06 114.19L54.06,114.19A18,18 106.67,0 1,60.65 89.6z"/>
|
||||||
|
<path id="shape-mid"
|
||||||
|
d="M84.65,131.17L131.42,104.17A18,18 107.83,0 1,156 110.76L156,110.76A18,18 107.83,0 1,149.42 135.35L102.65,162.35A18,18 106.67,0 1,78.06 155.76L78.06,155.76A18,18 106.67,0 1,84.65 131.17z"/>
|
||||||
|
<path id="shape-bot"
|
||||||
|
d="M108.65,172.74L108.65,172.74A18,18 116.03,0 1,133.24 179.33L133.24,179.33A18,18 116.03,0 1,126.65 203.92L126.65,203.92A18,18 116.03,0 1,102.06 197.33L102.06,197.33A18,18 116.03,0 1,108.65 172.74z"/>
|
||||||
|
<mask id="cutout-mask">
|
||||||
|
<rect x="0" y="0" width="240" height="240" fill="white"/>
|
||||||
|
<g transform="translate(15.77, 15.77) scale(0.86856, 0.86856)">
|
||||||
|
<g transform="translate(45.96154, 43.846153) scale(0.63461536, 0.63461536)">
|
||||||
|
<use href="#shape-top" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
<use href="#shape-mid" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
<use href="#shape-bot" fill="black" stroke="black" stroke-width="25"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</mask>
|
||||||
|
<linearGradient id="ring-grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#22D3EE"/>
|
||||||
|
<stop offset="100%" stop-color="#7C5CFF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<circle cx="120" cy="120" r="64" fill="none" stroke="#FFB02E" stroke-width="4" opacity="0.55"/>
|
||||||
|
<circle cx="120" cy="120" r="54" fill="none" stroke="url(#ring-grad)" stroke-width="12" mask="url(#cutout-mask)"
|
||||||
|
opacity="1"/>
|
||||||
|
<circle cx="120" cy="120" r="42" fill="none" stroke="#FFD25F" stroke-width="3" opacity="0.78"/>
|
||||||
|
<g transform="translate(15.77, 15.77) scale(0.86856, 0.86856)" filter="url(#glow-shadow)">
|
||||||
|
<g transform="translate(45.96154, 43.846153) scale(0.63461536, 0.63461536)">
|
||||||
|
<use href="#shape-top" fill="#7367FF"/>
|
||||||
|
<use href="#shape-mid" fill="#1685D8"/>
|
||||||
|
<use href="#shape-bot" fill="#12C8FF"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -129,19 +129,11 @@ func handleAction(action *Action, result ActionResult) {
|
|||||||
case getExternalProviderMethod:
|
case getExternalProviderMethod:
|
||||||
externalProviderName := action.Data.(string)
|
externalProviderName := action.Data.(string)
|
||||||
result.success(handleGetExternalProvider(externalProviderName))
|
result.success(handleGetExternalProvider(externalProviderName))
|
||||||
|
return
|
||||||
case updateGeoDataMethod:
|
case updateGeoDataMethod:
|
||||||
paramsString := action.Data.(string)
|
geoType := action.Data.(string)
|
||||||
var params = map[string]string{}
|
handleUpdateGeoData(geoType)
|
||||||
err := json.Unmarshal([]byte(paramsString), ¶ms)
|
result.success("")
|
||||||
if err != nil {
|
|
||||||
result.success(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
geoType := params["geo-type"]
|
|
||||||
geoName := params["geo-name"]
|
|
||||||
handleUpdateGeoData(geoType, geoName, func(value string) {
|
|
||||||
result.success(value)
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
case updateExternalProviderMethod:
|
case updateExternalProviderMethod:
|
||||||
providerName := action.Data.(string)
|
providerName := action.Data.(string)
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/adapter"
|
"github.com/metacubex/mihomo/adapter"
|
||||||
"github.com/metacubex/mihomo/adapter/inbound"
|
"github.com/metacubex/mihomo/adapter/inbound"
|
||||||
"github.com/metacubex/mihomo/adapter/outboundgroup"
|
"github.com/metacubex/mihomo/adapter/outboundgroup"
|
||||||
@@ -13,6 +18,7 @@ import (
|
|||||||
"github.com/metacubex/mihomo/common/batch"
|
"github.com/metacubex/mihomo/common/batch"
|
||||||
"github.com/metacubex/mihomo/component/dialer"
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
"github.com/metacubex/mihomo/component/resolver"
|
"github.com/metacubex/mihomo/component/resolver"
|
||||||
|
"github.com/metacubex/mihomo/component/updater"
|
||||||
"github.com/metacubex/mihomo/config"
|
"github.com/metacubex/mihomo/config"
|
||||||
"github.com/metacubex/mihomo/constant"
|
"github.com/metacubex/mihomo/constant"
|
||||||
"github.com/metacubex/mihomo/constant/features"
|
"github.com/metacubex/mihomo/constant/features"
|
||||||
@@ -24,10 +30,6 @@ import (
|
|||||||
"github.com/metacubex/mihomo/log"
|
"github.com/metacubex/mihomo/log"
|
||||||
rp "github.com/metacubex/mihomo/rules/provider"
|
rp "github.com/metacubex/mihomo/rules/provider"
|
||||||
"github.com/metacubex/mihomo/tunnel"
|
"github.com/metacubex/mihomo/tunnel"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -234,7 +236,17 @@ func updateConfig(params *UpdateParams) {
|
|||||||
general.Tun.Stack = *params.Tun.Stack
|
general.Tun.Stack = *params.Tun.Stack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if params.GeoAutoUpdate != nil {
|
||||||
|
updater.SetGeoAutoUpdate(*params.GeoAutoUpdate)
|
||||||
|
}
|
||||||
|
if params.GeoUpdateInterval != nil {
|
||||||
|
updater.SetGeoUpdateInterval(*params.GeoUpdateInterval)
|
||||||
|
}
|
||||||
|
|
||||||
updateListeners()
|
updateListeners()
|
||||||
|
if updater.GeoAutoUpdate() {
|
||||||
|
updater.RegisterGeoUpdaterWithCancel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyConfig(params *SetupParams) error {
|
func applyConfig(params *SetupParams) error {
|
||||||
@@ -250,6 +262,9 @@ func applyConfig(params *SetupParams) error {
|
|||||||
hub.ApplyConfig(currentConfig)
|
hub.ApplyConfig(currentConfig)
|
||||||
patchSelectGroup(params.SelectedMap)
|
patchSelectGroup(params.SelectedMap)
|
||||||
updateListeners()
|
updateListeners()
|
||||||
|
if updater.GeoAutoUpdate() {
|
||||||
|
updater.RegisterGeoUpdaterWithCancel()
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ type UpdateParams struct {
|
|||||||
ExternalController *string `json:"external-controller"`
|
ExternalController *string `json:"external-controller"`
|
||||||
Interface *string `json:"interface-name"`
|
Interface *string `json:"interface-name"`
|
||||||
UnifiedDelay *bool `json:"unified-delay"`
|
UnifiedDelay *bool `json:"unified-delay"`
|
||||||
|
GeoAutoUpdate *bool `json:"geo-auto-update"`
|
||||||
|
GeoUpdateInterval *int `json:"geo-update-interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type tunSchema struct {
|
type tunSchema struct {
|
||||||
@@ -123,12 +125,20 @@ type Message struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LogMessage MessageType = "log"
|
LogMessage MessageType = "log"
|
||||||
DelayMessage MessageType = "delay"
|
DelayMessage MessageType = "delay"
|
||||||
RequestMessage MessageType = "request"
|
RequestMessage MessageType = "request"
|
||||||
LoadedMessage MessageType = "loaded"
|
LoadedMessage MessageType = "loaded"
|
||||||
|
GeoUpdateMessage MessageType = "geoUpdate"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type GeoUpdateStatus struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Updating bool `json:"updating"`
|
||||||
|
Skipped bool `json:"skipped,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
func (message *Message) Json() (string, error) {
|
func (message *Message) Json() (string, error) {
|
||||||
data, err := json.Marshal(message)
|
data, err := json.Marshal(message)
|
||||||
return string(data), err
|
return string(data), err
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ require (
|
|||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/akutz/memconn v0.1.0 // indirect
|
github.com/akutz/memconn v0.1.0 // indirect
|
||||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
|
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
|
||||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||||
|
github.com/bodgit/plumbing v1.3.0 // indirect
|
||||||
|
github.com/bodgit/windows v1.0.1 // indirect
|
||||||
github.com/coder/websocket v1.8.12 // indirect
|
github.com/coder/websocket v1.8.12 // indirect
|
||||||
github.com/coreos/go-iptables v0.8.0 // indirect
|
github.com/coreos/go-iptables v0.8.0 // indirect
|
||||||
github.com/dlclark/regexp2 v1.12.0 // indirect
|
github.com/dlclark/regexp2 v1.12.0 // indirect
|
||||||
github.com/dunglas/httpsfv v1.0.2 // indirect
|
github.com/dunglas/httpsfv v1.0.2 // indirect
|
||||||
github.com/enfein/mieru/v3 v3.31.0 // indirect
|
github.com/enfein/mieru/v3 v3.33.0 // indirect
|
||||||
github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 // indirect
|
github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 // indirect
|
||||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
||||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
||||||
@@ -42,6 +44,7 @@ require (
|
|||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
|
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
github.com/huin/goupnp v1.3.0 // indirect
|
github.com/huin/goupnp v1.3.0 // indirect
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 // indirect
|
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
@@ -51,6 +54,7 @@ require (
|
|||||||
github.com/klauspost/reedsolomon v1.12.3 // indirect
|
github.com/klauspost/reedsolomon v1.12.3 // indirect
|
||||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||||
github.com/mdlayher/socket v0.5.1 // indirect
|
github.com/mdlayher/socket v0.5.1 // indirect
|
||||||
|
github.com/metacubex/age v0.0.0-20260603010618-28d156b4ea78 // indirect
|
||||||
github.com/metacubex/amneziawg-go v0.0.0-20251104174305-5a0e9f7e361d // indirect
|
github.com/metacubex/amneziawg-go v0.0.0-20251104174305-5a0e9f7e361d // indirect
|
||||||
github.com/metacubex/ascon v0.1.0 // indirect
|
github.com/metacubex/ascon v0.1.0 // indirect
|
||||||
github.com/metacubex/bart v0.26.0 // indirect
|
github.com/metacubex/bart v0.26.0 // indirect
|
||||||
@@ -67,30 +71,31 @@ require (
|
|||||||
github.com/metacubex/hkdf v0.1.0 // indirect
|
github.com/metacubex/hkdf v0.1.0 // indirect
|
||||||
github.com/metacubex/hpke v0.1.0 // indirect
|
github.com/metacubex/hpke v0.1.0 // indirect
|
||||||
github.com/metacubex/http v0.1.6 // indirect
|
github.com/metacubex/http v0.1.6 // indirect
|
||||||
github.com/metacubex/jsonv2 v0.0.0-20260513175203-1c6abea7534c // indirect
|
github.com/metacubex/jsonv2 v0.0.0-20260518173308-f4597c22f1df // indirect
|
||||||
github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604 // indirect
|
github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604 // indirect
|
||||||
github.com/metacubex/mhurl v0.1.0 // indirect
|
github.com/metacubex/mhurl v0.1.0 // indirect
|
||||||
github.com/metacubex/mlkem v0.1.0 // indirect
|
github.com/metacubex/mlkem v0.1.0 // indirect
|
||||||
github.com/metacubex/nftables v0.0.0-20260426003805-208c2c1ba2cb // indirect
|
github.com/metacubex/nftables v0.0.0-20260426003805-208c2c1ba2cb // indirect
|
||||||
github.com/metacubex/qpack v0.6.0 // indirect
|
github.com/metacubex/qpack v0.6.0 // indirect
|
||||||
github.com/metacubex/quic-go v0.59.1-0.20260413153657-53bb22f2c306 // indirect
|
github.com/metacubex/quic-go v0.59.1-0.20260520020949-fcd18c7b6ace // indirect
|
||||||
github.com/metacubex/randv2 v0.2.0 // indirect
|
github.com/metacubex/randv2 v0.2.0 // indirect
|
||||||
github.com/metacubex/restls-client-go v0.1.7 // indirect
|
github.com/metacubex/restls-client-go v0.1.7 // indirect
|
||||||
|
github.com/metacubex/sevenzip v1.6.4 // indirect
|
||||||
github.com/metacubex/sing v0.5.7 // indirect
|
github.com/metacubex/sing v0.5.7 // indirect
|
||||||
github.com/metacubex/sing-mux v0.3.9 // indirect
|
github.com/metacubex/sing-mux v0.3.9 // indirect
|
||||||
github.com/metacubex/sing-quic v0.0.0-20260512151354-8475655be853 // indirect
|
github.com/metacubex/sing-quic v0.0.0-20260527143057-68e10a6afdc3 // indirect
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.12 // indirect
|
github.com/metacubex/sing-shadowsocks v0.2.12 // indirect
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.7 // indirect
|
github.com/metacubex/sing-shadowsocks2 v0.2.7 // indirect
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 // indirect
|
github.com/metacubex/sing-shadowtls v0.0.0-20260517015314-c11c36474edc // indirect
|
||||||
github.com/metacubex/sing-tun v0.4.18 // indirect
|
github.com/metacubex/sing-tun v0.4.20 // indirect
|
||||||
github.com/metacubex/sing-vmess v0.2.5 // indirect
|
github.com/metacubex/sing-vmess v0.2.5 // indirect
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20260507084707-690d479ec947 // indirect
|
github.com/metacubex/sing-wireguard v0.0.0-20260520151737-7e7c7c1b854c // indirect
|
||||||
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141 // indirect
|
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141 // indirect
|
||||||
github.com/metacubex/ssh v0.1.0 // indirect
|
github.com/metacubex/ssh v0.1.0 // indirect
|
||||||
github.com/metacubex/tailscale v0.0.0-20260516120020-a21c2c99dcbe // indirect
|
github.com/metacubex/tailscale v0.0.0-20260520011538-f23132fac4b7 // indirect
|
||||||
github.com/metacubex/tailscale-wireguard-go v0.0.0-20260513233728-8bc7ee255d04 // indirect
|
github.com/metacubex/tailscale-wireguard-go v0.0.0-20260521124654-e1bf77ef79af // indirect
|
||||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 // indirect
|
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 // indirect
|
||||||
github.com/metacubex/tls v0.1.5 // indirect
|
github.com/metacubex/tls v0.1.6 // indirect
|
||||||
github.com/metacubex/utls v1.8.4 // indirect
|
github.com/metacubex/utls v1.8.4 // indirect
|
||||||
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f // indirect
|
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f // indirect
|
||||||
github.com/metacubex/yamux v0.0.0-20250918083631-dd5f17c0be49 // indirect
|
github.com/metacubex/yamux v0.0.0-20250918083631-dd5f17c0be49 // indirect
|
||||||
@@ -100,8 +105,9 @@ require (
|
|||||||
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
||||||
github.com/openacid/low v0.1.21 // indirect
|
github.com/openacid/low v0.1.21 // indirect
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
|
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
github.com/pierrec/lz4/v4 v4.1.27 // indirect
|
||||||
github.com/pires/go-proxyproto v0.8.0 // indirect
|
github.com/pires/go-proxyproto v0.8.0 // indirect
|
||||||
|
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e // indirect
|
||||||
github.com/safchain/ethtool v0.3.0 // indirect
|
github.com/safchain/ethtool v0.3.0 // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
||||||
github.com/samber/lo v1.53.0 // indirect
|
github.com/samber/lo v1.53.0 // indirect
|
||||||
@@ -109,11 +115,13 @@ require (
|
|||||||
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect
|
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect
|
||||||
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
|
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
|
||||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||||
|
github.com/stangelandcl/ppmd v0.1.1 // indirect
|
||||||
github.com/tailscale/certstore v0.1.1-0.20260409135935-3638fb84b77d // indirect
|
github.com/tailscale/certstore v0.1.1-0.20260409135935-3638fb84b77d // indirect
|
||||||
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
|
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
|
||||||
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a // indirect
|
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a // indirect
|
||||||
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
|
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||||
|
github.com/ulikunitz/xz v0.5.15 // indirect
|
||||||
github.com/vishvananda/netns v0.0.5 // indirect
|
github.com/vishvananda/netns v0.0.5 // indirect
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
|
|||||||
@@ -12,11 +12,15 @@ github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A=
|
|||||||
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw=
|
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
|
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
||||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
||||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
|
github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU=
|
||||||
|
github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs=
|
||||||
|
github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4=
|
||||||
|
github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
|
||||||
github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4=
|
github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4=
|
||||||
github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
|
github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
|
||||||
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
||||||
@@ -30,8 +34,8 @@ github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz
|
|||||||
github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/dunglas/httpsfv v1.0.2 h1:iERDp/YAfnojSDJ7PW3dj1AReJz4MrwbECSSE59JWL0=
|
github.com/dunglas/httpsfv v1.0.2 h1:iERDp/YAfnojSDJ7PW3dj1AReJz4MrwbECSSE59JWL0=
|
||||||
github.com/dunglas/httpsfv v1.0.2/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg=
|
github.com/dunglas/httpsfv v1.0.2/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg=
|
||||||
github.com/enfein/mieru/v3 v3.31.0 h1:Fl2ocRCRXJzMygzdRjBHgqI996ZuIDHUmyQyovSf9sA=
|
github.com/enfein/mieru/v3 v3.33.0 h1:hv2jK8nqYHwpSG86U2rpZR2I8Aff1/J3ifRmd9NBbFc=
|
||||||
github.com/enfein/mieru/v3 v3.31.0/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM=
|
github.com/enfein/mieru/v3 v3.33.0/go.mod h1:zJBUCsi5rxyvHM8fjFf+GLaEl4OEjjBXr1s5F6Qd3hM=
|
||||||
github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 h1:kXYqH/sL8dS/FdoFjr12ePjnLPorPo2FsnrHNuXSDyo=
|
github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358 h1:kXYqH/sL8dS/FdoFjr12ePjnLPorPo2FsnrHNuXSDyo=
|
||||||
github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
|
github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
|
||||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
|
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
|
||||||
@@ -75,6 +79,8 @@ github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQu
|
|||||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||||
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
|
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
|
||||||
github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7spovjlY=
|
github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7spovjlY=
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||||
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
||||||
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4=
|
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4=
|
||||||
@@ -90,10 +96,16 @@ github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/4
|
|||||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/klauspost/reedsolomon v1.12.3 h1:tzUznbfc3OFwJaTebv/QdhnFf2Xvb7gZ24XaHLBPmdc=
|
github.com/klauspost/reedsolomon v1.12.3 h1:tzUznbfc3OFwJaTebv/QdhnFf2Xvb7gZ24XaHLBPmdc=
|
||||||
github.com/klauspost/reedsolomon v1.12.3/go.mod h1:3K5rXwABAvzGeR01r6pWZieUALXO/Tq7bFKGIb4m4WI=
|
github.com/klauspost/reedsolomon v1.12.3/go.mod h1:3K5rXwABAvzGeR01r6pWZieUALXO/Tq7bFKGIb4m4WI=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||||
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||||
|
github.com/metacubex/age v0.0.0-20260603010618-28d156b4ea78 h1:LqWr0vb9zDNuQS+jJd4fnRYk/SEI7KJ7TDe/L4WFK48=
|
||||||
|
github.com/metacubex/age v0.0.0-20260603010618-28d156b4ea78/go.mod h1:BTBG/iVY7rg3qq5WdVCg0GFk58CSvCDSbjy8I7kEx/c=
|
||||||
github.com/metacubex/amneziawg-go v0.0.0-20251104174305-5a0e9f7e361d h1:vAJ0ZT4aO803F1uw2roIA9yH7Sxzox34tVVyye1bz6c=
|
github.com/metacubex/amneziawg-go v0.0.0-20251104174305-5a0e9f7e361d h1:vAJ0ZT4aO803F1uw2roIA9yH7Sxzox34tVVyye1bz6c=
|
||||||
github.com/metacubex/amneziawg-go v0.0.0-20251104174305-5a0e9f7e361d/go.mod h1:MsM/5czONyXMJ3PRr5DbQ4O/BxzAnJWOIcJdLzW6qHY=
|
github.com/metacubex/amneziawg-go v0.0.0-20251104174305-5a0e9f7e361d/go.mod h1:MsM/5czONyXMJ3PRr5DbQ4O/BxzAnJWOIcJdLzW6qHY=
|
||||||
github.com/metacubex/ascon v0.1.0 h1:6ZWxmXYszT1XXtwkf6nxfFhc/OTtQ9R3Vyj1jN32lGM=
|
github.com/metacubex/ascon v0.1.0 h1:6ZWxmXYszT1XXtwkf6nxfFhc/OTtQ9R3Vyj1jN32lGM=
|
||||||
@@ -126,8 +138,8 @@ github.com/metacubex/hpke v0.1.0 h1:gu2jUNhraehWi0P/z5HX2md3d7L1FhPQE6/Q0E9r9xQ=
|
|||||||
github.com/metacubex/hpke v0.1.0/go.mod h1:vfDm6gfgrwlXUxKDkWbcE44hXtmc1uxLDm2BcR11b3U=
|
github.com/metacubex/hpke v0.1.0/go.mod h1:vfDm6gfgrwlXUxKDkWbcE44hXtmc1uxLDm2BcR11b3U=
|
||||||
github.com/metacubex/http v0.1.6 h1:xvXuvXMCMxCWMF5nEJF4yiKvXL+p2atWMzs37e80m1I=
|
github.com/metacubex/http v0.1.6 h1:xvXuvXMCMxCWMF5nEJF4yiKvXL+p2atWMzs37e80m1I=
|
||||||
github.com/metacubex/http v0.1.6/go.mod h1:Nxx0zZAo2AhRfanyL+fmmK6ACMtVsfpwIl1aFAik2Eg=
|
github.com/metacubex/http v0.1.6/go.mod h1:Nxx0zZAo2AhRfanyL+fmmK6ACMtVsfpwIl1aFAik2Eg=
|
||||||
github.com/metacubex/jsonv2 v0.0.0-20260513175203-1c6abea7534c h1:KGhBHDe6FveU0ury+9RyX329nclM1CHODa0Fi+uOAYM=
|
github.com/metacubex/jsonv2 v0.0.0-20260518173308-f4597c22f1df h1:S0vBzqjXok24VopstOgPd1JdgglW9tXehrqvwpQWbQ8=
|
||||||
github.com/metacubex/jsonv2 v0.0.0-20260513175203-1c6abea7534c/go.mod h1:F4sVXat6QjPXkNsKRDyyG3BhSkxPFFnRPEIwmmyCgbg=
|
github.com/metacubex/jsonv2 v0.0.0-20260518173308-f4597c22f1df/go.mod h1:F4sVXat6QjPXkNsKRDyyG3BhSkxPFFnRPEIwmmyCgbg=
|
||||||
github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604 h1:hJwCVlE3ojViC35MGHB+FBr8TuIf3BUFn2EQ1VIamsI=
|
github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604 h1:hJwCVlE3ojViC35MGHB+FBr8TuIf3BUFn2EQ1VIamsI=
|
||||||
github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604/go.mod h1:lpmN3m269b3V5jFCWtffqBLS4U3QQoIid9ugtO+OhVc=
|
github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604/go.mod h1:lpmN3m269b3V5jFCWtffqBLS4U3QQoIid9ugtO+OhVc=
|
||||||
github.com/metacubex/mhurl v0.1.0 h1:ZdW4Zxe3j3uJ89gNytOazHu6kbHn5owutN/VfXOI8GE=
|
github.com/metacubex/mhurl v0.1.0 h1:ZdW4Zxe3j3uJ89gNytOazHu6kbHn5owutN/VfXOI8GE=
|
||||||
@@ -138,42 +150,44 @@ github.com/metacubex/nftables v0.0.0-20260426003805-208c2c1ba2cb h1:wk6mHYPURSUv
|
|||||||
github.com/metacubex/nftables v0.0.0-20260426003805-208c2c1ba2cb/go.mod h1:73ZrCfhdkW4F2E2GAlta3km/S2RHhFNogCMtWZV2anQ=
|
github.com/metacubex/nftables v0.0.0-20260426003805-208c2c1ba2cb/go.mod h1:73ZrCfhdkW4F2E2GAlta3km/S2RHhFNogCMtWZV2anQ=
|
||||||
github.com/metacubex/qpack v0.6.0 h1:YqClGIMOpiRYLjV1qOs483Od08MdPgRnHjt90FuaAKw=
|
github.com/metacubex/qpack v0.6.0 h1:YqClGIMOpiRYLjV1qOs483Od08MdPgRnHjt90FuaAKw=
|
||||||
github.com/metacubex/qpack v0.6.0/go.mod h1:lKGSi7Xk94IMvHGOmxS9eIei3bvIqpOAImEBsaOwTkA=
|
github.com/metacubex/qpack v0.6.0/go.mod h1:lKGSi7Xk94IMvHGOmxS9eIei3bvIqpOAImEBsaOwTkA=
|
||||||
github.com/metacubex/quic-go v0.59.1-0.20260413153657-53bb22f2c306 h1:HlGLmLsWJMLSu0CMI9z/BmEnithB4oXM5Rom6/0Qxtg=
|
github.com/metacubex/quic-go v0.59.1-0.20260520020949-fcd18c7b6ace h1:KXacx7dp1GYVMgxezwXRt5BMsEbvAYuA6rPFUmdAvcQ=
|
||||||
github.com/metacubex/quic-go v0.59.1-0.20260413153657-53bb22f2c306/go.mod h1:oNzMrmylS897M3zSMuapIdwSwfq6F2qW01Z3NhVRJhk=
|
github.com/metacubex/quic-go v0.59.1-0.20260520020949-fcd18c7b6ace/go.mod h1:2YEQEvFrZ5V76oynMBDTlN+4fdnSHCa2uNJxv3cm1HU=
|
||||||
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||||
github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k=
|
github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k=
|
||||||
github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g=
|
github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g=
|
||||||
|
github.com/metacubex/sevenzip v1.6.4 h1:OIL+DeOeSAbKNsjqxcYUMiarRmX6Kaxakb0GT7E9Oik=
|
||||||
|
github.com/metacubex/sevenzip v1.6.4/go.mod h1:FP3X9bzFKj9wPxifGN9B3w2fIEicMjzKYIGIhnu+1pw=
|
||||||
github.com/metacubex/sing v0.5.7 h1:8OC+fhKFSv/l9ehEhJRaZZAOuthfZo68SteBVLe8QqM=
|
github.com/metacubex/sing v0.5.7 h1:8OC+fhKFSv/l9ehEhJRaZZAOuthfZo68SteBVLe8QqM=
|
||||||
github.com/metacubex/sing v0.5.7/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
github.com/metacubex/sing v0.5.7/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
||||||
github.com/metacubex/sing-mux v0.3.9 h1:/aoBD2+sK2qsXDlNDe3hkR0GZuFDtwIZhOeGUx9W0Yk=
|
github.com/metacubex/sing-mux v0.3.9 h1:/aoBD2+sK2qsXDlNDe3hkR0GZuFDtwIZhOeGUx9W0Yk=
|
||||||
github.com/metacubex/sing-mux v0.3.9/go.mod h1:8bT7ZKT3clRrJjYc/x5CRYibC1TX/bK73a3r3+2E+Fc=
|
github.com/metacubex/sing-mux v0.3.9/go.mod h1:8bT7ZKT3clRrJjYc/x5CRYibC1TX/bK73a3r3+2E+Fc=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20260512151354-8475655be853 h1:nZ5WNU6kjj6kBu4+2eMySFkUVGCop64rZnLMm+HPh8w=
|
github.com/metacubex/sing-quic v0.0.0-20260527143057-68e10a6afdc3 h1:PnMby5+kZXTl/CFDHfxMbMTaSRD+uMKMsrDYVQyAmX8=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20260512151354-8475655be853/go.mod h1:6ayFGfzzBE85csgQkM3gf4neFq6s0losHlPRSxY+nuk=
|
github.com/metacubex/sing-quic v0.0.0-20260527143057-68e10a6afdc3/go.mod h1:6ayFGfzzBE85csgQkM3gf4neFq6s0losHlPRSxY+nuk=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE=
|
github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU=
|
github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.7 h1:hSuuc0YpsfiqYqt1o+fP4m34BQz4e6wVj3PPBVhor3A=
|
github.com/metacubex/sing-shadowsocks2 v0.2.7 h1:hSuuc0YpsfiqYqt1o+fP4m34BQz4e6wVj3PPBVhor3A=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.7/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE=
|
github.com/metacubex/sing-shadowsocks2 v0.2.7/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE=
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI=
|
github.com/metacubex/sing-shadowtls v0.0.0-20260517015314-c11c36474edc h1:8wLoFfYQ88iGPL+krQ5tJsI8IAmkFjKpQL2q+y3pvss=
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E=
|
github.com/metacubex/sing-shadowtls v0.0.0-20260517015314-c11c36474edc/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E=
|
||||||
github.com/metacubex/sing-tun v0.4.18 h1:WRzAosG0YkT3aZq5RJWtF+RdCgeJ8EpooS5ZM1lkXo0=
|
github.com/metacubex/sing-tun v0.4.20 h1:xdupzizRoZKyDzP0l68WAx5Sk4ooiuT1GiWsiJyOGPw=
|
||||||
github.com/metacubex/sing-tun v0.4.18/go.mod h1:g4I/JNplDBhXLF+aQWgFbhNeJPSXQOWS9HvLeNvkgeA=
|
github.com/metacubex/sing-tun v0.4.20/go.mod h1:g4I/JNplDBhXLF+aQWgFbhNeJPSXQOWS9HvLeNvkgeA=
|
||||||
github.com/metacubex/sing-vmess v0.2.5 h1:m9Zt5I27lB9fmLMZfism9sH2LcnAfShZfwSkf6/KJoE=
|
github.com/metacubex/sing-vmess v0.2.5 h1:m9Zt5I27lB9fmLMZfism9sH2LcnAfShZfwSkf6/KJoE=
|
||||||
github.com/metacubex/sing-vmess v0.2.5/go.mod h1:AwtlzUgf8COe9tRYAKqWZ+leDH7p5U98a0ZUpYehl8Q=
|
github.com/metacubex/sing-vmess v0.2.5/go.mod h1:AwtlzUgf8COe9tRYAKqWZ+leDH7p5U98a0ZUpYehl8Q=
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20260507084707-690d479ec947 h1:IB03BvRQtvjWScyOK5jSQVJYY8osmZXHL+4VCEFMWcM=
|
github.com/metacubex/sing-wireguard v0.0.0-20260520151737-7e7c7c1b854c h1:tH9FuQW357zp2xAGzkoZTGpNGMVmEFZov0iV5M2S5ew=
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20260507084707-690d479ec947/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80=
|
github.com/metacubex/sing-wireguard v0.0.0-20260520151737-7e7c7c1b854c/go.mod h1:eQZDJTx+IH3k4mXqaOJ3VJ9h9ZqOl60F7TLi5wAU51Q=
|
||||||
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141 h1:DK2l6m2Fc85H2BhiAPgbJygiWhesPlfGmF+9Vw6ARdk=
|
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141 h1:DK2l6m2Fc85H2BhiAPgbJygiWhesPlfGmF+9Vw6ARdk=
|
||||||
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141/go.mod h1:/yI4OiGOSn0SURhZdJF3CbtPg3nwK700bG8TZLMBvAg=
|
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141/go.mod h1:/yI4OiGOSn0SURhZdJF3CbtPg3nwK700bG8TZLMBvAg=
|
||||||
github.com/metacubex/ssh v0.1.0 h1:iGfr99qk/eMHzUnQ/0bTxXT8+8SWqLSHBWDHoAhngzw=
|
github.com/metacubex/ssh v0.1.0 h1:iGfr99qk/eMHzUnQ/0bTxXT8+8SWqLSHBWDHoAhngzw=
|
||||||
github.com/metacubex/ssh v0.1.0/go.mod h1:NUtl0d+/f2cG9ECEpMM8iCVOpmggQlC13oLeDUONDlU=
|
github.com/metacubex/ssh v0.1.0/go.mod h1:NUtl0d+/f2cG9ECEpMM8iCVOpmggQlC13oLeDUONDlU=
|
||||||
github.com/metacubex/tailscale v0.0.0-20260516120020-a21c2c99dcbe h1:ZdAKshacNruZGuKTE8WMTuxyGgpv/LySLoE/EEmgF9c=
|
github.com/metacubex/tailscale v0.0.0-20260520011538-f23132fac4b7 h1:LoJR4NMyNKHeEJoeGDtcsao7sV0NRkzMeV5H/0J0MIE=
|
||||||
github.com/metacubex/tailscale v0.0.0-20260516120020-a21c2c99dcbe/go.mod h1:2G1V82OGXgxT7m7046GA80I9SlcvczljCK0C7NQ3c10=
|
github.com/metacubex/tailscale v0.0.0-20260520011538-f23132fac4b7/go.mod h1:MAo3HhE7968rIwmDvYTYE8xCsV4x+hLnkChdXeP3X4c=
|
||||||
github.com/metacubex/tailscale-wireguard-go v0.0.0-20260513233728-8bc7ee255d04 h1:zk+mDDSBl5lv80WWtaFUbpj8XLb7AhjCUbn2pB37N0U=
|
github.com/metacubex/tailscale-wireguard-go v0.0.0-20260521124654-e1bf77ef79af h1:c60IbBMUq2h1M2m7+grMJJmBmrObxL8SwvNtm6Ozbwk=
|
||||||
github.com/metacubex/tailscale-wireguard-go v0.0.0-20260513233728-8bc7ee255d04/go.mod h1:pKUKBy7IcQ5r0i66gWENHgxKvBn8tlgAGx0DZMq8h5M=
|
github.com/metacubex/tailscale-wireguard-go v0.0.0-20260521124654-e1bf77ef79af/go.mod h1:i3zLKytWkOnyT1i9OmiLevWvrN5J5HE1+yjE7UYNfcQ=
|
||||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 h1:H6TnfM12tOoTizYE/qBHH3nEuibIelmHI+BVSxVJr8o=
|
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 h1:H6TnfM12tOoTizYE/qBHH3nEuibIelmHI+BVSxVJr8o=
|
||||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||||
github.com/metacubex/tls v0.1.5 h1:ECcB83dj+zadnhlKcLnUUf1Sq6+vU0f/zoyU0+9oPTc=
|
github.com/metacubex/tls v0.1.6 h1:t2ubLneYa4ceyIC++54a57BLqZFA/QYUrhdjLk2GPwo=
|
||||||
github.com/metacubex/tls v0.1.5/go.mod h1:0XeVdL0cBw+8i5Hqy3lVeP9IyD/LFTq02ExvHM6rzEM=
|
github.com/metacubex/tls v0.1.6/go.mod h1:0XeVdL0cBw+8i5Hqy3lVeP9IyD/LFTq02ExvHM6rzEM=
|
||||||
github.com/metacubex/utls v1.8.4 h1:HmL9nUApDdWSkgUyodfwF6hSjtiwCGGdyhaSpEejKpg=
|
github.com/metacubex/utls v1.8.4 h1:HmL9nUApDdWSkgUyodfwF6hSjtiwCGGdyhaSpEejKpg=
|
||||||
github.com/metacubex/utls v1.8.4/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko=
|
github.com/metacubex/utls v1.8.4/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko=
|
||||||
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk=
|
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk=
|
||||||
@@ -195,13 +209,16 @@ github.com/openacid/must v0.1.3/go.mod h1:luPiXCuJlEo3UUFQngVQokV0MPGryeYvtCbQPs
|
|||||||
github.com/openacid/testkeys v0.1.6/go.mod h1:MfA7cACzBpbiwekivj8StqX0WIRmqlMsci1c37CA3Do=
|
github.com/openacid/testkeys v0.1.6/go.mod h1:MfA7cACzBpbiwekivj8StqX0WIRmqlMsci1c37CA3Do=
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
|
||||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.27 h1:+PhzhWDrjRj89TH2sw43nE3+4+W8lSxIuQadEHZyjUk=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.27/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
|
||||||
github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0=
|
github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0=
|
||||||
github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY=
|
github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e h1:dCWirM5F3wMY+cmRda/B1BiPsFtmzXqV9b0hLWtVBMs=
|
||||||
|
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e/go.mod h1:9leZcVcItj6m9/CfHY5Em/iBrCz7js8LcRQGTKEEv2M=
|
||||||
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
||||||
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
||||||
@@ -216,10 +233,19 @@ github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e h1:ur8uMsPIF
|
|||||||
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e/go.mod h1:+e5fBW3bpPyo+3uLo513gIUblc03egGjMM0+5GKbzK8=
|
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e/go.mod h1:+e5fBW3bpPyo+3uLo513gIUblc03egGjMM0+5GKbzK8=
|
||||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||||
|
github.com/stangelandcl/ppmd v0.1.1 h1:c25QazhlWUn5nmR1QOzafKhQxBicAr7GGCKER2aJ8H8=
|
||||||
|
github.com/stangelandcl/ppmd v0.1.1/go.mod h1:Rrv7M+/2P5jYr/GMLhBl7Ug3uJ1bUiVzr5LbbaV6xgY=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/tailscale/certstore v0.1.1-0.20260409135935-3638fb84b77d h1:JcGKBZAL7ePLwOhUdN8qGQZlP5GueEiIZwY7R62pejE=
|
github.com/tailscale/certstore v0.1.1-0.20260409135935-3638fb84b77d h1:JcGKBZAL7ePLwOhUdN8qGQZlP5GueEiIZwY7R62pejE=
|
||||||
@@ -232,6 +258,8 @@ github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc h1:24heQPtnFR+y
|
|||||||
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc/go.mod h1:f93CXfllFsO9ZQVq+Zocb1Gp4G5Fz0b0rXHLOzt/Djc=
|
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc/go.mod h1:f93CXfllFsO9ZQVq+Zocb1Gp4G5Fz0b0rXHLOzt/Djc=
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||||
|
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
|
||||||
|
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
@@ -245,6 +273,8 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
|||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
||||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
|
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
|
||||||
|
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||||
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
|
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
|
||||||
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
|
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
|
||||||
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7 h1:UNrDfkQqiEYzdMlNsVvBYOAJWZjdktqFE9tQh5BT2+4=
|
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7 h1:UNrDfkQqiEYzdMlNsVvBYOAJWZjdktqFE9tQh5BT2+4=
|
||||||
@@ -302,8 +332,9 @@ golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ
|
|||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -347,36 +347,22 @@ func handleGetExternalProvider(externalProviderName string) string {
|
|||||||
return string(data)
|
return string(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleUpdateGeoData(geoType string, geoName string, fn func(value string)) {
|
func handleUpdateGeoData(geoType string) {
|
||||||
go func() {
|
go func() {
|
||||||
path := constant.Path.Resolve(geoName)
|
|
||||||
switch geoType {
|
switch geoType {
|
||||||
case "MMDB":
|
case "MMDB":
|
||||||
err := updater.UpdateMMDBWithPath(path)
|
updater.UpdateMMDB()
|
||||||
if err != nil {
|
return
|
||||||
fn(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case "ASN":
|
case "ASN":
|
||||||
err := updater.UpdateASNWithPath(path)
|
updater.UpdateASN()
|
||||||
if err != nil {
|
return
|
||||||
fn(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case "GEOIP":
|
case "GEOIP":
|
||||||
err := updater.UpdateGeoIpWithPath(path)
|
updater.UpdateGeoIp()
|
||||||
if err != nil {
|
return
|
||||||
fn(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case "GEOSITE":
|
case "GEOSITE":
|
||||||
err := updater.UpdateGeoSiteWithPath(path)
|
updater.UpdateGeoSite()
|
||||||
if err != nil {
|
return
|
||||||
fn(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn("")
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,4 +554,18 @@ func init() {
|
|||||||
Data: providerName,
|
Data: providerName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
updater.GeoUpdateHook = func(geoType string, updating bool, skipped bool, updateErr error) {
|
||||||
|
status := GeoUpdateStatus{
|
||||||
|
Type: geoType,
|
||||||
|
Updating: updating,
|
||||||
|
Skipped: skipped,
|
||||||
|
}
|
||||||
|
if updateErr != nil {
|
||||||
|
status.Error = updateErr.Error()
|
||||||
|
}
|
||||||
|
sendMessage(Message{
|
||||||
|
Type: GeoUpdateMessage,
|
||||||
|
Data: status,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export 'future.dart';
|
|||||||
export 'http.dart';
|
export 'http.dart';
|
||||||
export 'icons.dart';
|
export 'icons.dart';
|
||||||
export 'indexing.dart';
|
export 'indexing.dart';
|
||||||
|
export 'input_limits.dart';
|
||||||
export 'iterable.dart';
|
export 'iterable.dart';
|
||||||
export 'javascript.dart';
|
export 'javascript.dart';
|
||||||
export 'keyboard.dart';
|
export 'keyboard.dart';
|
||||||
@@ -29,7 +30,6 @@ export 'package.dart';
|
|||||||
export 'path.dart';
|
export 'path.dart';
|
||||||
export 'permission.dart';
|
export 'permission.dart';
|
||||||
export 'picker.dart';
|
export 'picker.dart';
|
||||||
export 'pipe.dart';
|
|
||||||
export 'preferences.dart';
|
export 'preferences.dart';
|
||||||
export 'print.dart';
|
export 'print.dart';
|
||||||
export 'protocol.dart';
|
export 'protocol.dart';
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class FixedList<T> {
|
|||||||
final List<T> _list;
|
final List<T> _list;
|
||||||
|
|
||||||
FixedList(this.maxLength, {List<T>? list})
|
FixedList(this.maxLength, {List<T>? list})
|
||||||
: _list = (list ?? [])..truncate(maxLength);
|
: _list = (list ?? [])..truncate(maxLength);
|
||||||
|
|
||||||
void add(T item) {
|
void add(T item) {
|
||||||
_list.add(item);
|
_list.add(item);
|
||||||
@@ -25,10 +25,7 @@ class FixedList<T> {
|
|||||||
T operator [](int index) => _list[index];
|
T operator [](int index) => _list[index];
|
||||||
|
|
||||||
FixedList<T> copyWith() {
|
FixedList<T> copyWith() {
|
||||||
return FixedList(
|
return FixedList(maxLength, list: List.of(_list));
|
||||||
maxLength,
|
|
||||||
list: List.of(_list),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,10 +38,7 @@ class FixedMap<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
V updateCacheValue(K key, ValueCallback<V> callback) {
|
V updateCacheValue(K key, ValueCallback<V> callback) {
|
||||||
final realValue = _map.updateCacheValue(
|
final realValue = _map.updateCacheValue(key, callback);
|
||||||
key,
|
|
||||||
callback,
|
|
||||||
);
|
|
||||||
_adjustMap();
|
_adjustMap();
|
||||||
return realValue;
|
return realValue;
|
||||||
}
|
}
|
||||||
@@ -65,9 +59,7 @@ class FixedMap<K, V> {
|
|||||||
|
|
||||||
void _adjustMap() {
|
void _adjustMap() {
|
||||||
if (_map.length > maxLength) {
|
if (_map.length > maxLength) {
|
||||||
_map = Map.fromEntries(
|
_map = Map.fromEntries(map.entries.toList()..truncate(maxLength));
|
||||||
map.entries.toList()..truncate(maxLength),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
abstract final class TextInputLimits {
|
||||||
|
static const name = 64;
|
||||||
|
static const groupName = 64;
|
||||||
|
static const url = 2048;
|
||||||
|
static const uri = url;
|
||||||
|
static const iconUrl = url;
|
||||||
|
static const dnsServer = url;
|
||||||
|
static const hostValue = url;
|
||||||
|
static const userName = 128;
|
||||||
|
static const password = 512;
|
||||||
|
static const userAgent = 512;
|
||||||
|
static const fileName = 255;
|
||||||
|
static const port = 5;
|
||||||
|
static const number = 10;
|
||||||
|
static const interval = number;
|
||||||
|
static const search = 256;
|
||||||
|
static const rule = 1024;
|
||||||
|
static const filter = 1024;
|
||||||
|
static const status = 128;
|
||||||
|
static const dnsListen = 255;
|
||||||
|
static const domain = 512;
|
||||||
|
static const geoSite = 128;
|
||||||
|
static const geoIpCode = 16;
|
||||||
|
static const cidr = 64;
|
||||||
|
|
||||||
|
static List<TextInputFormatter> limit(int maxLength) {
|
||||||
|
return [LengthLimitingTextInputFormatter(maxLength)];
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<TextInputFormatter> digitsOnly(int maxLength) {
|
||||||
|
return [
|
||||||
|
FilteringTextInputFormatter.digitsOnly,
|
||||||
|
LengthLimitingTextInputFormatter(maxLength),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,6 +80,13 @@ extension ListExt<T> on List<T> {
|
|||||||
return newList;
|
return newList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<T> copyAndReorder(int oldIndex, int newIndex) {
|
||||||
|
final newList = List<T>.from(this);
|
||||||
|
final item = newList.removeAt(oldIndex);
|
||||||
|
newList.insert(newIndex, item);
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
List<T> safeSublist(int start, [int? end]) {
|
List<T> safeSublist(int start, [int? end]) {
|
||||||
if (start <= 0) return this;
|
if (start <= 0) return this;
|
||||||
if (start > length) return [];
|
if (start > length) return [];
|
||||||
|
|||||||
@@ -5,90 +5,90 @@ import 'system.dart';
|
|||||||
|
|
||||||
final Map<PhysicalKeyboardKey, String> _knownKeyLabels =
|
final Map<PhysicalKeyboardKey, String> _knownKeyLabels =
|
||||||
<PhysicalKeyboardKey, String>{
|
<PhysicalKeyboardKey, String>{
|
||||||
PhysicalKeyboardKey.keyA: 'A',
|
PhysicalKeyboardKey.keyA: 'A',
|
||||||
PhysicalKeyboardKey.keyB: 'B',
|
PhysicalKeyboardKey.keyB: 'B',
|
||||||
PhysicalKeyboardKey.keyC: 'C',
|
PhysicalKeyboardKey.keyC: 'C',
|
||||||
PhysicalKeyboardKey.keyD: 'D',
|
PhysicalKeyboardKey.keyD: 'D',
|
||||||
PhysicalKeyboardKey.keyE: 'E',
|
PhysicalKeyboardKey.keyE: 'E',
|
||||||
PhysicalKeyboardKey.keyF: 'F',
|
PhysicalKeyboardKey.keyF: 'F',
|
||||||
PhysicalKeyboardKey.keyG: 'G',
|
PhysicalKeyboardKey.keyG: 'G',
|
||||||
PhysicalKeyboardKey.keyH: 'H',
|
PhysicalKeyboardKey.keyH: 'H',
|
||||||
PhysicalKeyboardKey.keyI: 'I',
|
PhysicalKeyboardKey.keyI: 'I',
|
||||||
PhysicalKeyboardKey.keyJ: 'J',
|
PhysicalKeyboardKey.keyJ: 'J',
|
||||||
PhysicalKeyboardKey.keyK: 'K',
|
PhysicalKeyboardKey.keyK: 'K',
|
||||||
PhysicalKeyboardKey.keyL: 'L',
|
PhysicalKeyboardKey.keyL: 'L',
|
||||||
PhysicalKeyboardKey.keyM: 'M',
|
PhysicalKeyboardKey.keyM: 'M',
|
||||||
PhysicalKeyboardKey.keyN: 'N',
|
PhysicalKeyboardKey.keyN: 'N',
|
||||||
PhysicalKeyboardKey.keyO: 'O',
|
PhysicalKeyboardKey.keyO: 'O',
|
||||||
PhysicalKeyboardKey.keyP: 'P',
|
PhysicalKeyboardKey.keyP: 'P',
|
||||||
PhysicalKeyboardKey.keyQ: 'Q',
|
PhysicalKeyboardKey.keyQ: 'Q',
|
||||||
PhysicalKeyboardKey.keyR: 'R',
|
PhysicalKeyboardKey.keyR: 'R',
|
||||||
PhysicalKeyboardKey.keyS: 'S',
|
PhysicalKeyboardKey.keyS: 'S',
|
||||||
PhysicalKeyboardKey.keyT: 'T',
|
PhysicalKeyboardKey.keyT: 'T',
|
||||||
PhysicalKeyboardKey.keyU: 'U',
|
PhysicalKeyboardKey.keyU: 'U',
|
||||||
PhysicalKeyboardKey.keyV: 'V',
|
PhysicalKeyboardKey.keyV: 'V',
|
||||||
PhysicalKeyboardKey.keyW: 'W',
|
PhysicalKeyboardKey.keyW: 'W',
|
||||||
PhysicalKeyboardKey.keyX: 'X',
|
PhysicalKeyboardKey.keyX: 'X',
|
||||||
PhysicalKeyboardKey.keyY: 'Y',
|
PhysicalKeyboardKey.keyY: 'Y',
|
||||||
PhysicalKeyboardKey.keyZ: 'Z',
|
PhysicalKeyboardKey.keyZ: 'Z',
|
||||||
PhysicalKeyboardKey.digit1: '1',
|
PhysicalKeyboardKey.digit1: '1',
|
||||||
PhysicalKeyboardKey.digit2: '2',
|
PhysicalKeyboardKey.digit2: '2',
|
||||||
PhysicalKeyboardKey.digit3: '3',
|
PhysicalKeyboardKey.digit3: '3',
|
||||||
PhysicalKeyboardKey.digit4: '4',
|
PhysicalKeyboardKey.digit4: '4',
|
||||||
PhysicalKeyboardKey.digit5: '5',
|
PhysicalKeyboardKey.digit5: '5',
|
||||||
PhysicalKeyboardKey.digit6: '6',
|
PhysicalKeyboardKey.digit6: '6',
|
||||||
PhysicalKeyboardKey.digit7: '7',
|
PhysicalKeyboardKey.digit7: '7',
|
||||||
PhysicalKeyboardKey.digit8: '8',
|
PhysicalKeyboardKey.digit8: '8',
|
||||||
PhysicalKeyboardKey.digit9: '9',
|
PhysicalKeyboardKey.digit9: '9',
|
||||||
PhysicalKeyboardKey.digit0: '0',
|
PhysicalKeyboardKey.digit0: '0',
|
||||||
PhysicalKeyboardKey.enter: 'ENTER',
|
PhysicalKeyboardKey.enter: 'ENTER',
|
||||||
PhysicalKeyboardKey.escape: 'ESCAPE',
|
PhysicalKeyboardKey.escape: 'ESCAPE',
|
||||||
PhysicalKeyboardKey.backspace: 'BACKSPACE',
|
PhysicalKeyboardKey.backspace: 'BACKSPACE',
|
||||||
PhysicalKeyboardKey.tab: 'TAB',
|
PhysicalKeyboardKey.tab: 'TAB',
|
||||||
PhysicalKeyboardKey.space: 'SPACE',
|
PhysicalKeyboardKey.space: 'SPACE',
|
||||||
PhysicalKeyboardKey.minus: '-',
|
PhysicalKeyboardKey.minus: '-',
|
||||||
PhysicalKeyboardKey.equal: '=',
|
PhysicalKeyboardKey.equal: '=',
|
||||||
PhysicalKeyboardKey.bracketLeft: '[',
|
PhysicalKeyboardKey.bracketLeft: '[',
|
||||||
PhysicalKeyboardKey.bracketRight: ']',
|
PhysicalKeyboardKey.bracketRight: ']',
|
||||||
PhysicalKeyboardKey.backslash: '\\',
|
PhysicalKeyboardKey.backslash: '\\',
|
||||||
PhysicalKeyboardKey.semicolon: ';',
|
PhysicalKeyboardKey.semicolon: ';',
|
||||||
PhysicalKeyboardKey.quote: '"',
|
PhysicalKeyboardKey.quote: '"',
|
||||||
PhysicalKeyboardKey.backquote: '`',
|
PhysicalKeyboardKey.backquote: '`',
|
||||||
PhysicalKeyboardKey.comma: ',',
|
PhysicalKeyboardKey.comma: ',',
|
||||||
PhysicalKeyboardKey.period: '.',
|
PhysicalKeyboardKey.period: '.',
|
||||||
PhysicalKeyboardKey.slash: '/',
|
PhysicalKeyboardKey.slash: '/',
|
||||||
PhysicalKeyboardKey.capsLock: 'CAPSLOCK',
|
PhysicalKeyboardKey.capsLock: 'CAPSLOCK',
|
||||||
PhysicalKeyboardKey.f1: 'F1',
|
PhysicalKeyboardKey.f1: 'F1',
|
||||||
PhysicalKeyboardKey.f2: 'F2',
|
PhysicalKeyboardKey.f2: 'F2',
|
||||||
PhysicalKeyboardKey.f3: 'F3',
|
PhysicalKeyboardKey.f3: 'F3',
|
||||||
PhysicalKeyboardKey.f4: 'F4',
|
PhysicalKeyboardKey.f4: 'F4',
|
||||||
PhysicalKeyboardKey.f5: 'F5',
|
PhysicalKeyboardKey.f5: 'F5',
|
||||||
PhysicalKeyboardKey.f6: 'F6',
|
PhysicalKeyboardKey.f6: 'F6',
|
||||||
PhysicalKeyboardKey.f7: 'F7',
|
PhysicalKeyboardKey.f7: 'F7',
|
||||||
PhysicalKeyboardKey.f8: 'F8',
|
PhysicalKeyboardKey.f8: 'F8',
|
||||||
PhysicalKeyboardKey.f9: 'F9',
|
PhysicalKeyboardKey.f9: 'F9',
|
||||||
PhysicalKeyboardKey.f10: 'F10',
|
PhysicalKeyboardKey.f10: 'F10',
|
||||||
PhysicalKeyboardKey.f11: 'F11',
|
PhysicalKeyboardKey.f11: 'F11',
|
||||||
PhysicalKeyboardKey.f12: 'F12',
|
PhysicalKeyboardKey.f12: 'F12',
|
||||||
PhysicalKeyboardKey.home: 'HOME',
|
PhysicalKeyboardKey.home: 'HOME',
|
||||||
PhysicalKeyboardKey.pageUp: 'PAGEUP',
|
PhysicalKeyboardKey.pageUp: 'PAGEUP',
|
||||||
PhysicalKeyboardKey.delete: 'DELETE',
|
PhysicalKeyboardKey.delete: 'DELETE',
|
||||||
PhysicalKeyboardKey.end: 'END',
|
PhysicalKeyboardKey.end: 'END',
|
||||||
PhysicalKeyboardKey.pageDown: 'PAGEDOWN',
|
PhysicalKeyboardKey.pageDown: 'PAGEDOWN',
|
||||||
PhysicalKeyboardKey.arrowRight: '→',
|
PhysicalKeyboardKey.arrowRight: '→',
|
||||||
PhysicalKeyboardKey.arrowLeft: '←',
|
PhysicalKeyboardKey.arrowLeft: '←',
|
||||||
PhysicalKeyboardKey.arrowDown: '↓',
|
PhysicalKeyboardKey.arrowDown: '↓',
|
||||||
PhysicalKeyboardKey.arrowUp: '↑',
|
PhysicalKeyboardKey.arrowUp: '↑',
|
||||||
PhysicalKeyboardKey.controlLeft: 'CTRL',
|
PhysicalKeyboardKey.controlLeft: 'CTRL',
|
||||||
PhysicalKeyboardKey.shiftLeft: 'SHIFT',
|
PhysicalKeyboardKey.shiftLeft: 'SHIFT',
|
||||||
PhysicalKeyboardKey.altLeft: 'ALT',
|
PhysicalKeyboardKey.altLeft: 'ALT',
|
||||||
PhysicalKeyboardKey.metaLeft: system.isMacOS ? '⌘' : 'WIN',
|
PhysicalKeyboardKey.metaLeft: system.isMacOS ? '⌘' : 'WIN',
|
||||||
PhysicalKeyboardKey.controlRight: 'CTRL',
|
PhysicalKeyboardKey.controlRight: 'CTRL',
|
||||||
PhysicalKeyboardKey.shiftRight: 'SHIFT',
|
PhysicalKeyboardKey.shiftRight: 'SHIFT',
|
||||||
PhysicalKeyboardKey.altRight: 'ALT',
|
PhysicalKeyboardKey.altRight: 'ALT',
|
||||||
PhysicalKeyboardKey.metaRight: system.isMacOS ? '⌘' : 'WIN',
|
PhysicalKeyboardKey.metaRight: system.isMacOS ? '⌘' : 'WIN',
|
||||||
PhysicalKeyboardKey.fn: 'FN',
|
PhysicalKeyboardKey.fn: 'FN',
|
||||||
};
|
};
|
||||||
|
|
||||||
extension KeyboardKeyExt on KeyboardKey {
|
extension KeyboardKeyExt on KeyboardKey {
|
||||||
String get label {
|
String get label {
|
||||||
|
|||||||
@@ -16,21 +16,20 @@ class LinkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initAppLinksListen(
|
Future<void> initAppLinksListen(
|
||||||
Function(String url) installConfigCallBack) async {
|
Function(String url) installConfigCallBack,
|
||||||
|
) async {
|
||||||
commonPrint.log('initAppLinksListen');
|
commonPrint.log('initAppLinksListen');
|
||||||
destroy();
|
destroy();
|
||||||
subscription = _appLinks.uriLinkStream.listen(
|
subscription = _appLinks.uriLinkStream.listen((uri) {
|
||||||
(uri) {
|
commonPrint.log('onAppLink: $uri');
|
||||||
commonPrint.log('onAppLink: $uri');
|
if (uri.host == 'install-config') {
|
||||||
if (uri.host == 'install-config') {
|
final parameters = uri.queryParameters;
|
||||||
final parameters = uri.queryParameters;
|
final url = parameters['url'];
|
||||||
final url = parameters['url'];
|
if (url != null) {
|
||||||
if (url != null) {
|
installConfigCallBack(url);
|
||||||
installConfigCallBack(url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy() {
|
void destroy() {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import 'common.dart';
|
|||||||
|
|
||||||
extension PackageInfoExtension on PackageInfo {
|
extension PackageInfoExtension on PackageInfo {
|
||||||
String get ua => [
|
String get ua => [
|
||||||
'$appName/v$version',
|
'$appName/v$version',
|
||||||
'clash-verge',
|
'clash-verge',
|
||||||
'Platform/${Platform.operatingSystem}',
|
'Platform/${Platform.operatingSystem}',
|
||||||
].join(' ');
|
].join(' ');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,8 @@ import 'package:image_picker/image_picker.dart';
|
|||||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||||
|
|
||||||
class Picker {
|
class Picker {
|
||||||
Future<PlatformFile?> pickerFile({bool withData = true}) async {
|
Future<PlatformFile?> pickerFile() async {
|
||||||
final filePickerResult = await FilePicker.pickFiles(
|
return FilePicker.pickFile(initialDirectory: await appPath.downloadDirPath);
|
||||||
withData: withData,
|
|
||||||
allowMultiple: false,
|
|
||||||
initialDirectory: await appPath.downloadDirPath,
|
|
||||||
);
|
|
||||||
return filePickerResult?.files.first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> saveFile(String fileName, Uint8List bytes) async {
|
Future<String?> saveFile(String fileName, Uint8List bytes) async {
|
||||||
@@ -34,15 +29,12 @@ class Picker {
|
|||||||
if (!await localFile.exists()) {
|
if (!await localFile.exists()) {
|
||||||
await localFile.create(recursive: true);
|
await localFile.create(recursive: true);
|
||||||
}
|
}
|
||||||
final bytes = Platform.isAndroid ? await localFile.readAsBytes() : null;
|
final bytes = await localFile.readAsBytes();
|
||||||
final path = await FilePicker.saveFile(
|
final path = await FilePicker.saveFile(
|
||||||
fileName: fileName,
|
fileName: fileName,
|
||||||
initialDirectory: await appPath.downloadDirPath,
|
initialDirectory: await appPath.downloadDirPath,
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
);
|
);
|
||||||
if (path != null && bytes == null) {
|
|
||||||
await localFile.copy(path);
|
|
||||||
}
|
|
||||||
await localFile.safeDelete();
|
await localFile.safeDelete();
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
@@ -65,4 +57,10 @@ class Picker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension PlatformFileExt on PlatformFile {
|
||||||
|
Future<Uint8List> readBytes() {
|
||||||
|
return readAsBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final picker = Picker();
|
final picker = Picker();
|
||||||
|
|||||||
@@ -1,234 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'dart:ffi';
|
|
||||||
import 'dart:isolate';
|
|
||||||
import 'dart:typed_data';
|
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
import 'package:fl_clash/common/common.dart';
|
|
||||||
import 'package:fl_clash/enum/enum.dart';
|
|
||||||
import 'package:win32/win32.dart';
|
|
||||||
|
|
||||||
const _pipeBufferSize = 256 * 1024;
|
|
||||||
|
|
||||||
class _PipeCmd {
|
|
||||||
final int type; // 0 = write, 1 = shutdown
|
|
||||||
final Uint8List? data;
|
|
||||||
|
|
||||||
const _PipeCmd(this.type, this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _pipeIsolate(List<Object> args) {
|
|
||||||
final pipeName = args[0] as String;
|
|
||||||
final dataPort = args[1] as SendPort;
|
|
||||||
|
|
||||||
final namePtr = pipeName.toNativeUtf16();
|
|
||||||
|
|
||||||
final handle = CreateNamedPipe(
|
|
||||||
namePtr,
|
|
||||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
|
||||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
|
||||||
1,
|
|
||||||
_pipeBufferSize,
|
|
||||||
_pipeBufferSize,
|
|
||||||
0,
|
|
||||||
nullptr,
|
|
||||||
);
|
|
||||||
|
|
||||||
calloc.free(namePtr);
|
|
||||||
|
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
|
||||||
dataPort.send(
|
|
||||||
'error:CreateNamedPipe failed, Win32 error=${GetLastError()}',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final writeRx = ReceivePort();
|
|
||||||
|
|
||||||
final readBuf = calloc<Uint8>(_pipeBufferSize);
|
|
||||||
final bytesRead = calloc<Uint32>();
|
|
||||||
final overlapped = calloc<OVERLAPPED>();
|
|
||||||
final readEvent = CreateEvent(nullptr, 1, 0, nullptr);
|
|
||||||
overlapped.ref.hEvent = readEvent;
|
|
||||||
|
|
||||||
var running = true;
|
|
||||||
var clientConnected = false;
|
|
||||||
|
|
||||||
writeRx.listen((msg) {
|
|
||||||
if (msg is _PipeCmd) {
|
|
||||||
if (msg.type == 0) {
|
|
||||||
if (clientConnected && msg.data != null) {
|
|
||||||
final buf = calloc<Uint8>(msg.data!.length);
|
|
||||||
final written = calloc<Uint32>();
|
|
||||||
buf.asTypedList(msg.data!.length).setAll(0, msg.data!);
|
|
||||||
WriteFile(handle, buf, msg.data!.length, written, nullptr);
|
|
||||||
calloc.free(written);
|
|
||||||
calloc.free(buf);
|
|
||||||
}
|
|
||||||
} else if (msg.type == 1) {
|
|
||||||
running = false;
|
|
||||||
if (clientConnected) {
|
|
||||||
DisconnectNamedPipe(handle);
|
|
||||||
clientConnected = false;
|
|
||||||
}
|
|
||||||
writeRx.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final connectEvent = CreateEvent(nullptr, 1, 0, nullptr);
|
|
||||||
final connectOverlapped = calloc<OVERLAPPED>();
|
|
||||||
connectOverlapped.ref.hEvent = connectEvent;
|
|
||||||
|
|
||||||
while (running) {
|
|
||||||
final cr = ConnectNamedPipe(handle, connectOverlapped);
|
|
||||||
if (cr == 0) {
|
|
||||||
final err = GetLastError();
|
|
||||||
if (err == ERROR_IO_PENDING) {
|
|
||||||
while (running) {
|
|
||||||
final wr = WaitForSingleObject(connectEvent, 100);
|
|
||||||
if (wr == WAIT_OBJECT_0) break;
|
|
||||||
}
|
|
||||||
if (!running) break;
|
|
||||||
} else if (err != ERROR_PIPE_CONNECTED) {
|
|
||||||
dataPort.send('error:ConnectNamedPipe failed, Win32 error=$err');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!running) break;
|
|
||||||
|
|
||||||
clientConnected = true;
|
|
||||||
dataPort.send(writeRx.sendPort);
|
|
||||||
|
|
||||||
var readPending = false;
|
|
||||||
while (running && clientConnected) {
|
|
||||||
if (!readPending) {
|
|
||||||
bytesRead.value = 0;
|
|
||||||
final readResult = ReadFile(
|
|
||||||
handle,
|
|
||||||
readBuf,
|
|
||||||
_pipeBufferSize,
|
|
||||||
bytesRead,
|
|
||||||
overlapped,
|
|
||||||
);
|
|
||||||
if (readResult != 0) {
|
|
||||||
if (bytesRead.value > 0) {
|
|
||||||
dataPort.send(
|
|
||||||
Uint8List.fromList(readBuf.asTypedList(bytesRead.value)),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final err = GetLastError();
|
|
||||||
if (err == ERROR_IO_PENDING) {
|
|
||||||
readPending = true;
|
|
||||||
} else if (bytesRead.value > 0) {
|
|
||||||
dataPort.send(
|
|
||||||
Uint8List.fromList(readBuf.asTypedList(bytesRead.value)),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readPending) {
|
|
||||||
final wr = WaitForSingleObject(readEvent, 100);
|
|
||||||
if (wr == WAIT_OBJECT_0) {
|
|
||||||
final got = GetOverlappedResult(handle, overlapped, bytesRead, 0);
|
|
||||||
if (got != 0 && bytesRead.value > 0) {
|
|
||||||
dataPort.send(
|
|
||||||
Uint8List.fromList(readBuf.asTypedList(bytesRead.value)),
|
|
||||||
);
|
|
||||||
readPending = false;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (wr != WAIT_TIMEOUT) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (running && clientConnected) {
|
|
||||||
DisconnectNamedPipe(handle);
|
|
||||||
clientConnected = false;
|
|
||||||
dataPort.send('closed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(readEvent);
|
|
||||||
CloseHandle(connectEvent);
|
|
||||||
calloc.free(connectOverlapped);
|
|
||||||
calloc.free(overlapped);
|
|
||||||
calloc.free(bytesRead);
|
|
||||||
calloc.free(readBuf);
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
class NamedPipeServer {
|
|
||||||
final String pipeName;
|
|
||||||
Isolate? _isolate;
|
|
||||||
SendPort? _writePort;
|
|
||||||
ReceivePort? _responsePort;
|
|
||||||
StreamSubscription? _responseSub;
|
|
||||||
|
|
||||||
final _dataController = StreamController<Uint8List>.broadcast();
|
|
||||||
Completer<void> _connectionCompleter = Completer<void>();
|
|
||||||
|
|
||||||
void Function()? onDisconnect;
|
|
||||||
|
|
||||||
NamedPipeServer._(this.pipeName);
|
|
||||||
|
|
||||||
Stream<Uint8List> get dataStream => _dataController.stream;
|
|
||||||
Completer<void> get connectionCompleter => _connectionCompleter;
|
|
||||||
|
|
||||||
static Future<NamedPipeServer> bind(String pipeName) async {
|
|
||||||
final server = NamedPipeServer._(pipeName);
|
|
||||||
server._responsePort = ReceivePort();
|
|
||||||
|
|
||||||
server._responseSub = server._responsePort!.listen((message) {
|
|
||||||
if (message is SendPort) {
|
|
||||||
server._writePort = message;
|
|
||||||
if (server._connectionCompleter.isCompleted) {
|
|
||||||
server._connectionCompleter = Completer<void>();
|
|
||||||
}
|
|
||||||
server._connectionCompleter.complete();
|
|
||||||
} else if (message is Uint8List) {
|
|
||||||
server._dataController.add(message);
|
|
||||||
} else if (message == 'closed') {
|
|
||||||
server._connectionCompleter = Completer<void>();
|
|
||||||
server.onDisconnect?.call();
|
|
||||||
} else if (message is String && message.startsWith('error:')) {
|
|
||||||
commonPrint.log('[NamedPipeServer] $message', logLevel: LogLevel.error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
server._isolate = await Isolate.spawn(_pipeIsolate, [
|
|
||||||
pipeName,
|
|
||||||
server._responsePort!.sendPort,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeln(String message) {
|
|
||||||
final wp = _writePort;
|
|
||||||
if (wp == null) return;
|
|
||||||
final str = '$message\n';
|
|
||||||
wp.send(_PipeCmd(0, Uint8List.fromList(str.codeUnits)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> close() async {
|
|
||||||
final wp = _writePort;
|
|
||||||
if (wp == null) return;
|
|
||||||
_writePort = null;
|
|
||||||
wp.send(const _PipeCmd(1, null));
|
|
||||||
_responseSub?.cancel();
|
|
||||||
_responsePort?.close();
|
|
||||||
await Future.delayed(const Duration(milliseconds: 50));
|
|
||||||
_isolate?.kill();
|
|
||||||
_isolate = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,26 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:win32_registry/win32_registry.dart';
|
import 'package:win32_registry/win32_registry.dart';
|
||||||
|
|
||||||
|
class ProtocolRegistrationPlan {
|
||||||
|
final String scheme;
|
||||||
|
final String executable;
|
||||||
|
|
||||||
|
const ProtocolRegistrationPlan({
|
||||||
|
required this.scheme,
|
||||||
|
required this.executable,
|
||||||
|
});
|
||||||
|
|
||||||
|
String get protocolKey => 'Software\\Classes\\$scheme';
|
||||||
|
|
||||||
|
String get commandKey => 'shell\\open\\command';
|
||||||
|
|
||||||
|
String get protocolValueName => 'URL Protocol';
|
||||||
|
|
||||||
|
String get protocolValue => '';
|
||||||
|
|
||||||
|
String get command => '"$executable" "%1"';
|
||||||
|
}
|
||||||
|
|
||||||
class Protocol {
|
class Protocol {
|
||||||
static Protocol? _instance;
|
static Protocol? _instance;
|
||||||
|
|
||||||
@@ -13,19 +33,25 @@ class Protocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void register(String scheme) {
|
void register(String scheme) {
|
||||||
final String protocolRegKey = 'Software\\Classes\\$scheme';
|
final plan = ProtocolRegistrationPlan(
|
||||||
const RegistryValue protocolRegValue = RegistryValue.string(
|
scheme: scheme,
|
||||||
'URL Protocol',
|
executable: Platform.resolvedExecutable,
|
||||||
'',
|
|
||||||
);
|
);
|
||||||
const String protocolCmdRegKey = 'shell\\open\\command';
|
final regKey = CURRENT_USER.create(plan.protocolKey);
|
||||||
final RegistryValue protocolCmdRegValue = RegistryValue.string(
|
try {
|
||||||
'',
|
regKey.setValue(
|
||||||
'"${Platform.resolvedExecutable}" "%1"',
|
plan.protocolValueName,
|
||||||
);
|
RegistryValue.string(plan.protocolValue),
|
||||||
final regKey = Registry.currentUser.createKey(protocolRegKey);
|
);
|
||||||
regKey.createValue(protocolRegValue);
|
final commandKey = regKey.create(plan.commandKey);
|
||||||
regKey.createKey(protocolCmdRegKey).createValue(protocolCmdRegValue);
|
try {
|
||||||
|
commandKey.setValue('', RegistryValue.string(plan.command));
|
||||||
|
} finally {
|
||||||
|
commandKey.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
regKey.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,30 +113,30 @@ class Request {
|
|||||||
|
|
||||||
final future = dio
|
final future = dio
|
||||||
.get<Map<String, dynamic>>(
|
.get<Map<String, dynamic>>(
|
||||||
source.key,
|
source.key,
|
||||||
cancelToken: token,
|
cancelToken: token,
|
||||||
options: Options(responseType: ResponseType.json),
|
options: Options(responseType: ResponseType.json),
|
||||||
)
|
)
|
||||||
.timeout(const Duration(seconds: 10));
|
.timeout(const Duration(seconds: 10));
|
||||||
future
|
future
|
||||||
.then((res) {
|
.then((res) {
|
||||||
if (res.statusCode == HttpStatus.ok && res.data != null) {
|
if (res.statusCode == HttpStatus.ok && res.data != null) {
|
||||||
completer.complete(Result.success(source.value(res.data!)));
|
completer.complete(Result.success(source.value(res.data!)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
commonPrint.log('checkIp data empty', logLevel: LogLevel.info);
|
commonPrint.log('checkIp data empty', logLevel: LogLevel.info);
|
||||||
failureCount++;
|
failureCount++;
|
||||||
handleFailRes();
|
handleFailRes();
|
||||||
})
|
})
|
||||||
.catchError((e) {
|
.catchError((e) {
|
||||||
failureCount++;
|
failureCount++;
|
||||||
if (e is DioException && e.type == DioExceptionType.cancel) {
|
if (e is DioException && e.type == DioExceptionType.cancel) {
|
||||||
completer.complete(Result.error('cancelled'));
|
completer.complete(Result.error('cancelled'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
commonPrint.log('checkIp error $e', logLevel: LogLevel.warning);
|
commonPrint.log('checkIp error $e', logLevel: LogLevel.warning);
|
||||||
handleFailRes();
|
handleFailRes();
|
||||||
});
|
});
|
||||||
return completer.future;
|
return completer.future;
|
||||||
});
|
});
|
||||||
final res = await Future.any(futures);
|
final res = await Future.any(futures);
|
||||||
@@ -149,9 +149,9 @@ class Request {
|
|||||||
try {
|
try {
|
||||||
final response = await dio
|
final response = await dio
|
||||||
.get(
|
.get(
|
||||||
'http://$localhost:$helperPort/ping',
|
'http://$localhost:$helperPort/ping',
|
||||||
options: Options(responseType: ResponseType.plain),
|
options: Options(responseType: ResponseType.plain),
|
||||||
)
|
)
|
||||||
.timeout(const Duration(milliseconds: 2000));
|
.timeout(const Duration(milliseconds: 2000));
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
return false;
|
return false;
|
||||||
@@ -166,10 +166,10 @@ class Request {
|
|||||||
try {
|
try {
|
||||||
final response = await dio
|
final response = await dio
|
||||||
.post(
|
.post(
|
||||||
'http://$localhost:$helperPort/start',
|
'http://$localhost:$helperPort/start',
|
||||||
data: json.encode({'path': appPath.corePath, 'arg': arg}),
|
data: json.encode({'path': appPath.corePath, 'arg': arg}),
|
||||||
options: Options(responseType: ResponseType.plain),
|
options: Options(responseType: ResponseType.plain),
|
||||||
)
|
)
|
||||||
.timeout(const Duration(milliseconds: 2000));
|
.timeout(const Duration(milliseconds: 2000));
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
return false;
|
return false;
|
||||||
@@ -185,9 +185,9 @@ class Request {
|
|||||||
try {
|
try {
|
||||||
final response = await dio
|
final response = await dio
|
||||||
.post(
|
.post(
|
||||||
'http://$localhost:$helperPort/stop',
|
'http://$localhost:$helperPort/stop',
|
||||||
options: Options(responseType: ResponseType.plain),
|
options: Options(responseType: ResponseType.plain),
|
||||||
)
|
)
|
||||||
.timeout(const Duration(milliseconds: 2000));
|
.timeout(const Duration(milliseconds: 2000));
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class System {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
title: currentAppLocalizations.pleaseInputAdminPassword,
|
title: currentAppLocalizations.pleaseInputAdminPassword,
|
||||||
value: '',
|
value: '',
|
||||||
|
inputFormatters: TextInputLimits.limit(TextInputLimits.password),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (password == null || password.isEmpty) {
|
if (password == null || password.isEmpty) {
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ Future<VM2<String, String>> _makeRealProfileTask(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
rawConfig['profile']['store-selected'] = false;
|
rawConfig['profile']['store-selected'] = false;
|
||||||
rawConfig['geox-url'] = realPatchConfig.geoXUrl.toJson();
|
rawConfig['geox-url'] = realPatchConfig.geoXUrl.raw;
|
||||||
rawConfig['global-ua'] = realPatchConfig.globalUa ?? defaultUA;
|
rawConfig['global-ua'] = realPatchConfig.globalUa ?? defaultUA;
|
||||||
if (rawConfig['hosts'] == null) {
|
if (rawConfig['hosts'] == null) {
|
||||||
rawConfig['hosts'] = {};
|
rawConfig['hosts'] = {};
|
||||||
@@ -331,10 +331,10 @@ Future<String> _encodeLogsTask(List<Log> data) async {
|
|||||||
|
|
||||||
Future<MigrationData> oldToNowTask(Map<String, Object?> data) async {
|
Future<MigrationData> oldToNowTask(Map<String, Object?> data) async {
|
||||||
final homeDir = await appPath.homeDirPath;
|
final homeDir = await appPath.homeDirPath;
|
||||||
return compute<
|
return compute<VM3<Map<String, Object?>, String, String>, MigrationData>(
|
||||||
VM3<Map<String, Object?>, String, String>,
|
_oldToNowTask,
|
||||||
MigrationData
|
VM3(data, homeDir, homeDir),
|
||||||
>(_oldToNowTask, VM3(data, homeDir, homeDir));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<MigrationData> _oldToNowTask(
|
Future<MigrationData> _oldToNowTask(
|
||||||
|
|||||||
@@ -11,11 +11,8 @@ extension TextStyleExtension on TextStyle {
|
|||||||
|
|
||||||
TextStyle get toBold => copyWith(fontWeight: FontWeight.bold);
|
TextStyle get toBold => copyWith(fontWeight: FontWeight.bold);
|
||||||
|
|
||||||
TextStyle get toJetBrainsMono => copyWith(
|
TextStyle get toJetBrainsMono =>
|
||||||
fontFamily: FontFamily.jetBrainsMono.value,
|
copyWith(fontFamily: FontFamily.jetBrainsMono.value);
|
||||||
);
|
|
||||||
|
|
||||||
TextStyle adjustSize(int size) => copyWith(
|
TextStyle adjustSize(int size) => copyWith(fontSize: fontSize! + size);
|
||||||
fontSize: fontSize! + size,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,8 +177,8 @@ class CoreController {
|
|||||||
return ExternalProvider.fromJson(json.decode(externalProvidersRawString));
|
return ExternalProvider.fromJson(json.decode(externalProvidersRawString));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> updateGeoData(UpdateGeoDataParams params) {
|
Future<String> updateGeoData(String type) {
|
||||||
return _interface.updateGeoData(params);
|
return _interface.updateGeoData(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> sideLoadExternalProvider({
|
Future<String> sideLoadExternalProvider({
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ abstract mixin class CoreEventListener {
|
|||||||
void onLoaded(String providerName) {}
|
void onLoaded(String providerName) {}
|
||||||
|
|
||||||
void onCrash(String message) {}
|
void onCrash(String message) {}
|
||||||
|
|
||||||
|
void onGeoUpdate(
|
||||||
|
String geoType,
|
||||||
|
bool updating,
|
||||||
|
bool skipped,
|
||||||
|
String? error,
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoreEventManager {
|
class CoreEventManager {
|
||||||
@@ -38,6 +45,15 @@ class CoreEventManager {
|
|||||||
case CoreEventType.crash:
|
case CoreEventType.crash:
|
||||||
listener.onCrash(event.data);
|
listener.onCrash(event.data);
|
||||||
break;
|
break;
|
||||||
|
case CoreEventType.geoUpdate:
|
||||||
|
final data = event.data as Map<String, dynamic>;
|
||||||
|
listener.onGeoUpdate(
|
||||||
|
data['type'] as String,
|
||||||
|
data['updating'] as bool,
|
||||||
|
data['skipped'] as bool? ?? false,
|
||||||
|
data['error'] as String?,
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ mixin CoreInterface {
|
|||||||
|
|
||||||
Future<String>? getExternalProvider(String externalProviderName);
|
Future<String>? getExternalProvider(String externalProviderName);
|
||||||
|
|
||||||
Future<String> updateGeoData(UpdateGeoDataParams params);
|
Future<String> updateGeoData(String type);
|
||||||
|
|
||||||
Future<String> sideLoadExternalProvider({
|
Future<String> sideLoadExternalProvider({
|
||||||
required String providerName,
|
required String providerName,
|
||||||
@@ -214,10 +214,10 @@ abstract class CoreHandlerInterface with CoreInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> updateGeoData(UpdateGeoDataParams params) async {
|
Future<String> updateGeoData(String type) async {
|
||||||
return await _invoke<String>(
|
return await _invoke<String>(
|
||||||
method: ActionMethod.updateGeoData,
|
method: ActionMethod.updateGeoData,
|
||||||
data: json.encode(params),
|
data: type,
|
||||||
) ??
|
) ??
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,50 +34,50 @@ class IPCCoreTransport {
|
|||||||
try {
|
try {
|
||||||
final stream = restartIpcServer(name: address);
|
final stream = restartIpcServer(name: address);
|
||||||
_subscription = stream.listen(
|
_subscription = stream.listen(
|
||||||
(data) {
|
(data) {
|
||||||
if (data.isEmpty) return;
|
if (data.isEmpty) return;
|
||||||
final type = data[0];
|
final type = data[0];
|
||||||
final payload = data.length > 1 ? data.sublist(1) : Uint8List(0);
|
final payload = data.length > 1 ? data.sublist(1) : Uint8List(0);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case _typeReady:
|
case _typeReady:
|
||||||
commonPrint.log('IPC Ready');
|
commonPrint.log('IPC Ready');
|
||||||
if (_readyCompleter.isCompleted) {
|
if (_readyCompleter.isCompleted) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_readyCompleter.complete();
|
||||||
break;
|
break;
|
||||||
}
|
case _typeConnected:
|
||||||
_readyCompleter.complete();
|
commonPrint.log('IPC Connected');
|
||||||
break;
|
if (_completer.isCompleted) {
|
||||||
case _typeConnected:
|
break;
|
||||||
commonPrint.log('IPC Connected');
|
}
|
||||||
if (_completer.isCompleted) {
|
_completer.complete();
|
||||||
break;
|
break;
|
||||||
}
|
case _typeDisconnected:
|
||||||
_completer.complete();
|
commonPrint.log('IPC Disconnected');
|
||||||
break;
|
_completer = Completer<void>();
|
||||||
case _typeDisconnected:
|
onDisconnect?.call();
|
||||||
commonPrint.log('IPC Disconnected');
|
break;
|
||||||
_completer = Completer<void>();
|
case _typeData:
|
||||||
onDisconnect?.call();
|
_dataController.add(payload);
|
||||||
break;
|
break;
|
||||||
case _typeData:
|
case _typeError:
|
||||||
_dataController.add(payload);
|
final msg = utf8.decode(payload);
|
||||||
break;
|
commonPrint.log('IPC error: $msg', logLevel: LogLevel.error);
|
||||||
case _typeError:
|
break;
|
||||||
final msg = utf8.decode(payload);
|
default:
|
||||||
commonPrint.log('IPC error: $msg', logLevel: LogLevel.error);
|
commonPrint.log(
|
||||||
break;
|
'IPC unknown frame type: $type',
|
||||||
default:
|
logLevel: LogLevel.warning,
|
||||||
commonPrint.log(
|
);
|
||||||
'IPC unknown frame type: $type',
|
}
|
||||||
logLevel: LogLevel.warning,
|
},
|
||||||
);
|
onError: (error) {
|
||||||
}
|
commonPrint.log('IPC error: $error', logLevel: LogLevel.error);
|
||||||
},
|
},
|
||||||
onError: (error) {
|
cancelOnError: false,
|
||||||
commonPrint.log('IPC error: $error', logLevel: LogLevel.error);
|
);
|
||||||
},
|
await _readyCompleter.future;
|
||||||
cancelOnError: false,
|
|
||||||
);
|
|
||||||
await _readyCompleter.future;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
commonPrint.log(
|
commonPrint.log(
|
||||||
'Failed to start IPC server: $e',
|
'Failed to start IPC server: $e',
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ enum ResultType {
|
|||||||
error,
|
error,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CoreEventType { log, delay, request, loaded, crash }
|
enum CoreEventType { log, delay, request, loaded, crash, geoUpdate }
|
||||||
|
|
||||||
enum InvokeMessageType { protect, process }
|
enum InvokeMessageType { protect, process }
|
||||||
|
|
||||||
@@ -331,6 +331,40 @@ enum DashboardWidget {
|
|||||||
|
|
||||||
enum GeodataLoader { standard, memconservative }
|
enum GeodataLoader { standard, memconservative }
|
||||||
|
|
||||||
|
enum GeoResource {
|
||||||
|
@JsonValue('mmdb')
|
||||||
|
MMDB,
|
||||||
|
@JsonValue('asn')
|
||||||
|
ASN,
|
||||||
|
@JsonValue('geo-ip')
|
||||||
|
GEOIP,
|
||||||
|
@JsonValue('geo-site')
|
||||||
|
GEOSITE;
|
||||||
|
|
||||||
|
static GeoResource fromJson(String value) {
|
||||||
|
return switch (value) {
|
||||||
|
'mmdb' => GeoResource.MMDB,
|
||||||
|
'asn' => GeoResource.ASN,
|
||||||
|
'geo-ip' || 'geoip' => GeoResource.GEOIP,
|
||||||
|
'geo-site' || 'geosite' => GeoResource.GEOSITE,
|
||||||
|
_ => throw ArgumentError.value(value, 'value', 'Invalid geo resource'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension GeoResourceExt on GeoResource {
|
||||||
|
String get value {
|
||||||
|
return switch (this) {
|
||||||
|
GeoResource.MMDB => 'mmdb',
|
||||||
|
GeoResource.ASN => 'asn',
|
||||||
|
GeoResource.GEOIP => 'geo-ip',
|
||||||
|
GeoResource.GEOSITE => 'geo-site',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
String get updatingKey => 'geo_resource_$name';
|
||||||
|
}
|
||||||
|
|
||||||
enum PageLabel {
|
enum PageLabel {
|
||||||
dashboard,
|
dashboard,
|
||||||
proxies,
|
proxies,
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ class _AddOrEditRuleDialogState extends State<AddOrEditRuleDialog> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final rule = Rule(
|
final rule = Rule(
|
||||||
id: widget.rule?.id ?? -1,
|
id: widget.rule?.id ?? snowflake.id,
|
||||||
ruleAction: _ruleAction,
|
ruleAction: _ruleAction,
|
||||||
content: _contentController.text,
|
content: _contentController.text,
|
||||||
ruleTarget: _ruleTargetController.text,
|
ruleTarget: _ruleTargetController.text,
|
||||||
@@ -310,6 +310,9 @@ class _AddOrEditRuleDialogState extends State<AddOrEditRuleDialog> {
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
|
inputFormatters: TextInputLimits.limit(
|
||||||
|
TextInputLimits.rule,
|
||||||
|
),
|
||||||
onFieldSubmitted: (_) {
|
onFieldSubmitted: (_) {
|
||||||
_handleSubmit();
|
_handleSubmit();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -33,40 +33,52 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
|
|
||||||
static String m4(label) => "${label} cannot be empty";
|
static String m4(label) => "${label} cannot be empty";
|
||||||
|
|
||||||
static String m5(label) => "Current ${label} already exists";
|
static String m5(count) => "${count} entries";
|
||||||
|
|
||||||
static String m6(count) =>
|
static String m6(label) => "Current ${label} already exists";
|
||||||
|
|
||||||
|
static String m7(name) => "${name} skipped";
|
||||||
|
|
||||||
|
static String m8(name) => "${name} updated";
|
||||||
|
|
||||||
|
static String m9(name) => "Updating ${name}...";
|
||||||
|
|
||||||
|
static String m10(count) =>
|
||||||
"${Intl.plural(count, one: '1 hour ago', other: '${count} hours ago')}";
|
"${Intl.plural(count, one: '1 hour ago', other: '${count} hours ago')}";
|
||||||
|
|
||||||
static String m7(target) => "${target} is an invalid policy";
|
static String m11(count) => "${count} hours";
|
||||||
|
|
||||||
static String m8(proxyName) => "${proxyName} is an invalid proxy";
|
static String m12(target) => "${target} is an invalid policy";
|
||||||
|
|
||||||
static String m9(providerName) =>
|
static String m13(proxyName) => "${proxyName} is an invalid proxy";
|
||||||
|
|
||||||
|
static String m14(providerName) =>
|
||||||
"${providerName} is an invalid proxy provider";
|
"${providerName} is an invalid proxy provider";
|
||||||
|
|
||||||
static String m10(subRule) => "${subRule} is an invalid SUB_RULE";
|
static String m15(subRule) => "${subRule} is an invalid SUB_RULE";
|
||||||
|
|
||||||
static String m11(appName) =>
|
static String m16(appName) =>
|
||||||
"1. Open System Settings > Privacy & Security\n2. Choose Location Services\n3. Find and check ${appName} in the right list\n\nAfter completing the setup, return to the app and use it normally. Thank you for your cooperation.";
|
"1. Open System Settings > Privacy & Security\n2. Choose Location Services\n3. Find and check ${appName} in the right list\n\nAfter completing the setup, return to the app and use it normally. Thank you for your cooperation.";
|
||||||
|
|
||||||
static String m12(count) =>
|
static String m17(count) =>
|
||||||
"${Intl.plural(count, one: '1 minute ago', other: '${count} minutes ago')}";
|
"${Intl.plural(count, one: '1 minute ago', other: '${count} minutes ago')}";
|
||||||
|
|
||||||
static String m13(count) =>
|
static String m18(count) =>
|
||||||
"${Intl.plural(count, one: '1 month ago', other: '${count} months ago')}";
|
"${Intl.plural(count, one: '1 month ago', other: '${count} months ago')}";
|
||||||
|
|
||||||
static String m14(label) => "No ${label} yet";
|
static String m19(label) => "No ${label} yet";
|
||||||
|
|
||||||
static String m15(label) => "${label} must be a number";
|
static String m20(label) => "${label} must be a number";
|
||||||
|
|
||||||
static String m16(label) => "${label} must be between 1024 and 49151";
|
static String m21(label) => "${label} must be between 1024 and 49151";
|
||||||
|
|
||||||
static String m17(count) => "${count} items have been selected";
|
static String m22(count) => "${count} seconds";
|
||||||
|
|
||||||
static String m18(label) => "${label} must be a url";
|
static String m23(count) => "${count} items have been selected";
|
||||||
|
|
||||||
static String m19(count) =>
|
static String m24(label) => "${label} must be a url";
|
||||||
|
|
||||||
|
static String m25(count) =>
|
||||||
"${Intl.plural(count, one: '1 year ago', other: '${count} years ago')}";
|
"${Intl.plural(count, one: '1 year ago', other: '${count} years ago')}";
|
||||||
|
|
||||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||||
@@ -343,6 +355,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"emptyTip": m4,
|
"emptyTip": m4,
|
||||||
"en": MessageLookupByLibrary.simpleMessage("English"),
|
"en": MessageLookupByLibrary.simpleMessage("English"),
|
||||||
"entries": MessageLookupByLibrary.simpleMessage(" entries"),
|
"entries": MessageLookupByLibrary.simpleMessage(" entries"),
|
||||||
|
"entriesCount": m5,
|
||||||
"exclude": MessageLookupByLibrary.simpleMessage("Hidden from recent tasks"),
|
"exclude": MessageLookupByLibrary.simpleMessage("Hidden from recent tasks"),
|
||||||
"excludeDesc": MessageLookupByLibrary.simpleMessage(
|
"excludeDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"When the app is in the background, the app is hidden from the recent task",
|
"When the app is in the background, the app is hidden from the recent task",
|
||||||
@@ -355,7 +368,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"When connected to an excluded SSID Wi-Fi, the app running state will be automatically switched.",
|
"When connected to an excluded SSID Wi-Fi, the app running state will be automatically switched.",
|
||||||
),
|
),
|
||||||
"excludeType": MessageLookupByLibrary.simpleMessage("Exclude type"),
|
"excludeType": MessageLookupByLibrary.simpleMessage("Exclude type"),
|
||||||
"existsTip": m5,
|
"existsTip": m6,
|
||||||
"exit": MessageLookupByLibrary.simpleMessage("Exit"),
|
"exit": MessageLookupByLibrary.simpleMessage("Exit"),
|
||||||
"expand": MessageLookupByLibrary.simpleMessage("Standard"),
|
"expand": MessageLookupByLibrary.simpleMessage("Standard"),
|
||||||
"expectedStatus": MessageLookupByLibrary.simpleMessage("Expected status"),
|
"expectedStatus": MessageLookupByLibrary.simpleMessage("Expected status"),
|
||||||
@@ -394,6 +407,18 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("FruitSalad"),
|
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("FruitSalad"),
|
||||||
"general": MessageLookupByLibrary.simpleMessage("General"),
|
"general": MessageLookupByLibrary.simpleMessage("General"),
|
||||||
|
"geoAutoUpdate": MessageLookupByLibrary.simpleMessage("Auto Update"),
|
||||||
|
"geoAutoUpdateInterval": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Auto Update Interval",
|
||||||
|
),
|
||||||
|
"geoAutoUpdateIntervalTip": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Auto update interval must be greater than 0",
|
||||||
|
),
|
||||||
|
"geoOptions": MessageLookupByLibrary.simpleMessage("Geo Options"),
|
||||||
|
"geoResources": MessageLookupByLibrary.simpleMessage("Geo Resources"),
|
||||||
|
"geoSkipped": m7,
|
||||||
|
"geoUpdated": m8,
|
||||||
|
"geoUpdating": m9,
|
||||||
"geodataLoader": MessageLookupByLibrary.simpleMessage(
|
"geodataLoader": MessageLookupByLibrary.simpleMessage(
|
||||||
"Geo Low Memory Mode",
|
"Geo Low Memory Mode",
|
||||||
),
|
),
|
||||||
@@ -420,7 +445,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage(
|
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Use keyboard to control applications",
|
"Use keyboard to control applications",
|
||||||
),
|
),
|
||||||
"hoursAgo": m6,
|
"hours": MessageLookupByLibrary.simpleMessage("hours"),
|
||||||
|
"hoursAgo": m10,
|
||||||
|
"hoursCount": m11,
|
||||||
"icon": MessageLookupByLibrary.simpleMessage("Icon"),
|
"icon": MessageLookupByLibrary.simpleMessage("Icon"),
|
||||||
"iconRecords": MessageLookupByLibrary.simpleMessage("Icon records"),
|
"iconRecords": MessageLookupByLibrary.simpleMessage("Icon records"),
|
||||||
"iconStyle": MessageLookupByLibrary.simpleMessage("Icon style"),
|
"iconStyle": MessageLookupByLibrary.simpleMessage("Icon style"),
|
||||||
@@ -464,10 +491,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"invalidBackupFile": MessageLookupByLibrary.simpleMessage(
|
"invalidBackupFile": MessageLookupByLibrary.simpleMessage(
|
||||||
"Invalid backup file",
|
"Invalid backup file",
|
||||||
),
|
),
|
||||||
"invalidPolicy": m7,
|
"invalidPolicy": m12,
|
||||||
"invalidProxy": m8,
|
"invalidProxy": m13,
|
||||||
"invalidProxyProvider": m9,
|
"invalidProxyProvider": m14,
|
||||||
"invalidSubRule": m10,
|
"invalidSubRule": m15,
|
||||||
"ipcidr": MessageLookupByLibrary.simpleMessage("Ipcidr"),
|
"ipcidr": MessageLookupByLibrary.simpleMessage("Ipcidr"),
|
||||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
|
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
|
||||||
"When turned on it will be able to receive IPv6 traffic",
|
"When turned on it will be able to receive IPv6 traffic",
|
||||||
@@ -501,7 +528,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"locationPermissionDesc": MessageLookupByLibrary.simpleMessage(
|
"locationPermissionDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"According to system requirements, obtaining the Wi-Fi name requires you to grant location permission.",
|
"According to system requirements, obtaining the Wi-Fi name requires you to grant location permission.",
|
||||||
),
|
),
|
||||||
"locationPermissionGuide": m11,
|
"locationPermissionGuide": m16,
|
||||||
"locationPermissionRequired": MessageLookupByLibrary.simpleMessage(
|
"locationPermissionRequired": MessageLookupByLibrary.simpleMessage(
|
||||||
"Location Permission Required",
|
"Location Permission Required",
|
||||||
),
|
),
|
||||||
@@ -531,11 +558,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Modify the default system exit event",
|
"Modify the default system exit event",
|
||||||
),
|
),
|
||||||
"minutesAgo": m12,
|
"minutesAgo": m17,
|
||||||
"mixedPort": MessageLookupByLibrary.simpleMessage("Mixed Port"),
|
"mixedPort": MessageLookupByLibrary.simpleMessage("Mixed Port"),
|
||||||
"mode": MessageLookupByLibrary.simpleMessage("Mode"),
|
"mode": MessageLookupByLibrary.simpleMessage("Mode"),
|
||||||
"monochromeScheme": MessageLookupByLibrary.simpleMessage("Monochrome"),
|
"monochromeScheme": MessageLookupByLibrary.simpleMessage("Monochrome"),
|
||||||
"monthsAgo": m13,
|
"monthsAgo": m18,
|
||||||
"more": MessageLookupByLibrary.simpleMessage("More"),
|
"more": MessageLookupByLibrary.simpleMessage("More"),
|
||||||
"name": MessageLookupByLibrary.simpleMessage("Name"),
|
"name": MessageLookupByLibrary.simpleMessage("Name"),
|
||||||
"nameserver": MessageLookupByLibrary.simpleMessage("Nameserver"),
|
"nameserver": MessageLookupByLibrary.simpleMessage("Nameserver"),
|
||||||
@@ -581,8 +608,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"nullProfileDesc": MessageLookupByLibrary.simpleMessage(
|
"nullProfileDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"No profile, Please add a profile",
|
"No profile, Please add a profile",
|
||||||
),
|
),
|
||||||
"nullTip": m14,
|
"nullTip": m19,
|
||||||
"numberTip": m15,
|
"numberTip": m20,
|
||||||
"onDemand": MessageLookupByLibrary.simpleMessage("On Demand"),
|
"onDemand": MessageLookupByLibrary.simpleMessage("On Demand"),
|
||||||
"onDemandDesc": MessageLookupByLibrary.simpleMessage(
|
"onDemandDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Configure the program running state for specific scenarios",
|
"Configure the program running state for specific scenarios",
|
||||||
@@ -631,7 +658,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"portConflictTip": MessageLookupByLibrary.simpleMessage(
|
"portConflictTip": MessageLookupByLibrary.simpleMessage(
|
||||||
"Please enter a different port",
|
"Please enter a different port",
|
||||||
),
|
),
|
||||||
"portTip": m16,
|
"portTip": m21,
|
||||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage(
|
"preferH3Desc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Prioritize the use of DOH\'s http/3",
|
"Prioritize the use of DOH\'s http/3",
|
||||||
),
|
),
|
||||||
@@ -888,6 +915,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
"search": MessageLookupByLibrary.simpleMessage("Search"),
|
||||||
"seconds": MessageLookupByLibrary.simpleMessage("Seconds"),
|
"seconds": MessageLookupByLibrary.simpleMessage("Seconds"),
|
||||||
|
"secondsCount": m22,
|
||||||
"selectAll": MessageLookupByLibrary.simpleMessage("Select all"),
|
"selectAll": MessageLookupByLibrary.simpleMessage("Select all"),
|
||||||
"selectProxies": MessageLookupByLibrary.simpleMessage("Select proxies"),
|
"selectProxies": MessageLookupByLibrary.simpleMessage("Select proxies"),
|
||||||
"selectProxyProviders": MessageLookupByLibrary.simpleMessage(
|
"selectProxyProviders": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -903,7 +931,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Please select sub rule",
|
"Please select sub rule",
|
||||||
),
|
),
|
||||||
"selected": MessageLookupByLibrary.simpleMessage("Selected"),
|
"selected": MessageLookupByLibrary.simpleMessage("Selected"),
|
||||||
"selectedCountTitle": m17,
|
"selectedCountTitle": m23,
|
||||||
"settings": MessageLookupByLibrary.simpleMessage("Settings"),
|
"settings": MessageLookupByLibrary.simpleMessage("Settings"),
|
||||||
"show": MessageLookupByLibrary.simpleMessage("Show"),
|
"show": MessageLookupByLibrary.simpleMessage("Show"),
|
||||||
"shrink": MessageLookupByLibrary.simpleMessage("Shrink"),
|
"shrink": MessageLookupByLibrary.simpleMessage("Shrink"),
|
||||||
@@ -1003,9 +1031,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"urlDesc": MessageLookupByLibrary.simpleMessage(
|
"urlDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Obtain profile through URL",
|
"Obtain profile through URL",
|
||||||
),
|
),
|
||||||
"urlTip": m18,
|
"urlTip": m24,
|
||||||
"useHosts": MessageLookupByLibrary.simpleMessage("Use hosts"),
|
"useHosts": MessageLookupByLibrary.simpleMessage("Use hosts"),
|
||||||
"useSystemHosts": MessageLookupByLibrary.simpleMessage("Use system hosts"),
|
"useSystemHosts": MessageLookupByLibrary.simpleMessage("Use system hosts"),
|
||||||
|
"userAgent": MessageLookupByLibrary.simpleMessage("User-Agent"),
|
||||||
"value": MessageLookupByLibrary.simpleMessage("Value"),
|
"value": MessageLookupByLibrary.simpleMessage("Value"),
|
||||||
"vibrantScheme": MessageLookupByLibrary.simpleMessage("Vibrant"),
|
"vibrantScheme": MessageLookupByLibrary.simpleMessage("Vibrant"),
|
||||||
"view": MessageLookupByLibrary.simpleMessage("View"),
|
"view": MessageLookupByLibrary.simpleMessage("View"),
|
||||||
@@ -1022,7 +1051,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"WebDAV configuration",
|
"WebDAV configuration",
|
||||||
),
|
),
|
||||||
"whitelistMode": MessageLookupByLibrary.simpleMessage("Whitelist mode"),
|
"whitelistMode": MessageLookupByLibrary.simpleMessage("Whitelist mode"),
|
||||||
"yearsAgo": m19,
|
"yearsAgo": m25,
|
||||||
"zh_CN": MessageLookupByLibrary.simpleMessage("Simplified Chinese"),
|
"zh_CN": MessageLookupByLibrary.simpleMessage("Simplified Chinese"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,36 +30,48 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
|
|
||||||
static String m4(label) => "${label}は空欄にできません";
|
static String m4(label) => "${label}は空欄にできません";
|
||||||
|
|
||||||
static String m5(label) => "現在の${label}は既に存在しています";
|
static String m5(count) => "${count} エントリ";
|
||||||
|
|
||||||
static String m6(count) => "${count}時間前";
|
static String m6(label) => "現在の${label}は既に存在しています";
|
||||||
|
|
||||||
static String m7(target) => "${target} は無効なポリシーです";
|
static String m7(name) => "${name} スキップ済み";
|
||||||
|
|
||||||
static String m8(proxyName) => "${proxyName} は無効なプロキシです";
|
static String m8(name) => "${name} 更新済み";
|
||||||
|
|
||||||
static String m9(providerName) => "${providerName} は無効なプロキシプロバイダーです";
|
static String m9(name) => "${name}を更新中...";
|
||||||
|
|
||||||
static String m10(subRule) => "${subRule} は無効なSUB_RULEです";
|
static String m10(count) => "${count}時間前";
|
||||||
|
|
||||||
static String m11(appName) =>
|
static String m11(count) => "${count} 時間";
|
||||||
|
|
||||||
|
static String m12(target) => "${target} は無効なポリシーです";
|
||||||
|
|
||||||
|
static String m13(proxyName) => "${proxyName} は無効なプロキシです";
|
||||||
|
|
||||||
|
static String m14(providerName) => "${providerName} は無効なプロキシプロバイダーです";
|
||||||
|
|
||||||
|
static String m15(subRule) => "${subRule} は無効なSUB_RULEです";
|
||||||
|
|
||||||
|
static String m16(appName) =>
|
||||||
"1. Open System Settings > Privacy & Security\n2. Choose Location Services\n3. Find and check ${appName} in the right list\n\nAfter completing the setup, return to the app and use it normally. Thank you for your cooperation.";
|
"1. Open System Settings > Privacy & Security\n2. Choose Location Services\n3. Find and check ${appName} in the right list\n\nAfter completing the setup, return to the app and use it normally. Thank you for your cooperation.";
|
||||||
|
|
||||||
static String m12(count) => "${count}分前";
|
static String m17(count) => "${count}分前";
|
||||||
|
|
||||||
static String m13(count) => "${count}ヶ月前";
|
static String m18(count) => "${count}ヶ月前";
|
||||||
|
|
||||||
static String m14(label) => "まだ${label}はありません";
|
static String m19(label) => "まだ${label}はありません";
|
||||||
|
|
||||||
static String m15(label) => "${label}は数字でなければなりません";
|
static String m20(label) => "${label}は数字でなければなりません";
|
||||||
|
|
||||||
static String m16(label) => "${label} は 1024 から 49151 の間でなければなりません";
|
static String m21(label) => "${label} は 1024 から 49151 の間でなければなりません";
|
||||||
|
|
||||||
static String m17(count) => "${count} 項目が選択されています";
|
static String m22(count) => "${count} 秒";
|
||||||
|
|
||||||
static String m18(label) => "${label}はURLである必要があります";
|
static String m23(count) => "${count} 項目が選択されています";
|
||||||
|
|
||||||
static String m19(count) => "${count}年前";
|
static String m24(label) => "${label}はURLである必要があります";
|
||||||
|
|
||||||
|
static String m25(count) => "${count}年前";
|
||||||
|
|
||||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||||
@@ -265,6 +277,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"emptyTip": m4,
|
"emptyTip": m4,
|
||||||
"en": MessageLookupByLibrary.simpleMessage("英語"),
|
"en": MessageLookupByLibrary.simpleMessage("英語"),
|
||||||
"entries": MessageLookupByLibrary.simpleMessage(" エントリ"),
|
"entries": MessageLookupByLibrary.simpleMessage(" エントリ"),
|
||||||
|
"entriesCount": m5,
|
||||||
"exclude": MessageLookupByLibrary.simpleMessage("最近のタスクから非表示"),
|
"exclude": MessageLookupByLibrary.simpleMessage("最近のタスクから非表示"),
|
||||||
"excludeDesc": MessageLookupByLibrary.simpleMessage(
|
"excludeDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"アプリがバックグラウンド時に最近のタスクから非表示",
|
"アプリがバックグラウンド時に最近のタスクから非表示",
|
||||||
@@ -275,7 +288,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"When connected to an excluded SSID Wi-Fi, the app running state will be automatically switched.",
|
"When connected to an excluded SSID Wi-Fi, the app running state will be automatically switched.",
|
||||||
),
|
),
|
||||||
"excludeType": MessageLookupByLibrary.simpleMessage("除外タイプ"),
|
"excludeType": MessageLookupByLibrary.simpleMessage("除外タイプ"),
|
||||||
"existsTip": m5,
|
"existsTip": m6,
|
||||||
"exit": MessageLookupByLibrary.simpleMessage("終了"),
|
"exit": MessageLookupByLibrary.simpleMessage("終了"),
|
||||||
"expand": MessageLookupByLibrary.simpleMessage("標準"),
|
"expand": MessageLookupByLibrary.simpleMessage("標準"),
|
||||||
"expectedStatus": MessageLookupByLibrary.simpleMessage("期待されるステータス"),
|
"expectedStatus": MessageLookupByLibrary.simpleMessage("期待されるステータス"),
|
||||||
@@ -310,6 +323,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("フルーツサラダ"),
|
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("フルーツサラダ"),
|
||||||
"general": MessageLookupByLibrary.simpleMessage("一般"),
|
"general": MessageLookupByLibrary.simpleMessage("一般"),
|
||||||
|
"geoAutoUpdate": MessageLookupByLibrary.simpleMessage("自動更新"),
|
||||||
|
"geoAutoUpdateInterval": MessageLookupByLibrary.simpleMessage("自動更新間隔"),
|
||||||
|
"geoAutoUpdateIntervalTip": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"自動更新間隔は0より大きくなければなりません",
|
||||||
|
),
|
||||||
|
"geoOptions": MessageLookupByLibrary.simpleMessage("Geoオプション"),
|
||||||
|
"geoResources": MessageLookupByLibrary.simpleMessage("Geoリソース"),
|
||||||
|
"geoSkipped": m7,
|
||||||
|
"geoUpdated": m8,
|
||||||
|
"geoUpdating": m9,
|
||||||
"geodataLoader": MessageLookupByLibrary.simpleMessage("Geo低メモリモード"),
|
"geodataLoader": MessageLookupByLibrary.simpleMessage("Geo低メモリモード"),
|
||||||
"geodataLoaderDesc": MessageLookupByLibrary.simpleMessage(
|
"geodataLoaderDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"有効化するとGeo低メモリローダーを使用",
|
"有効化するとGeo低メモリローダーを使用",
|
||||||
@@ -328,7 +351,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage(
|
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"キーボードでアプリを制御",
|
"キーボードでアプリを制御",
|
||||||
),
|
),
|
||||||
"hoursAgo": m6,
|
"hours": MessageLookupByLibrary.simpleMessage("時間"),
|
||||||
|
"hoursAgo": m10,
|
||||||
|
"hoursCount": m11,
|
||||||
"icon": MessageLookupByLibrary.simpleMessage("アイコン"),
|
"icon": MessageLookupByLibrary.simpleMessage("アイコン"),
|
||||||
"iconRecords": MessageLookupByLibrary.simpleMessage("アイコン履歴"),
|
"iconRecords": MessageLookupByLibrary.simpleMessage("アイコン履歴"),
|
||||||
"iconStyle": MessageLookupByLibrary.simpleMessage("アイコンスタイル"),
|
"iconStyle": MessageLookupByLibrary.simpleMessage("アイコンスタイル"),
|
||||||
@@ -360,10 +385,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"interval": MessageLookupByLibrary.simpleMessage("インターバル"),
|
"interval": MessageLookupByLibrary.simpleMessage("インターバル"),
|
||||||
"intranetIP": MessageLookupByLibrary.simpleMessage("イントラネットIP"),
|
"intranetIP": MessageLookupByLibrary.simpleMessage("イントラネットIP"),
|
||||||
"invalidBackupFile": MessageLookupByLibrary.simpleMessage("無効なバックアップファイル"),
|
"invalidBackupFile": MessageLookupByLibrary.simpleMessage("無効なバックアップファイル"),
|
||||||
"invalidPolicy": m7,
|
"invalidPolicy": m12,
|
||||||
"invalidProxy": m8,
|
"invalidProxy": m13,
|
||||||
"invalidProxyProvider": m9,
|
"invalidProxyProvider": m14,
|
||||||
"invalidSubRule": m10,
|
"invalidSubRule": m15,
|
||||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
|
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
|
||||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage("有効化するとIPv6トラフィックを受信可能"),
|
"ipv6Desc": MessageLookupByLibrary.simpleMessage("有効化するとIPv6トラフィックを受信可能"),
|
||||||
"ipv6InboundDesc": MessageLookupByLibrary.simpleMessage("IPv6インバウンドを許可"),
|
"ipv6InboundDesc": MessageLookupByLibrary.simpleMessage("IPv6インバウンドを許可"),
|
||||||
@@ -391,7 +416,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"locationPermissionDesc": MessageLookupByLibrary.simpleMessage(
|
"locationPermissionDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"According to system requirements, obtaining the Wi-Fi name requires you to grant location permission.",
|
"According to system requirements, obtaining the Wi-Fi name requires you to grant location permission.",
|
||||||
),
|
),
|
||||||
"locationPermissionGuide": m11,
|
"locationPermissionGuide": m16,
|
||||||
"locationPermissionRequired": MessageLookupByLibrary.simpleMessage(
|
"locationPermissionRequired": MessageLookupByLibrary.simpleMessage(
|
||||||
"Location Permission Required",
|
"Location Permission Required",
|
||||||
),
|
),
|
||||||
@@ -415,11 +440,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"システムの終了イベントを変更",
|
"システムの終了イベントを変更",
|
||||||
),
|
),
|
||||||
"minutesAgo": m12,
|
"minutesAgo": m17,
|
||||||
"mixedPort": MessageLookupByLibrary.simpleMessage("混合ポート"),
|
"mixedPort": MessageLookupByLibrary.simpleMessage("混合ポート"),
|
||||||
"mode": MessageLookupByLibrary.simpleMessage("モード"),
|
"mode": MessageLookupByLibrary.simpleMessage("モード"),
|
||||||
"monochromeScheme": MessageLookupByLibrary.simpleMessage("モノクローム"),
|
"monochromeScheme": MessageLookupByLibrary.simpleMessage("モノクローム"),
|
||||||
"monthsAgo": m13,
|
"monthsAgo": m18,
|
||||||
"more": MessageLookupByLibrary.simpleMessage("詳細"),
|
"more": MessageLookupByLibrary.simpleMessage("詳細"),
|
||||||
"name": MessageLookupByLibrary.simpleMessage("名前"),
|
"name": MessageLookupByLibrary.simpleMessage("名前"),
|
||||||
"nameserver": MessageLookupByLibrary.simpleMessage("ネームサーバー"),
|
"nameserver": MessageLookupByLibrary.simpleMessage("ネームサーバー"),
|
||||||
@@ -453,8 +478,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"nullProfileDesc": MessageLookupByLibrary.simpleMessage(
|
"nullProfileDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"プロファイルがありません。追加してください",
|
"プロファイルがありません。追加してください",
|
||||||
),
|
),
|
||||||
"nullTip": m14,
|
"nullTip": m19,
|
||||||
"numberTip": m15,
|
"numberTip": m20,
|
||||||
"onDemand": MessageLookupByLibrary.simpleMessage("On Demand"),
|
"onDemand": MessageLookupByLibrary.simpleMessage("On Demand"),
|
||||||
"onDemandDesc": MessageLookupByLibrary.simpleMessage(
|
"onDemandDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Configure the program running state for specific scenarios",
|
"Configure the program running state for specific scenarios",
|
||||||
@@ -497,7 +522,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"port": MessageLookupByLibrary.simpleMessage("ポート"),
|
"port": MessageLookupByLibrary.simpleMessage("ポート"),
|
||||||
"portConflictTip": MessageLookupByLibrary.simpleMessage("別のポートを入力してください"),
|
"portConflictTip": MessageLookupByLibrary.simpleMessage("別のポートを入力してください"),
|
||||||
"portTip": m16,
|
"portTip": m21,
|
||||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage("DOHのHTTP/3を優先使用"),
|
"preferH3Desc": MessageLookupByLibrary.simpleMessage("DOHのHTTP/3を優先使用"),
|
||||||
"prerequisites": MessageLookupByLibrary.simpleMessage("Prerequisites"),
|
"prerequisites": MessageLookupByLibrary.simpleMessage("Prerequisites"),
|
||||||
"pressKeyboard": MessageLookupByLibrary.simpleMessage("キーボードを押してください"),
|
"pressKeyboard": MessageLookupByLibrary.simpleMessage("キーボードを押してください"),
|
||||||
@@ -716,6 +741,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"search": MessageLookupByLibrary.simpleMessage("検索"),
|
"search": MessageLookupByLibrary.simpleMessage("検索"),
|
||||||
"seconds": MessageLookupByLibrary.simpleMessage("秒"),
|
"seconds": MessageLookupByLibrary.simpleMessage("秒"),
|
||||||
|
"secondsCount": m22,
|
||||||
"selectAll": MessageLookupByLibrary.simpleMessage("すべて選択"),
|
"selectAll": MessageLookupByLibrary.simpleMessage("すべて選択"),
|
||||||
"selectProxies": MessageLookupByLibrary.simpleMessage("プロキシを選択"),
|
"selectProxies": MessageLookupByLibrary.simpleMessage("プロキシを選択"),
|
||||||
"selectProxyProviders": MessageLookupByLibrary.simpleMessage(
|
"selectProxyProviders": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -727,7 +753,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"selectSubRule": MessageLookupByLibrary.simpleMessage("サブルールを選択してください"),
|
"selectSubRule": MessageLookupByLibrary.simpleMessage("サブルールを選択してください"),
|
||||||
"selected": MessageLookupByLibrary.simpleMessage("選択済み"),
|
"selected": MessageLookupByLibrary.simpleMessage("選択済み"),
|
||||||
"selectedCountTitle": m17,
|
"selectedCountTitle": m23,
|
||||||
"settings": MessageLookupByLibrary.simpleMessage("設定"),
|
"settings": MessageLookupByLibrary.simpleMessage("設定"),
|
||||||
"show": MessageLookupByLibrary.simpleMessage("表示"),
|
"show": MessageLookupByLibrary.simpleMessage("表示"),
|
||||||
"shrink": MessageLookupByLibrary.simpleMessage("縮小"),
|
"shrink": MessageLookupByLibrary.simpleMessage("縮小"),
|
||||||
@@ -809,9 +835,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"upload": MessageLookupByLibrary.simpleMessage("アップロード"),
|
"upload": MessageLookupByLibrary.simpleMessage("アップロード"),
|
||||||
"url": MessageLookupByLibrary.simpleMessage("URL"),
|
"url": MessageLookupByLibrary.simpleMessage("URL"),
|
||||||
"urlDesc": MessageLookupByLibrary.simpleMessage("URL経由でプロファイルを取得"),
|
"urlDesc": MessageLookupByLibrary.simpleMessage("URL経由でプロファイルを取得"),
|
||||||
"urlTip": m18,
|
"urlTip": m24,
|
||||||
"useHosts": MessageLookupByLibrary.simpleMessage("ホストを使用"),
|
"useHosts": MessageLookupByLibrary.simpleMessage("ホストを使用"),
|
||||||
"useSystemHosts": MessageLookupByLibrary.simpleMessage("システムホストを使用"),
|
"useSystemHosts": MessageLookupByLibrary.simpleMessage("システムホストを使用"),
|
||||||
|
"userAgent": MessageLookupByLibrary.simpleMessage("ユーザーエージェント"),
|
||||||
"value": MessageLookupByLibrary.simpleMessage("値"),
|
"value": MessageLookupByLibrary.simpleMessage("値"),
|
||||||
"vibrantScheme": MessageLookupByLibrary.simpleMessage("ビブラント"),
|
"vibrantScheme": MessageLookupByLibrary.simpleMessage("ビブラント"),
|
||||||
"view": MessageLookupByLibrary.simpleMessage("表示"),
|
"view": MessageLookupByLibrary.simpleMessage("表示"),
|
||||||
@@ -824,7 +851,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"vpnTip": MessageLookupByLibrary.simpleMessage("変更はVPN再起動後に有効"),
|
"vpnTip": MessageLookupByLibrary.simpleMessage("変更はVPN再起動後に有効"),
|
||||||
"webDAVConfiguration": MessageLookupByLibrary.simpleMessage("WebDAV設定"),
|
"webDAVConfiguration": MessageLookupByLibrary.simpleMessage("WebDAV設定"),
|
||||||
"whitelistMode": MessageLookupByLibrary.simpleMessage("ホワイトリストモード"),
|
"whitelistMode": MessageLookupByLibrary.simpleMessage("ホワイトリストモード"),
|
||||||
"yearsAgo": m19,
|
"yearsAgo": m25,
|
||||||
"zh_CN": MessageLookupByLibrary.simpleMessage("簡体字中国語"),
|
"zh_CN": MessageLookupByLibrary.simpleMessage("簡体字中国語"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,40 +32,52 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
|
|
||||||
static String m4(label) => "${label} не может быть пустым";
|
static String m4(label) => "${label} не может быть пустым";
|
||||||
|
|
||||||
static String m5(label) => "Текущий ${label} уже существует";
|
static String m5(count) => "${count} записей";
|
||||||
|
|
||||||
static String m6(count) =>
|
static String m6(label) => "Текущий ${label} уже существует";
|
||||||
|
|
||||||
|
static String m7(name) => "${name} пропущено";
|
||||||
|
|
||||||
|
static String m8(name) => "${name} обновлено";
|
||||||
|
|
||||||
|
static String m9(name) => "Обновление ${name}...";
|
||||||
|
|
||||||
|
static String m10(count) =>
|
||||||
"${Intl.plural(count, one: '${count} час назад', few: '${count} часа назад', many: '${count} часов назад', other: '${count} часа назад')}";
|
"${Intl.plural(count, one: '${count} час назад', few: '${count} часа назад', many: '${count} часов назад', other: '${count} часа назад')}";
|
||||||
|
|
||||||
static String m7(target) => "${target} является недопустимой политикой";
|
static String m11(count) => "${count} часов";
|
||||||
|
|
||||||
static String m8(proxyName) => "${proxyName} является недопустимым прокси";
|
static String m12(target) => "${target} является недопустимой политикой";
|
||||||
|
|
||||||
static String m9(providerName) =>
|
static String m13(proxyName) => "${proxyName} является недопустимым прокси";
|
||||||
|
|
||||||
|
static String m14(providerName) =>
|
||||||
"${providerName} является недопустимым провайдером прокси";
|
"${providerName} является недопустимым провайдером прокси";
|
||||||
|
|
||||||
static String m10(subRule) => "${subRule} является недопустимым подправилом";
|
static String m15(subRule) => "${subRule} является недопустимым подправилом";
|
||||||
|
|
||||||
static String m11(appName) =>
|
static String m16(appName) =>
|
||||||
"1. Open System Settings > Privacy & Security\n2. Choose Location Services\n3. Find and check ${appName} in the right list\n\nAfter completing the setup, return to the app and use it normally. Thank you for your cooperation.";
|
"1. Open System Settings > Privacy & Security\n2. Choose Location Services\n3. Find and check ${appName} in the right list\n\nAfter completing the setup, return to the app and use it normally. Thank you for your cooperation.";
|
||||||
|
|
||||||
static String m12(count) =>
|
static String m17(count) =>
|
||||||
"${Intl.plural(count, one: '${count} минута назад', few: '${count} минуты назад', many: '${count} минут назад', other: '${count} минуты назад')}";
|
"${Intl.plural(count, one: '${count} минута назад', few: '${count} минуты назад', many: '${count} минут назад', other: '${count} минуты назад')}";
|
||||||
|
|
||||||
static String m13(count) =>
|
static String m18(count) =>
|
||||||
"${Intl.plural(count, one: '${count} месяц назад', few: '${count} месяца назад', many: '${count} месяцев назад', other: '${count} месяца назад')}";
|
"${Intl.plural(count, one: '${count} месяц назад', few: '${count} месяца назад', many: '${count} месяцев назад', other: '${count} месяца назад')}";
|
||||||
|
|
||||||
static String m14(label) => "${label} пока отсутствуют";
|
static String m19(label) => "${label} пока отсутствуют";
|
||||||
|
|
||||||
static String m15(label) => "${label} должно быть числом";
|
static String m20(label) => "${label} должно быть числом";
|
||||||
|
|
||||||
static String m16(label) => "${label} должен быть числом от 1024 до 49151";
|
static String m21(label) => "${label} должен быть числом от 1024 до 49151";
|
||||||
|
|
||||||
static String m17(count) => "Выбрано ${count} элементов";
|
static String m22(count) => "${count} секунд";
|
||||||
|
|
||||||
static String m18(label) => "${label} должен быть URL";
|
static String m23(count) => "Выбрано ${count} элементов";
|
||||||
|
|
||||||
static String m19(count) =>
|
static String m24(label) => "${label} должен быть URL";
|
||||||
|
|
||||||
|
static String m25(count) =>
|
||||||
"${Intl.plural(count, one: '${count} год назад', few: '${count} года назад', many: '${count} лет назад', other: '${count} года назад')}";
|
"${Intl.plural(count, one: '${count} год назад', few: '${count} года назад', many: '${count} лет назад', other: '${count} года назад')}";
|
||||||
|
|
||||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||||
@@ -352,6 +364,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"emptyTip": m4,
|
"emptyTip": m4,
|
||||||
"en": MessageLookupByLibrary.simpleMessage("Английский"),
|
"en": MessageLookupByLibrary.simpleMessage("Английский"),
|
||||||
"entries": MessageLookupByLibrary.simpleMessage(" записей"),
|
"entries": MessageLookupByLibrary.simpleMessage(" записей"),
|
||||||
|
"entriesCount": m5,
|
||||||
"exclude": MessageLookupByLibrary.simpleMessage(
|
"exclude": MessageLookupByLibrary.simpleMessage(
|
||||||
"Скрыть из последних задач",
|
"Скрыть из последних задач",
|
||||||
),
|
),
|
||||||
@@ -366,7 +379,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"When connected to an excluded SSID Wi-Fi, the app running state will be automatically switched.",
|
"When connected to an excluded SSID Wi-Fi, the app running state will be automatically switched.",
|
||||||
),
|
),
|
||||||
"excludeType": MessageLookupByLibrary.simpleMessage("Тип исключения"),
|
"excludeType": MessageLookupByLibrary.simpleMessage("Тип исключения"),
|
||||||
"existsTip": m5,
|
"existsTip": m6,
|
||||||
"exit": MessageLookupByLibrary.simpleMessage("Выход"),
|
"exit": MessageLookupByLibrary.simpleMessage("Выход"),
|
||||||
"expand": MessageLookupByLibrary.simpleMessage("Стандартный"),
|
"expand": MessageLookupByLibrary.simpleMessage("Стандартный"),
|
||||||
"expectedStatus": MessageLookupByLibrary.simpleMessage("Ожидаемый статус"),
|
"expectedStatus": MessageLookupByLibrary.simpleMessage("Ожидаемый статус"),
|
||||||
@@ -409,6 +422,18 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("Фруктовый микс"),
|
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("Фруктовый микс"),
|
||||||
"general": MessageLookupByLibrary.simpleMessage("Общие"),
|
"general": MessageLookupByLibrary.simpleMessage("Общие"),
|
||||||
|
"geoAutoUpdate": MessageLookupByLibrary.simpleMessage("Автообновление"),
|
||||||
|
"geoAutoUpdateInterval": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Интервал автообновления",
|
||||||
|
),
|
||||||
|
"geoAutoUpdateIntervalTip": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Интервал автообновления должен быть больше 0",
|
||||||
|
),
|
||||||
|
"geoOptions": MessageLookupByLibrary.simpleMessage("Настройки Geo"),
|
||||||
|
"geoResources": MessageLookupByLibrary.simpleMessage("Ресурсы Geo"),
|
||||||
|
"geoSkipped": m7,
|
||||||
|
"geoUpdated": m8,
|
||||||
|
"geoUpdating": m9,
|
||||||
"geodataLoader": MessageLookupByLibrary.simpleMessage(
|
"geodataLoader": MessageLookupByLibrary.simpleMessage(
|
||||||
"Режим низкого потребления памяти для геоданных",
|
"Режим низкого потребления памяти для геоданных",
|
||||||
),
|
),
|
||||||
@@ -437,7 +462,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage(
|
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Использование клавиатуры для управления приложением",
|
"Использование клавиатуры для управления приложением",
|
||||||
),
|
),
|
||||||
"hoursAgo": m6,
|
"hours": MessageLookupByLibrary.simpleMessage("часов"),
|
||||||
|
"hoursAgo": m10,
|
||||||
|
"hoursCount": m11,
|
||||||
"icon": MessageLookupByLibrary.simpleMessage("Иконка"),
|
"icon": MessageLookupByLibrary.simpleMessage("Иконка"),
|
||||||
"iconRecords": MessageLookupByLibrary.simpleMessage("История иконок"),
|
"iconRecords": MessageLookupByLibrary.simpleMessage("История иконок"),
|
||||||
"iconStyle": MessageLookupByLibrary.simpleMessage("Стиль иконки"),
|
"iconStyle": MessageLookupByLibrary.simpleMessage("Стиль иконки"),
|
||||||
@@ -483,10 +510,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"invalidBackupFile": MessageLookupByLibrary.simpleMessage(
|
"invalidBackupFile": MessageLookupByLibrary.simpleMessage(
|
||||||
"Неверный файл резервной копии",
|
"Неверный файл резервной копии",
|
||||||
),
|
),
|
||||||
"invalidPolicy": m7,
|
"invalidPolicy": m12,
|
||||||
"invalidProxy": m8,
|
"invalidProxy": m13,
|
||||||
"invalidProxyProvider": m9,
|
"invalidProxyProvider": m14,
|
||||||
"invalidSubRule": m10,
|
"invalidSubRule": m15,
|
||||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
|
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
|
||||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
|
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
|
||||||
"При включении будет возможно получать IPv6 трафик",
|
"При включении будет возможно получать IPv6 трафик",
|
||||||
@@ -520,7 +547,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"locationPermissionDesc": MessageLookupByLibrary.simpleMessage(
|
"locationPermissionDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"According to system requirements, obtaining the Wi-Fi name requires you to grant location permission.",
|
"According to system requirements, obtaining the Wi-Fi name requires you to grant location permission.",
|
||||||
),
|
),
|
||||||
"locationPermissionGuide": m11,
|
"locationPermissionGuide": m16,
|
||||||
"locationPermissionRequired": MessageLookupByLibrary.simpleMessage(
|
"locationPermissionRequired": MessageLookupByLibrary.simpleMessage(
|
||||||
"Location Permission Required",
|
"Location Permission Required",
|
||||||
),
|
),
|
||||||
@@ -558,11 +585,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Изменить стандартное событие выхода из системы",
|
"Изменить стандартное событие выхода из системы",
|
||||||
),
|
),
|
||||||
"minutesAgo": m12,
|
"minutesAgo": m17,
|
||||||
"mixedPort": MessageLookupByLibrary.simpleMessage("Смешанный порт"),
|
"mixedPort": MessageLookupByLibrary.simpleMessage("Смешанный порт"),
|
||||||
"mode": MessageLookupByLibrary.simpleMessage("Режим"),
|
"mode": MessageLookupByLibrary.simpleMessage("Режим"),
|
||||||
"monochromeScheme": MessageLookupByLibrary.simpleMessage("Монохром"),
|
"monochromeScheme": MessageLookupByLibrary.simpleMessage("Монохром"),
|
||||||
"monthsAgo": m13,
|
"monthsAgo": m18,
|
||||||
"more": MessageLookupByLibrary.simpleMessage("Еще"),
|
"more": MessageLookupByLibrary.simpleMessage("Еще"),
|
||||||
"name": MessageLookupByLibrary.simpleMessage("Имя"),
|
"name": MessageLookupByLibrary.simpleMessage("Имя"),
|
||||||
"nameserver": MessageLookupByLibrary.simpleMessage("Сервер имен"),
|
"nameserver": MessageLookupByLibrary.simpleMessage("Сервер имен"),
|
||||||
@@ -608,8 +635,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"nullProfileDesc": MessageLookupByLibrary.simpleMessage(
|
"nullProfileDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Нет профиля, пожалуйста, добавьте профиль",
|
"Нет профиля, пожалуйста, добавьте профиль",
|
||||||
),
|
),
|
||||||
"nullTip": m14,
|
"nullTip": m19,
|
||||||
"numberTip": m15,
|
"numberTip": m20,
|
||||||
"onDemand": MessageLookupByLibrary.simpleMessage("On Demand"),
|
"onDemand": MessageLookupByLibrary.simpleMessage("On Demand"),
|
||||||
"onDemandDesc": MessageLookupByLibrary.simpleMessage(
|
"onDemandDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Configure the program running state for specific scenarios",
|
"Configure the program running state for specific scenarios",
|
||||||
@@ -666,7 +693,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"portConflictTip": MessageLookupByLibrary.simpleMessage(
|
"portConflictTip": MessageLookupByLibrary.simpleMessage(
|
||||||
"Введите другой порт",
|
"Введите другой порт",
|
||||||
),
|
),
|
||||||
"portTip": m16,
|
"portTip": m21,
|
||||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage(
|
"preferH3Desc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Приоритетное использование HTTP/3 для DOH",
|
"Приоритетное использование HTTP/3 для DOH",
|
||||||
),
|
),
|
||||||
@@ -935,6 +962,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"search": MessageLookupByLibrary.simpleMessage("Поиск"),
|
"search": MessageLookupByLibrary.simpleMessage("Поиск"),
|
||||||
"seconds": MessageLookupByLibrary.simpleMessage("Секунд"),
|
"seconds": MessageLookupByLibrary.simpleMessage("Секунд"),
|
||||||
|
"secondsCount": m22,
|
||||||
"selectAll": MessageLookupByLibrary.simpleMessage("Выбрать все"),
|
"selectAll": MessageLookupByLibrary.simpleMessage("Выбрать все"),
|
||||||
"selectProxies": MessageLookupByLibrary.simpleMessage("Выбрать прокси"),
|
"selectProxies": MessageLookupByLibrary.simpleMessage("Выбрать прокси"),
|
||||||
"selectProxyProviders": MessageLookupByLibrary.simpleMessage(
|
"selectProxyProviders": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -950,7 +978,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Пожалуйста, выберите подправило",
|
"Пожалуйста, выберите подправило",
|
||||||
),
|
),
|
||||||
"selected": MessageLookupByLibrary.simpleMessage("Выбрано"),
|
"selected": MessageLookupByLibrary.simpleMessage("Выбрано"),
|
||||||
"selectedCountTitle": m17,
|
"selectedCountTitle": m23,
|
||||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||||
"show": MessageLookupByLibrary.simpleMessage("Показать"),
|
"show": MessageLookupByLibrary.simpleMessage("Показать"),
|
||||||
"shrink": MessageLookupByLibrary.simpleMessage("Сжать"),
|
"shrink": MessageLookupByLibrary.simpleMessage("Сжать"),
|
||||||
@@ -1064,11 +1092,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"urlDesc": MessageLookupByLibrary.simpleMessage(
|
"urlDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"Получить профиль через URL",
|
"Получить профиль через URL",
|
||||||
),
|
),
|
||||||
"urlTip": m18,
|
"urlTip": m24,
|
||||||
"useHosts": MessageLookupByLibrary.simpleMessage("Использовать hosts"),
|
"useHosts": MessageLookupByLibrary.simpleMessage("Использовать hosts"),
|
||||||
"useSystemHosts": MessageLookupByLibrary.simpleMessage(
|
"useSystemHosts": MessageLookupByLibrary.simpleMessage(
|
||||||
"Использовать системные hosts",
|
"Использовать системные hosts",
|
||||||
),
|
),
|
||||||
|
"userAgent": MessageLookupByLibrary.simpleMessage("User-Agent"),
|
||||||
"value": MessageLookupByLibrary.simpleMessage("Значение"),
|
"value": MessageLookupByLibrary.simpleMessage("Значение"),
|
||||||
"vibrantScheme": MessageLookupByLibrary.simpleMessage("Яркие"),
|
"vibrantScheme": MessageLookupByLibrary.simpleMessage("Яркие"),
|
||||||
"view": MessageLookupByLibrary.simpleMessage("Просмотр"),
|
"view": MessageLookupByLibrary.simpleMessage("Просмотр"),
|
||||||
@@ -1087,7 +1116,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"whitelistMode": MessageLookupByLibrary.simpleMessage(
|
"whitelistMode": MessageLookupByLibrary.simpleMessage(
|
||||||
"Режим белого списка",
|
"Режим белого списка",
|
||||||
),
|
),
|
||||||
"yearsAgo": m19,
|
"yearsAgo": m25,
|
||||||
"zh_CN": MessageLookupByLibrary.simpleMessage("Упрощенный китайский"),
|
"zh_CN": MessageLookupByLibrary.simpleMessage("Упрощенный китайский"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,36 +30,48 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
|
|
||||||
static String m4(label) => "${label}不能为空";
|
static String m4(label) => "${label}不能为空";
|
||||||
|
|
||||||
static String m5(label) => "${label}当前已存在";
|
static String m5(count) => "${count} 个条目";
|
||||||
|
|
||||||
static String m6(count) => "${count} 小时前";
|
static String m6(label) => "${label}当前已存在";
|
||||||
|
|
||||||
static String m7(target) => "${target} 是一个无效的策略";
|
static String m7(name) => "${name} 已跳过";
|
||||||
|
|
||||||
static String m8(proxyName) => "${proxyName} 是一个无效的代理";
|
static String m8(name) => "${name} 已更新";
|
||||||
|
|
||||||
static String m9(providerName) => "${providerName} 是一个无效的代理集";
|
static String m9(name) => "正在更新 ${name}...";
|
||||||
|
|
||||||
static String m10(subRule) => "${subRule} 是一个无效的SUB_RULE";
|
static String m10(count) => "${count} 小时前";
|
||||||
|
|
||||||
static String m11(appName) =>
|
static String m11(count) => "${count} 小时";
|
||||||
|
|
||||||
|
static String m12(target) => "${target} 是一个无效的策略";
|
||||||
|
|
||||||
|
static String m13(proxyName) => "${proxyName} 是一个无效的代理";
|
||||||
|
|
||||||
|
static String m14(providerName) => "${providerName} 是一个无效的代理集";
|
||||||
|
|
||||||
|
static String m15(subRule) => "${subRule} 是一个无效的SUB_RULE";
|
||||||
|
|
||||||
|
static String m16(appName) =>
|
||||||
"1. 打开 系统设置 > 隐私与安全性\n2. 选择 定位服务\n3. 在右侧列表中找到并勾选 ${appName}\n\n完成设置后,返回应用即可正常使用。感谢您的配合。";
|
"1. 打开 系统设置 > 隐私与安全性\n2. 选择 定位服务\n3. 在右侧列表中找到并勾选 ${appName}\n\n完成设置后,返回应用即可正常使用。感谢您的配合。";
|
||||||
|
|
||||||
static String m12(count) => "${count} 分钟前";
|
static String m17(count) => "${count} 分钟前";
|
||||||
|
|
||||||
static String m13(count) => "${count} 个月前";
|
static String m18(count) => "${count} 个月前";
|
||||||
|
|
||||||
static String m14(label) => "暂无${label}";
|
static String m19(label) => "暂无${label}";
|
||||||
|
|
||||||
static String m15(label) => "${label}必须为数字";
|
static String m20(label) => "${label}必须为数字";
|
||||||
|
|
||||||
static String m16(label) => "${label} 必须在 1024 到 49151 之间";
|
static String m21(label) => "${label} 必须在 1024 到 49151 之间";
|
||||||
|
|
||||||
static String m17(count) => "已选择 ${count} 项";
|
static String m22(count) => "${count} 秒";
|
||||||
|
|
||||||
static String m18(label) => "${label}必须为URL";
|
static String m23(count) => "已选择 ${count} 项";
|
||||||
|
|
||||||
static String m19(count) => "${count} 年前";
|
static String m24(label) => "${label}必须为URL";
|
||||||
|
|
||||||
|
static String m25(count) => "${count} 年前";
|
||||||
|
|
||||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||||
@@ -237,6 +249,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"emptyTip": m4,
|
"emptyTip": m4,
|
||||||
"en": MessageLookupByLibrary.simpleMessage("英语"),
|
"en": MessageLookupByLibrary.simpleMessage("英语"),
|
||||||
"entries": MessageLookupByLibrary.simpleMessage("个条目"),
|
"entries": MessageLookupByLibrary.simpleMessage("个条目"),
|
||||||
|
"entriesCount": m5,
|
||||||
"exclude": MessageLookupByLibrary.simpleMessage("从最近任务中隐藏"),
|
"exclude": MessageLookupByLibrary.simpleMessage("从最近任务中隐藏"),
|
||||||
"excludeDesc": MessageLookupByLibrary.simpleMessage("应用在后台时,从最近任务中隐藏应用"),
|
"excludeDesc": MessageLookupByLibrary.simpleMessage("应用在后台时,从最近任务中隐藏应用"),
|
||||||
"excludeProxyFilter": MessageLookupByLibrary.simpleMessage("排除节点过滤器"),
|
"excludeProxyFilter": MessageLookupByLibrary.simpleMessage("排除节点过滤器"),
|
||||||
@@ -245,7 +258,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"连接到被排除SSID的WIFI时,将会自动切换应用运行状态",
|
"连接到被排除SSID的WIFI时,将会自动切换应用运行状态",
|
||||||
),
|
),
|
||||||
"excludeType": MessageLookupByLibrary.simpleMessage("排除类型"),
|
"excludeType": MessageLookupByLibrary.simpleMessage("排除类型"),
|
||||||
"existsTip": m5,
|
"existsTip": m6,
|
||||||
"exit": MessageLookupByLibrary.simpleMessage("退出"),
|
"exit": MessageLookupByLibrary.simpleMessage("退出"),
|
||||||
"expand": MessageLookupByLibrary.simpleMessage("标准"),
|
"expand": MessageLookupByLibrary.simpleMessage("标准"),
|
||||||
"expectedStatus": MessageLookupByLibrary.simpleMessage("预期状态"),
|
"expectedStatus": MessageLookupByLibrary.simpleMessage("预期状态"),
|
||||||
@@ -274,6 +287,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"forceRestartCoreTip": MessageLookupByLibrary.simpleMessage("您确定要强制重启核心吗?"),
|
"forceRestartCoreTip": MessageLookupByLibrary.simpleMessage("您确定要强制重启核心吗?"),
|
||||||
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("果缤纷"),
|
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("果缤纷"),
|
||||||
"general": MessageLookupByLibrary.simpleMessage("常规"),
|
"general": MessageLookupByLibrary.simpleMessage("常规"),
|
||||||
|
"geoAutoUpdate": MessageLookupByLibrary.simpleMessage("自动更新"),
|
||||||
|
"geoAutoUpdateInterval": MessageLookupByLibrary.simpleMessage("自动更新间隔"),
|
||||||
|
"geoAutoUpdateIntervalTip": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"自动更新间隔必须大于0",
|
||||||
|
),
|
||||||
|
"geoOptions": MessageLookupByLibrary.simpleMessage("Geo 选项"),
|
||||||
|
"geoResources": MessageLookupByLibrary.simpleMessage("Geo 资源"),
|
||||||
|
"geoSkipped": m7,
|
||||||
|
"geoUpdated": m8,
|
||||||
|
"geoUpdating": m9,
|
||||||
"geodataLoader": MessageLookupByLibrary.simpleMessage("Geo低内存模式"),
|
"geodataLoader": MessageLookupByLibrary.simpleMessage("Geo低内存模式"),
|
||||||
"geodataLoaderDesc": MessageLookupByLibrary.simpleMessage("开启将使用Geo低内存加载器"),
|
"geodataLoaderDesc": MessageLookupByLibrary.simpleMessage("开启将使用Geo低内存加载器"),
|
||||||
"geoipCode": MessageLookupByLibrary.simpleMessage("Geoip代码"),
|
"geoipCode": MessageLookupByLibrary.simpleMessage("Geoip代码"),
|
||||||
@@ -288,7 +311,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"hotkeyConflict": MessageLookupByLibrary.simpleMessage("快捷键冲突"),
|
"hotkeyConflict": MessageLookupByLibrary.simpleMessage("快捷键冲突"),
|
||||||
"hotkeyManagement": MessageLookupByLibrary.simpleMessage("快捷键管理"),
|
"hotkeyManagement": MessageLookupByLibrary.simpleMessage("快捷键管理"),
|
||||||
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage("使用键盘控制应用程序"),
|
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage("使用键盘控制应用程序"),
|
||||||
"hoursAgo": m6,
|
"hours": MessageLookupByLibrary.simpleMessage("小时"),
|
||||||
|
"hoursAgo": m10,
|
||||||
|
"hoursCount": m11,
|
||||||
"icon": MessageLookupByLibrary.simpleMessage("图片"),
|
"icon": MessageLookupByLibrary.simpleMessage("图片"),
|
||||||
"iconRecords": MessageLookupByLibrary.simpleMessage("图标记录"),
|
"iconRecords": MessageLookupByLibrary.simpleMessage("图标记录"),
|
||||||
"iconStyle": MessageLookupByLibrary.simpleMessage("图标样式"),
|
"iconStyle": MessageLookupByLibrary.simpleMessage("图标样式"),
|
||||||
@@ -316,10 +341,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"interval": MessageLookupByLibrary.simpleMessage("间隔"),
|
"interval": MessageLookupByLibrary.simpleMessage("间隔"),
|
||||||
"intranetIP": MessageLookupByLibrary.simpleMessage("内网 IP"),
|
"intranetIP": MessageLookupByLibrary.simpleMessage("内网 IP"),
|
||||||
"invalidBackupFile": MessageLookupByLibrary.simpleMessage("无效备份文件"),
|
"invalidBackupFile": MessageLookupByLibrary.simpleMessage("无效备份文件"),
|
||||||
"invalidPolicy": m7,
|
"invalidPolicy": m12,
|
||||||
"invalidProxy": m8,
|
"invalidProxy": m13,
|
||||||
"invalidProxyProvider": m9,
|
"invalidProxyProvider": m14,
|
||||||
"invalidSubRule": m10,
|
"invalidSubRule": m15,
|
||||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IP/掩码"),
|
"ipcidr": MessageLookupByLibrary.simpleMessage("IP/掩码"),
|
||||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage("开启后将可以接收IPv6流量"),
|
"ipv6Desc": MessageLookupByLibrary.simpleMessage("开启后将可以接收IPv6流量"),
|
||||||
"ipv6InboundDesc": MessageLookupByLibrary.simpleMessage("允许IPv6入站"),
|
"ipv6InboundDesc": MessageLookupByLibrary.simpleMessage("允许IPv6入站"),
|
||||||
@@ -343,7 +368,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"locationPermissionDesc": MessageLookupByLibrary.simpleMessage(
|
"locationPermissionDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
"根据系统要求,获取Wi-Fi名称需要您授予位置权限。",
|
"根据系统要求,获取Wi-Fi名称需要您授予位置权限。",
|
||||||
),
|
),
|
||||||
"locationPermissionGuide": m11,
|
"locationPermissionGuide": m16,
|
||||||
"locationPermissionRequired": MessageLookupByLibrary.simpleMessage(
|
"locationPermissionRequired": MessageLookupByLibrary.simpleMessage(
|
||||||
"需要位置权限",
|
"需要位置权限",
|
||||||
),
|
),
|
||||||
@@ -365,11 +390,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"min": MessageLookupByLibrary.simpleMessage("最小"),
|
"min": MessageLookupByLibrary.simpleMessage("最小"),
|
||||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("退出时最小化"),
|
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("退出时最小化"),
|
||||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage("修改系统默认退出事件"),
|
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage("修改系统默认退出事件"),
|
||||||
"minutesAgo": m12,
|
"minutesAgo": m17,
|
||||||
"mixedPort": MessageLookupByLibrary.simpleMessage("混合端口"),
|
"mixedPort": MessageLookupByLibrary.simpleMessage("混合端口"),
|
||||||
"mode": MessageLookupByLibrary.simpleMessage("模式"),
|
"mode": MessageLookupByLibrary.simpleMessage("模式"),
|
||||||
"monochromeScheme": MessageLookupByLibrary.simpleMessage("单色"),
|
"monochromeScheme": MessageLookupByLibrary.simpleMessage("单色"),
|
||||||
"monthsAgo": m13,
|
"monthsAgo": m18,
|
||||||
"more": MessageLookupByLibrary.simpleMessage("更多"),
|
"more": MessageLookupByLibrary.simpleMessage("更多"),
|
||||||
"name": MessageLookupByLibrary.simpleMessage("名称"),
|
"name": MessageLookupByLibrary.simpleMessage("名称"),
|
||||||
"nameserver": MessageLookupByLibrary.simpleMessage("域名服务器"),
|
"nameserver": MessageLookupByLibrary.simpleMessage("域名服务器"),
|
||||||
@@ -395,8 +420,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"none": MessageLookupByLibrary.simpleMessage("无"),
|
"none": MessageLookupByLibrary.simpleMessage("无"),
|
||||||
"notSelectedTip": MessageLookupByLibrary.simpleMessage("当前代理组无法选中"),
|
"notSelectedTip": MessageLookupByLibrary.simpleMessage("当前代理组无法选中"),
|
||||||
"nullProfileDesc": MessageLookupByLibrary.simpleMessage("没有配置文件,请先添加配置文件"),
|
"nullProfileDesc": MessageLookupByLibrary.simpleMessage("没有配置文件,请先添加配置文件"),
|
||||||
"nullTip": m14,
|
"nullTip": m19,
|
||||||
"numberTip": m15,
|
"numberTip": m20,
|
||||||
"onDemand": MessageLookupByLibrary.simpleMessage("按需运行"),
|
"onDemand": MessageLookupByLibrary.simpleMessage("按需运行"),
|
||||||
"onDemandDesc": MessageLookupByLibrary.simpleMessage("配置程序特定场景运行状态"),
|
"onDemandDesc": MessageLookupByLibrary.simpleMessage("配置程序特定场景运行状态"),
|
||||||
"onlyIcon": MessageLookupByLibrary.simpleMessage("仅图标"),
|
"onlyIcon": MessageLookupByLibrary.simpleMessage("仅图标"),
|
||||||
@@ -431,7 +456,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"port": MessageLookupByLibrary.simpleMessage("端口"),
|
"port": MessageLookupByLibrary.simpleMessage("端口"),
|
||||||
"portConflictTip": MessageLookupByLibrary.simpleMessage("请输入不同的端口"),
|
"portConflictTip": MessageLookupByLibrary.simpleMessage("请输入不同的端口"),
|
||||||
"portTip": m16,
|
"portTip": m21,
|
||||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage("优先使用DOH的http/3"),
|
"preferH3Desc": MessageLookupByLibrary.simpleMessage("优先使用DOH的http/3"),
|
||||||
"prerequisites": MessageLookupByLibrary.simpleMessage("前置条件"),
|
"prerequisites": MessageLookupByLibrary.simpleMessage("前置条件"),
|
||||||
"pressKeyboard": MessageLookupByLibrary.simpleMessage("请按下按键"),
|
"pressKeyboard": MessageLookupByLibrary.simpleMessage("请按下按键"),
|
||||||
@@ -614,6 +639,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"search": MessageLookupByLibrary.simpleMessage("搜索"),
|
"search": MessageLookupByLibrary.simpleMessage("搜索"),
|
||||||
"seconds": MessageLookupByLibrary.simpleMessage("秒"),
|
"seconds": MessageLookupByLibrary.simpleMessage("秒"),
|
||||||
|
"secondsCount": m22,
|
||||||
"selectAll": MessageLookupByLibrary.simpleMessage("全选"),
|
"selectAll": MessageLookupByLibrary.simpleMessage("全选"),
|
||||||
"selectProxies": MessageLookupByLibrary.simpleMessage("选择代理"),
|
"selectProxies": MessageLookupByLibrary.simpleMessage("选择代理"),
|
||||||
"selectProxyProviders": MessageLookupByLibrary.simpleMessage("选择代理集"),
|
"selectProxyProviders": MessageLookupByLibrary.simpleMessage("选择代理集"),
|
||||||
@@ -621,7 +647,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"selectSplitStrategy": MessageLookupByLibrary.simpleMessage("请选择分流策略"),
|
"selectSplitStrategy": MessageLookupByLibrary.simpleMessage("请选择分流策略"),
|
||||||
"selectSubRule": MessageLookupByLibrary.simpleMessage("请选择子规则"),
|
"selectSubRule": MessageLookupByLibrary.simpleMessage("请选择子规则"),
|
||||||
"selected": MessageLookupByLibrary.simpleMessage("已选择"),
|
"selected": MessageLookupByLibrary.simpleMessage("已选择"),
|
||||||
"selectedCountTitle": m17,
|
"selectedCountTitle": m23,
|
||||||
"settings": MessageLookupByLibrary.simpleMessage("设置"),
|
"settings": MessageLookupByLibrary.simpleMessage("设置"),
|
||||||
"show": MessageLookupByLibrary.simpleMessage("显示"),
|
"show": MessageLookupByLibrary.simpleMessage("显示"),
|
||||||
"shrink": MessageLookupByLibrary.simpleMessage("紧凑"),
|
"shrink": MessageLookupByLibrary.simpleMessage("紧凑"),
|
||||||
@@ -697,9 +723,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"upload": MessageLookupByLibrary.simpleMessage("上传"),
|
"upload": MessageLookupByLibrary.simpleMessage("上传"),
|
||||||
"url": MessageLookupByLibrary.simpleMessage("URL"),
|
"url": MessageLookupByLibrary.simpleMessage("URL"),
|
||||||
"urlDesc": MessageLookupByLibrary.simpleMessage("通过URL获取配置文件"),
|
"urlDesc": MessageLookupByLibrary.simpleMessage("通过URL获取配置文件"),
|
||||||
"urlTip": m18,
|
"urlTip": m24,
|
||||||
"useHosts": MessageLookupByLibrary.simpleMessage("使用Hosts"),
|
"useHosts": MessageLookupByLibrary.simpleMessage("使用Hosts"),
|
||||||
"useSystemHosts": MessageLookupByLibrary.simpleMessage("使用系统Hosts"),
|
"useSystemHosts": MessageLookupByLibrary.simpleMessage("使用系统Hosts"),
|
||||||
|
"userAgent": MessageLookupByLibrary.simpleMessage("用户代理"),
|
||||||
"value": MessageLookupByLibrary.simpleMessage("值"),
|
"value": MessageLookupByLibrary.simpleMessage("值"),
|
||||||
"vibrantScheme": MessageLookupByLibrary.simpleMessage("活力"),
|
"vibrantScheme": MessageLookupByLibrary.simpleMessage("活力"),
|
||||||
"view": MessageLookupByLibrary.simpleMessage("查看"),
|
"view": MessageLookupByLibrary.simpleMessage("查看"),
|
||||||
@@ -712,7 +739,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"vpnTip": MessageLookupByLibrary.simpleMessage("重启VPN后改变生效"),
|
"vpnTip": MessageLookupByLibrary.simpleMessage("重启VPN后改变生效"),
|
||||||
"webDAVConfiguration": MessageLookupByLibrary.simpleMessage("WebDAV配置"),
|
"webDAVConfiguration": MessageLookupByLibrary.simpleMessage("WebDAV配置"),
|
||||||
"whitelistMode": MessageLookupByLibrary.simpleMessage("白名单模式"),
|
"whitelistMode": MessageLookupByLibrary.simpleMessage("白名单模式"),
|
||||||
"yearsAgo": m19,
|
"yearsAgo": m25,
|
||||||
"zh_CN": MessageLookupByLibrary.simpleMessage("中文简体"),
|
"zh_CN": MessageLookupByLibrary.simpleMessage("中文简体"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1039,6 +1039,11 @@ class AppLocalizations {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `User-Agent`
|
||||||
|
String get userAgent {
|
||||||
|
return Intl.message('User-Agent', name: 'userAgent', desc: '', args: []);
|
||||||
|
}
|
||||||
|
|
||||||
/// `Unified delay`
|
/// `Unified delay`
|
||||||
String get unifiedDelay {
|
String get unifiedDelay {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
@@ -4378,6 +4383,116 @@ class AppLocalizations {
|
|||||||
String get suspended {
|
String get suspended {
|
||||||
return Intl.message('Suspended...', name: 'suspended', desc: '', args: []);
|
return Intl.message('Suspended...', name: 'suspended', desc: '', args: []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Geo Options`
|
||||||
|
String get geoOptions {
|
||||||
|
return Intl.message('Geo Options', name: 'geoOptions', desc: '', args: []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Auto Update`
|
||||||
|
String get geoAutoUpdate {
|
||||||
|
return Intl.message(
|
||||||
|
'Auto Update',
|
||||||
|
name: 'geoAutoUpdate',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Auto Update Interval`
|
||||||
|
String get geoAutoUpdateInterval {
|
||||||
|
return Intl.message(
|
||||||
|
'Auto Update Interval',
|
||||||
|
name: 'geoAutoUpdateInterval',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Auto update interval must be greater than 0`
|
||||||
|
String get geoAutoUpdateIntervalTip {
|
||||||
|
return Intl.message(
|
||||||
|
'Auto update interval must be greater than 0',
|
||||||
|
name: 'geoAutoUpdateIntervalTip',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `hours`
|
||||||
|
String get hours {
|
||||||
|
return Intl.message('hours', name: 'hours', desc: '', args: []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `{count} hours`
|
||||||
|
String hoursCount(Object count) {
|
||||||
|
return Intl.message(
|
||||||
|
'$count hours',
|
||||||
|
name: 'hoursCount',
|
||||||
|
desc: '',
|
||||||
|
args: [count],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Geo Resources`
|
||||||
|
String get geoResources {
|
||||||
|
return Intl.message(
|
||||||
|
'Geo Resources',
|
||||||
|
name: 'geoResources',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Updating {name}...`
|
||||||
|
String geoUpdating(Object name) {
|
||||||
|
return Intl.message(
|
||||||
|
'Updating $name...',
|
||||||
|
name: 'geoUpdating',
|
||||||
|
desc: '',
|
||||||
|
args: [name],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `{name} skipped`
|
||||||
|
String geoSkipped(Object name) {
|
||||||
|
return Intl.message(
|
||||||
|
'$name skipped',
|
||||||
|
name: 'geoSkipped',
|
||||||
|
desc: '',
|
||||||
|
args: [name],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `{name} updated`
|
||||||
|
String geoUpdated(Object name) {
|
||||||
|
return Intl.message(
|
||||||
|
'$name updated',
|
||||||
|
name: 'geoUpdated',
|
||||||
|
desc: '',
|
||||||
|
args: [name],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `{count} seconds`
|
||||||
|
String secondsCount(Object count) {
|
||||||
|
return Intl.message(
|
||||||
|
'$count seconds',
|
||||||
|
name: 'secondsCount',
|
||||||
|
desc: '',
|
||||||
|
args: [count],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `{count} entries`
|
||||||
|
String entriesCount(Object count) {
|
||||||
|
return Intl.message(
|
||||||
|
'$count entries',
|
||||||
|
name: 'entriesCount',
|
||||||
|
desc: '',
|
||||||
|
args: [count],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import 'application.dart';
|
|||||||
import 'common/common.dart';
|
import 'common/common.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
try {
|
try {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
|
||||||
if (system.isDesktop) {
|
if (system.isDesktop) {
|
||||||
await RustLib.init();
|
await RustLib.init();
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ Future<void> main() async {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
return runApp(
|
runApp(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
home: InitErrorScreen(error: e, stack: s),
|
home: InitErrorScreen(error: e, stack: s),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:fl_clash/common/common.dart';
|
import 'package:fl_clash/common/common.dart';
|
||||||
import 'package:fl_clash/core/core.dart';
|
import 'package:fl_clash/core/core.dart';
|
||||||
import 'package:fl_clash/enum/enum.dart';
|
import 'package:fl_clash/enum/enum.dart';
|
||||||
@@ -72,7 +74,7 @@ class _CoreContainerState extends ConsumerState<CoreManager>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onLog(Log log) {
|
void onLog(Log log) {
|
||||||
// ref.read(logsProvider.notifier).add(log);
|
ref.read(logsProvider.notifier).add(log);
|
||||||
if (log.logLevel == LogLevel.error) {
|
if (log.logLevel == LogLevel.error) {
|
||||||
globalState.showNotifier(log.payload);
|
globalState.showNotifier(log.payload);
|
||||||
}
|
}
|
||||||
@@ -109,4 +111,23 @@ class _CoreContainerState extends ConsumerState<CoreManager>
|
|||||||
await coreController.shutdown(false);
|
await coreController.shutdown(false);
|
||||||
super.onCrash(message);
|
super.onCrash(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onGeoUpdate(String geoType, bool updating, bool skipped, String? error) {
|
||||||
|
final geoResource = GeoResource.fromJson(geoType.toLowerCase());
|
||||||
|
final key = geoResource.updatingKey;
|
||||||
|
final l10n = currentAppLocalizations;
|
||||||
|
if (updating) {
|
||||||
|
globalState.showNotifier(l10n.geoUpdating(geoResource.name));
|
||||||
|
} else if (skipped) {
|
||||||
|
globalState.showNotifier(l10n.geoSkipped(geoResource.name));
|
||||||
|
} else {
|
||||||
|
globalState.showNotifier(l10n.geoUpdated(geoResource.name));
|
||||||
|
}
|
||||||
|
ref.read(isUpdatingProvider(key).notifier).value = updating;
|
||||||
|
if (!updating && error != null && error.isNotEmpty) {
|
||||||
|
globalState.showNotifier(error);
|
||||||
|
}
|
||||||
|
super.onGeoUpdate(geoType, updating, skipped, error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class _HotKeyManagerState extends ConsumerState<HotKeyManager> {
|
|||||||
await Future.wait(hotkeyActionHandles);
|
await Future.wait(hotkeyActionHandles);
|
||||||
}
|
}
|
||||||
|
|
||||||
Shortcuts _buildShortcuts(Widget child) {
|
Shortcuts _buildCloseShortcuts(Widget child) {
|
||||||
return Shortcuts(
|
return Shortcuts(
|
||||||
shortcuts: {
|
shortcuts: {
|
||||||
utils.controlSingleActivator(LogicalKeyboardKey.keyW):
|
utils.controlSingleActivator(LogicalKeyboardKey.keyW):
|
||||||
@@ -84,7 +84,7 @@ class _HotKeyManagerState extends ConsumerState<HotKeyManager> {
|
|||||||
CloseWindowIntent: CallbackAction<CloseWindowIntent>(
|
CloseWindowIntent: CallbackAction<CloseWindowIntent>(
|
||||||
onInvoke: (_) => globalState.container
|
onInvoke: (_) => globalState.container
|
||||||
.read(systemActionProvider.notifier)
|
.read(systemActionProvider.notifier)
|
||||||
.handleBackOrExit(),
|
.handleClose(false),
|
||||||
),
|
),
|
||||||
DoNothingIntent: CallbackAction<DoNothingIntent>(
|
DoNothingIntent: CallbackAction<DoNothingIntent>(
|
||||||
onInvoke: (_) => null,
|
onInvoke: (_) => null,
|
||||||
@@ -97,6 +97,6 @@ class _HotKeyManagerState extends ConsumerState<HotKeyManager> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return _buildShortcuts(widget.child);
|
return _buildCloseShortcuts(widget.child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import 'dart:math';
|
|||||||
import 'package:fl_clash/common/common.dart';
|
import 'package:fl_clash/common/common.dart';
|
||||||
import 'package:fl_clash/common/theme.dart';
|
import 'package:fl_clash/common/theme.dart';
|
||||||
import 'package:fl_clash/providers/action.dart';
|
import 'package:fl_clash/providers/action.dart';
|
||||||
import 'package:fl_clash/providers/app.dart';
|
|
||||||
import 'package:fl_clash/providers/config.dart';
|
import 'package:fl_clash/providers/config.dart';
|
||||||
import 'package:fl_clash/state.dart';
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -21,41 +20,25 @@ class ThemeManager extends ConsumerWidget {
|
|||||||
if (!system.isAndroid) {
|
if (!system.isAndroid) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
return AnnotatedRegion<SystemUiMode>(
|
return Consumer(
|
||||||
sized: false,
|
builder: (context, ref, _) {
|
||||||
value: SystemUiMode.edgeToEdge,
|
final brightness = ref.watch(currentBrightnessProvider);
|
||||||
child: Consumer(
|
final iconBrightness = brightness == Brightness.light
|
||||||
builder: (context, ref, _) {
|
? Brightness.dark
|
||||||
final brightness = ref.watch(currentBrightnessProvider);
|
: Brightness.light;
|
||||||
final iconBrightness = brightness == Brightness.light
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
? Brightness.dark
|
value: SystemUiOverlayStyle(
|
||||||
: Brightness.light;
|
statusBarColor: Colors.transparent,
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
statusBarIconBrightness: iconBrightness,
|
||||||
ref
|
systemNavigationBarIconBrightness: iconBrightness,
|
||||||
.read(systemUiOverlayStyleStateProvider.notifier)
|
systemNavigationBarColor: Colors.transparent,
|
||||||
.update(
|
systemNavigationBarDividerColor: Colors.transparent,
|
||||||
(state) => state.copyWith(
|
systemNavigationBarContrastEnforced: false,
|
||||||
statusBarColor: Colors.transparent,
|
),
|
||||||
statusBarIconBrightness: iconBrightness,
|
sized: false,
|
||||||
systemNavigationBarIconBrightness: iconBrightness,
|
child: child,
|
||||||
systemNavigationBarColor: context.colorScheme.surface,
|
);
|
||||||
systemNavigationBarDividerColor: Colors.transparent,
|
},
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
|
||||||
value: SystemUiOverlayStyle(
|
|
||||||
statusBarColor: Colors.transparent,
|
|
||||||
statusBarIconBrightness: iconBrightness,
|
|
||||||
systemNavigationBarIconBrightness: iconBrightness,
|
|
||||||
systemNavigationBarColor: context.colorScheme.surface,
|
|
||||||
systemNavigationBarDividerColor: Colors.transparent,
|
|
||||||
),
|
|
||||||
sized: false,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class _WindowContainerState extends ConsumerState<WindowManager>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onWindowClose() async {
|
void onWindowClose() async {
|
||||||
await ref.read(systemActionProvider.notifier).handleBackOrExit();
|
await ref.read(systemActionProvider.notifier).handleClose();
|
||||||
super.onWindowClose();
|
super.onWindowClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +178,10 @@ class _WindowHeaderState extends State<WindowHeader> {
|
|||||||
windowExtManager.setWindowCornerPreference(round: false);
|
windowExtManager.setWindowCornerPreference(round: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isMaximizedNotifier.value = await windowManager.isMaximized();
|
final res = await windowManager.isMaximized();
|
||||||
|
if (mounted) {
|
||||||
|
isMaximizedNotifier.value = res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updatePin() async {
|
Future<void> _updatePin() async {
|
||||||
@@ -226,7 +229,7 @@ class _WindowHeaderState extends State<WindowHeader> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
globalState.container
|
globalState.container
|
||||||
.read(systemActionProvider.notifier)
|
.read(systemActionProvider.notifier)
|
||||||
.handleBackOrExit();
|
.handleClose();
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.close),
|
icon: const Icon(Icons.close),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -3,13 +3,23 @@ import 'package:fl_clash/enum/enum.dart';
|
|||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
part 'generated/clash_config.freezed.dart';
|
part 'generated/clash_config.freezed.dart';
|
||||||
|
|
||||||
part 'generated/clash_config.g.dart';
|
part 'generated/clash_config.g.dart';
|
||||||
|
|
||||||
const defaultClashConfig = PatchClashConfig();
|
const defaultClashConfig = PatchClashConfig();
|
||||||
|
|
||||||
const defaultTun = Tun();
|
const defaultTun = Tun();
|
||||||
const defaultDns = Dns();
|
const defaultDns = Dns();
|
||||||
const defaultGeoXUrl = GeoXUrl();
|
const defaultGeoXUrl = {
|
||||||
|
GeoResource.MMDB:
|
||||||
|
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb',
|
||||||
|
GeoResource.ASN:
|
||||||
|
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb',
|
||||||
|
GeoResource.GEOIP:
|
||||||
|
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat',
|
||||||
|
GeoResource.GEOSITE:
|
||||||
|
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat',
|
||||||
|
};
|
||||||
|
|
||||||
const defaultMixedPort = 7890;
|
const defaultMixedPort = 7890;
|
||||||
const defaultKeepAliveInterval = 30;
|
const defaultKeepAliveInterval = 30;
|
||||||
@@ -309,42 +319,6 @@ abstract class Dns with _$Dns {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
|
||||||
abstract class GeoXUrl with _$GeoXUrl {
|
|
||||||
const factory GeoXUrl({
|
|
||||||
@Default(
|
|
||||||
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb',
|
|
||||||
)
|
|
||||||
String mmdb,
|
|
||||||
@Default(
|
|
||||||
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb',
|
|
||||||
)
|
|
||||||
String asn,
|
|
||||||
@Default(
|
|
||||||
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat',
|
|
||||||
)
|
|
||||||
String geoip,
|
|
||||||
@Default(
|
|
||||||
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat',
|
|
||||||
)
|
|
||||||
String geosite,
|
|
||||||
}) = _GeoXUrl;
|
|
||||||
|
|
||||||
factory GeoXUrl.fromJson(Map<String, Object?> json) =>
|
|
||||||
_$GeoXUrlFromJson(json);
|
|
||||||
|
|
||||||
factory GeoXUrl.safeFormJson(Map<String, Object?>? json) {
|
|
||||||
if (json == null) {
|
|
||||||
return defaultGeoXUrl;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return GeoXUrl.fromJson(json);
|
|
||||||
} catch (_) {
|
|
||||||
return defaultGeoXUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class Rule with _$Rule {
|
abstract class Rule with _$Rule {
|
||||||
const factory Rule({
|
const factory Rule({
|
||||||
@@ -542,6 +516,24 @@ abstract class ClashConfig with _$ClashConfig {
|
|||||||
_$ClashConfigFromJson(json);
|
_$ClashConfigFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension GeoResourceUrlMapExt on Map<GeoResource, String> {
|
||||||
|
Map<String, String> get raw =>
|
||||||
|
map((key, value) => MapEntry(key.value, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<GeoResource, String> _geoXUrlFromJson(Map<String, Object?>? json) {
|
||||||
|
if (json == null) {
|
||||||
|
return defaultGeoXUrl;
|
||||||
|
}
|
||||||
|
return json.map(
|
||||||
|
(key, value) => MapEntry(GeoResource.fromJson(key), value as String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> _geoXUrlToJson(Map<GeoResource, String> value) {
|
||||||
|
return value.raw;
|
||||||
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class PatchClashConfig with _$PatchClashConfig {
|
abstract class PatchClashConfig with _$PatchClashConfig {
|
||||||
const factory PatchClashConfig({
|
const factory PatchClashConfig({
|
||||||
@@ -568,8 +560,12 @@ abstract class PatchClashConfig with _$PatchClashConfig {
|
|||||||
@Default(defaultTun) @JsonKey(fromJson: Tun.safeFormJson) Tun tun,
|
@Default(defaultTun) @JsonKey(fromJson: Tun.safeFormJson) Tun tun,
|
||||||
@Default(defaultDns) @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,
|
@Default(defaultDns) @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,
|
||||||
@Default(defaultGeoXUrl)
|
@Default(defaultGeoXUrl)
|
||||||
@JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson)
|
@JsonKey(
|
||||||
GeoXUrl geoXUrl,
|
name: 'geox-url',
|
||||||
|
fromJson: _geoXUrlFromJson,
|
||||||
|
toJson: _geoXUrlToJson,
|
||||||
|
)
|
||||||
|
Map<GeoResource, String> geoXUrl,
|
||||||
@Default(GeodataLoader.memconservative)
|
@Default(GeodataLoader.memconservative)
|
||||||
@JsonKey(name: 'geodata-loader')
|
@JsonKey(name: 'geodata-loader')
|
||||||
GeodataLoader geodataLoader,
|
GeodataLoader geodataLoader,
|
||||||
@@ -578,6 +574,8 @@ abstract class PatchClashConfig with _$PatchClashConfig {
|
|||||||
@JsonKey(name: 'external-controller')
|
@JsonKey(name: 'external-controller')
|
||||||
ExternalControllerStatus externalController,
|
ExternalControllerStatus externalController,
|
||||||
@Default({}) Map<String, String> hosts,
|
@Default({}) Map<String, String> hosts,
|
||||||
|
@Default(false) @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,
|
||||||
|
@Default(24) @JsonKey(name: 'geo-update-interval') int geoUpdateInterval,
|
||||||
}) = _PatchClashConfig;
|
}) = _PatchClashConfig;
|
||||||
|
|
||||||
factory PatchClashConfig.fromJson(Map<String, Object?> json) =>
|
factory PatchClashConfig.fromJson(Map<String, Object?> json) =>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
|||||||
import 'clash_config.dart';
|
import 'clash_config.dart';
|
||||||
|
|
||||||
part 'generated/common.freezed.dart';
|
part 'generated/common.freezed.dart';
|
||||||
|
|
||||||
part 'generated/common.g.dart';
|
part 'generated/common.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@@ -271,7 +272,7 @@ extension TrafficExt on Traffic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String get trayTitle {
|
String get trayTitle {
|
||||||
return '${up.shortTraffic.show}/s \n ${down.shortTraffic.show}/s';
|
return '${up.shortTraffic.show}/s\n${down.shortTraffic.show}/s';
|
||||||
}
|
}
|
||||||
|
|
||||||
num get speed => up + down;
|
num get speed => up + down;
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ abstract class AppSettingProps with _$AppSettingProps {
|
|||||||
@Default(false) bool developerMode,
|
@Default(false) bool developerMode,
|
||||||
@Default(RestoreStrategy.compatible) RestoreStrategy restoreStrategy,
|
@Default(RestoreStrategy.compatible) RestoreStrategy restoreStrategy,
|
||||||
@Default(true) bool showTrayTitle,
|
@Default(true) bool showTrayTitle,
|
||||||
|
@Default('') String customUserAgent,
|
||||||
}) = _AppSettingProps;
|
}) = _AppSettingProps;
|
||||||
|
|
||||||
factory AppSettingProps.fromJson(Map<String, Object?> json) =>
|
factory AppSettingProps.fromJson(Map<String, Object?> json) =>
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ abstract class UpdateParams with _$UpdateParams {
|
|||||||
@JsonKey(name: 'external-controller')
|
@JsonKey(name: 'external-controller')
|
||||||
required ExternalControllerStatus externalController,
|
required ExternalControllerStatus externalController,
|
||||||
@JsonKey(name: 'unified-delay') required bool unifiedDelay,
|
@JsonKey(name: 'unified-delay') required bool unifiedDelay,
|
||||||
|
@Default(false) @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,
|
||||||
|
@Default(24) @JsonKey(name: 'geo-update-interval') int geoUpdateInterval,
|
||||||
}) = _UpdateParams;
|
}) = _UpdateParams;
|
||||||
|
|
||||||
factory UpdateParams.fromJson(Map<String, dynamic> json) =>
|
factory UpdateParams.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@@ -3000,278 +3000,6 @@ $FallbackFilterCopyWith<$Res> get fallbackFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
mixin _$GeoXUrl {
|
|
||||||
|
|
||||||
String get mmdb; String get asn; String get geoip; String get geosite;
|
|
||||||
/// Create a copy of GeoXUrl
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$GeoXUrlCopyWith<GeoXUrl> get copyWith => _$GeoXUrlCopyWithImpl<GeoXUrl>(this as GeoXUrl, _$identity);
|
|
||||||
|
|
||||||
/// Serializes this GeoXUrl to a JSON map.
|
|
||||||
Map<String, dynamic> toJson();
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is GeoXUrl&&(identical(other.mmdb, mmdb) || other.mmdb == mmdb)&&(identical(other.asn, asn) || other.asn == asn)&&(identical(other.geoip, geoip) || other.geoip == geoip)&&(identical(other.geosite, geosite) || other.geosite == geosite));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,mmdb,asn,geoip,geosite);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'GeoXUrl(mmdb: $mmdb, asn: $asn, geoip: $geoip, geosite: $geosite)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class $GeoXUrlCopyWith<$Res> {
|
|
||||||
factory $GeoXUrlCopyWith(GeoXUrl value, $Res Function(GeoXUrl) _then) = _$GeoXUrlCopyWithImpl;
|
|
||||||
@useResult
|
|
||||||
$Res call({
|
|
||||||
String mmdb, String asn, String geoip, String geosite
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class _$GeoXUrlCopyWithImpl<$Res>
|
|
||||||
implements $GeoXUrlCopyWith<$Res> {
|
|
||||||
_$GeoXUrlCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final GeoXUrl _self;
|
|
||||||
final $Res Function(GeoXUrl) _then;
|
|
||||||
|
|
||||||
/// Create a copy of GeoXUrl
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? mmdb = null,Object? asn = null,Object? geoip = null,Object? geosite = null,}) {
|
|
||||||
return _then(_self.copyWith(
|
|
||||||
mmdb: null == mmdb ? _self.mmdb : mmdb // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,asn: null == asn ? _self.asn : asn // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,geoip: null == geoip ? _self.geoip : geoip // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,geosite: null == geosite ? _self.geosite : geosite // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Adds pattern-matching-related methods to [GeoXUrl].
|
|
||||||
extension GeoXUrlPatterns on GeoXUrl {
|
|
||||||
/// A variant of `map` that fallback to returning `orElse`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _GeoXUrl value)? $default,{required TResult orElse(),}){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoXUrl() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// Callbacks receives the raw object, upcasted.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case final Subclass2 value:
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _GeoXUrl value) $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoXUrl():
|
|
||||||
return $default(_that);case _:
|
|
||||||
throw StateError('Unexpected subclass');
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `map` that fallback to returning `null`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _GeoXUrl value)? $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoXUrl() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to an `orElse` callback.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String mmdb, String asn, String geoip, String geosite)? $default,{required TResult orElse(),}) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoXUrl() when $default != null:
|
|
||||||
return $default(_that.mmdb,_that.asn,_that.geoip,_that.geosite);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// As opposed to `map`, this offers destructuring.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case Subclass2(:final field2):
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String mmdb, String asn, String geoip, String geosite) $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoXUrl():
|
|
||||||
return $default(_that.mmdb,_that.asn,_that.geoip,_that.geosite);case _:
|
|
||||||
throw StateError('Unexpected subclass');
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to returning `null`
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String mmdb, String asn, String geoip, String geosite)? $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoXUrl() when $default != null:
|
|
||||||
return $default(_that.mmdb,_that.asn,_that.geoip,_that.geosite);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
@JsonSerializable()
|
|
||||||
|
|
||||||
class _GeoXUrl implements GeoXUrl {
|
|
||||||
const _GeoXUrl({this.mmdb = 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb', this.asn = 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb', this.geoip = 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat', this.geosite = 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat'});
|
|
||||||
factory _GeoXUrl.fromJson(Map<String, dynamic> json) => _$GeoXUrlFromJson(json);
|
|
||||||
|
|
||||||
@override@JsonKey() final String mmdb;
|
|
||||||
@override@JsonKey() final String asn;
|
|
||||||
@override@JsonKey() final String geoip;
|
|
||||||
@override@JsonKey() final String geosite;
|
|
||||||
|
|
||||||
/// Create a copy of GeoXUrl
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$GeoXUrlCopyWith<_GeoXUrl> get copyWith => __$GeoXUrlCopyWithImpl<_GeoXUrl>(this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return _$GeoXUrlToJson(this, );
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GeoXUrl&&(identical(other.mmdb, mmdb) || other.mmdb == mmdb)&&(identical(other.asn, asn) || other.asn == asn)&&(identical(other.geoip, geoip) || other.geoip == geoip)&&(identical(other.geosite, geosite) || other.geosite == geosite));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,mmdb,asn,geoip,geosite);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'GeoXUrl(mmdb: $mmdb, asn: $asn, geoip: $geoip, geosite: $geosite)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class _$GeoXUrlCopyWith<$Res> implements $GeoXUrlCopyWith<$Res> {
|
|
||||||
factory _$GeoXUrlCopyWith(_GeoXUrl value, $Res Function(_GeoXUrl) _then) = __$GeoXUrlCopyWithImpl;
|
|
||||||
@override @useResult
|
|
||||||
$Res call({
|
|
||||||
String mmdb, String asn, String geoip, String geosite
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class __$GeoXUrlCopyWithImpl<$Res>
|
|
||||||
implements _$GeoXUrlCopyWith<$Res> {
|
|
||||||
__$GeoXUrlCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final _GeoXUrl _self;
|
|
||||||
final $Res Function(_GeoXUrl) _then;
|
|
||||||
|
|
||||||
/// Create a copy of GeoXUrl
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? mmdb = null,Object? asn = null,Object? geoip = null,Object? geosite = null,}) {
|
|
||||||
return _then(_GeoXUrl(
|
|
||||||
mmdb: null == mmdb ? _self.mmdb : mmdb // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,asn: null == asn ? _self.asn : asn // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,geoip: null == geoip ? _self.geoip : geoip // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,geosite: null == geosite ? _self.geosite : geosite // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$Rule {
|
mixin _$Rule {
|
||||||
|
|
||||||
@@ -3885,7 +3613,7 @@ as Map<String, String>,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$PatchClashConfig {
|
mixin _$PatchClashConfig {
|
||||||
|
|
||||||
@JsonKey(name: 'mixed-port') int get mixedPort;@JsonKey(name: 'socks-port') int get socksPort;@JsonKey(name: 'port') int get port;@JsonKey(name: 'redir-port') int get redirPort;@JsonKey(name: 'tproxy-port') int get tproxyPort; Mode get mode;@JsonKey(name: 'allow-lan') bool get allowLan;@JsonKey(name: 'log-level') LogLevel get logLevel; bool get ipv6;@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode get findProcessMode;@JsonKey(name: 'keep-alive-interval') int get keepAliveInterval;@JsonKey(name: 'unified-delay') bool get unifiedDelay;@JsonKey(name: 'tcp-concurrent') bool get tcpConcurrent;@JsonKey(fromJson: Tun.safeFormJson) Tun get tun;@JsonKey(fromJson: Dns.safeDnsFromJson) Dns get dns;@JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson) GeoXUrl get geoXUrl;@JsonKey(name: 'geodata-loader') GeodataLoader get geodataLoader;@JsonKey(name: 'global-ua') String? get globalUa;@JsonKey(name: 'external-controller') ExternalControllerStatus get externalController; Map<String, String> get hosts;
|
@JsonKey(name: 'mixed-port') int get mixedPort;@JsonKey(name: 'socks-port') int get socksPort;@JsonKey(name: 'port') int get port;@JsonKey(name: 'redir-port') int get redirPort;@JsonKey(name: 'tproxy-port') int get tproxyPort; Mode get mode;@JsonKey(name: 'allow-lan') bool get allowLan;@JsonKey(name: 'log-level') LogLevel get logLevel; bool get ipv6;@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode get findProcessMode;@JsonKey(name: 'keep-alive-interval') int get keepAliveInterval;@JsonKey(name: 'unified-delay') bool get unifiedDelay;@JsonKey(name: 'tcp-concurrent') bool get tcpConcurrent;@JsonKey(fromJson: Tun.safeFormJson) Tun get tun;@JsonKey(fromJson: Dns.safeDnsFromJson) Dns get dns;@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map<GeoResource, String> get geoXUrl;@JsonKey(name: 'geodata-loader') GeodataLoader get geodataLoader;@JsonKey(name: 'global-ua') String? get globalUa;@JsonKey(name: 'external-controller') ExternalControllerStatus get externalController; Map<String, String> get hosts;@JsonKey(name: 'geo-auto-update') bool get geoAutoUpdate;@JsonKey(name: 'geo-update-interval') int get geoUpdateInterval;
|
||||||
/// Create a copy of PatchClashConfig
|
/// Create a copy of PatchClashConfig
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -3898,16 +3626,16 @@ $PatchClashConfigCopyWith<PatchClashConfig> get copyWith => _$PatchClashConfigCo
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is PatchClashConfig&&(identical(other.mixedPort, mixedPort) || other.mixedPort == mixedPort)&&(identical(other.socksPort, socksPort) || other.socksPort == socksPort)&&(identical(other.port, port) || other.port == port)&&(identical(other.redirPort, redirPort) || other.redirPort == redirPort)&&(identical(other.tproxyPort, tproxyPort) || other.tproxyPort == tproxyPort)&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.allowLan, allowLan) || other.allowLan == allowLan)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.keepAliveInterval, keepAliveInterval) || other.keepAliveInterval == keepAliveInterval)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.dns, dns) || other.dns == dns)&&(identical(other.geoXUrl, geoXUrl) || other.geoXUrl == geoXUrl)&&(identical(other.geodataLoader, geodataLoader) || other.geodataLoader == geodataLoader)&&(identical(other.globalUa, globalUa) || other.globalUa == globalUa)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&const DeepCollectionEquality().equals(other.hosts, hosts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is PatchClashConfig&&(identical(other.mixedPort, mixedPort) || other.mixedPort == mixedPort)&&(identical(other.socksPort, socksPort) || other.socksPort == socksPort)&&(identical(other.port, port) || other.port == port)&&(identical(other.redirPort, redirPort) || other.redirPort == redirPort)&&(identical(other.tproxyPort, tproxyPort) || other.tproxyPort == tproxyPort)&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.allowLan, allowLan) || other.allowLan == allowLan)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.keepAliveInterval, keepAliveInterval) || other.keepAliveInterval == keepAliveInterval)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.dns, dns) || other.dns == dns)&&const DeepCollectionEquality().equals(other.geoXUrl, geoXUrl)&&(identical(other.geodataLoader, geodataLoader) || other.geodataLoader == geodataLoader)&&(identical(other.globalUa, globalUa) || other.globalUa == globalUa)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&const DeepCollectionEquality().equals(other.hosts, hosts)&&(identical(other.geoAutoUpdate, geoAutoUpdate) || other.geoAutoUpdate == geoAutoUpdate)&&(identical(other.geoUpdateInterval, geoUpdateInterval) || other.geoUpdateInterval == geoUpdateInterval));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,mixedPort,socksPort,port,redirPort,tproxyPort,mode,allowLan,logLevel,ipv6,findProcessMode,keepAliveInterval,unifiedDelay,tcpConcurrent,tun,dns,geoXUrl,geodataLoader,globalUa,externalController,const DeepCollectionEquality().hash(hosts)]);
|
int get hashCode => Object.hashAll([runtimeType,mixedPort,socksPort,port,redirPort,tproxyPort,mode,allowLan,logLevel,ipv6,findProcessMode,keepAliveInterval,unifiedDelay,tcpConcurrent,tun,dns,const DeepCollectionEquality().hash(geoXUrl),geodataLoader,globalUa,externalController,const DeepCollectionEquality().hash(hosts),geoAutoUpdate,geoUpdateInterval]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PatchClashConfig(mixedPort: $mixedPort, socksPort: $socksPort, port: $port, redirPort: $redirPort, tproxyPort: $tproxyPort, mode: $mode, allowLan: $allowLan, logLevel: $logLevel, ipv6: $ipv6, findProcessMode: $findProcessMode, keepAliveInterval: $keepAliveInterval, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, tun: $tun, dns: $dns, geoXUrl: $geoXUrl, geodataLoader: $geodataLoader, globalUa: $globalUa, externalController: $externalController, hosts: $hosts)';
|
return 'PatchClashConfig(mixedPort: $mixedPort, socksPort: $socksPort, port: $port, redirPort: $redirPort, tproxyPort: $tproxyPort, mode: $mode, allowLan: $allowLan, logLevel: $logLevel, ipv6: $ipv6, findProcessMode: $findProcessMode, keepAliveInterval: $keepAliveInterval, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, tun: $tun, dns: $dns, geoXUrl: $geoXUrl, geodataLoader: $geodataLoader, globalUa: $globalUa, externalController: $externalController, hosts: $hosts, geoAutoUpdate: $geoAutoUpdate, geoUpdateInterval: $geoUpdateInterval)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3918,11 +3646,11 @@ abstract mixin class $PatchClashConfigCopyWith<$Res> {
|
|||||||
factory $PatchClashConfigCopyWith(PatchClashConfig value, $Res Function(PatchClashConfig) _then) = _$PatchClashConfigCopyWithImpl;
|
factory $PatchClashConfigCopyWith(PatchClashConfig value, $Res Function(PatchClashConfig) _then) = _$PatchClashConfigCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'socks-port') int socksPort,@JsonKey(name: 'port') int port,@JsonKey(name: 'redir-port') int redirPort,@JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode,@JsonKey(name: 'keep-alive-interval') int keepAliveInterval,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(fromJson: Tun.safeFormJson) Tun tun,@JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,@JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson) GeoXUrl geoXUrl,@JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader,@JsonKey(name: 'global-ua') String? globalUa,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts
|
@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'socks-port') int socksPort,@JsonKey(name: 'port') int port,@JsonKey(name: 'redir-port') int redirPort,@JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode,@JsonKey(name: 'keep-alive-interval') int keepAliveInterval,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(fromJson: Tun.safeFormJson) Tun tun,@JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map<GeoResource, String> geoXUrl,@JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader,@JsonKey(name: 'global-ua') String? globalUa,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$TunCopyWith<$Res> get tun;$DnsCopyWith<$Res> get dns;$GeoXUrlCopyWith<$Res> get geoXUrl;
|
$TunCopyWith<$Res> get tun;$DnsCopyWith<$Res> get dns;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -3935,7 +3663,7 @@ class _$PatchClashConfigCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of PatchClashConfig
|
/// Create a copy of PatchClashConfig
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? mixedPort = null,Object? socksPort = null,Object? port = null,Object? redirPort = null,Object? tproxyPort = null,Object? mode = null,Object? allowLan = null,Object? logLevel = null,Object? ipv6 = null,Object? findProcessMode = null,Object? keepAliveInterval = null,Object? unifiedDelay = null,Object? tcpConcurrent = null,Object? tun = null,Object? dns = null,Object? geoXUrl = null,Object? geodataLoader = null,Object? globalUa = freezed,Object? externalController = null,Object? hosts = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? mixedPort = null,Object? socksPort = null,Object? port = null,Object? redirPort = null,Object? tproxyPort = null,Object? mode = null,Object? allowLan = null,Object? logLevel = null,Object? ipv6 = null,Object? findProcessMode = null,Object? keepAliveInterval = null,Object? unifiedDelay = null,Object? tcpConcurrent = null,Object? tun = null,Object? dns = null,Object? geoXUrl = null,Object? geodataLoader = null,Object? globalUa = freezed,Object? externalController = null,Object? hosts = null,Object? geoAutoUpdate = null,Object? geoUpdateInterval = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable
|
mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable
|
||||||
as int,socksPort: null == socksPort ? _self.socksPort : socksPort // ignore: cast_nullable_to_non_nullable
|
as int,socksPort: null == socksPort ? _self.socksPort : socksPort // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -3953,11 +3681,13 @@ as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurre
|
|||||||
as bool,tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable
|
as bool,tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable
|
||||||
as Tun,dns: null == dns ? _self.dns : dns // ignore: cast_nullable_to_non_nullable
|
as Tun,dns: null == dns ? _self.dns : dns // ignore: cast_nullable_to_non_nullable
|
||||||
as Dns,geoXUrl: null == geoXUrl ? _self.geoXUrl : geoXUrl // ignore: cast_nullable_to_non_nullable
|
as Dns,geoXUrl: null == geoXUrl ? _self.geoXUrl : geoXUrl // ignore: cast_nullable_to_non_nullable
|
||||||
as GeoXUrl,geodataLoader: null == geodataLoader ? _self.geodataLoader : geodataLoader // ignore: cast_nullable_to_non_nullable
|
as Map<GeoResource, String>,geodataLoader: null == geodataLoader ? _self.geodataLoader : geodataLoader // ignore: cast_nullable_to_non_nullable
|
||||||
as GeodataLoader,globalUa: freezed == globalUa ? _self.globalUa : globalUa // ignore: cast_nullable_to_non_nullable
|
as GeodataLoader,globalUa: freezed == globalUa ? _self.globalUa : globalUa // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable
|
as String?,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable
|
||||||
as ExternalControllerStatus,hosts: null == hosts ? _self.hosts : hosts // ignore: cast_nullable_to_non_nullable
|
as ExternalControllerStatus,hosts: null == hosts ? _self.hosts : hosts // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, String>,
|
as Map<String, String>,geoAutoUpdate: null == geoAutoUpdate ? _self.geoAutoUpdate : geoAutoUpdate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,geoUpdateInterval: null == geoUpdateInterval ? _self.geoUpdateInterval : geoUpdateInterval // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of PatchClashConfig
|
/// Create a copy of PatchClashConfig
|
||||||
@@ -3978,15 +3708,6 @@ $DnsCopyWith<$Res> get dns {
|
|||||||
return $DnsCopyWith<$Res>(_self.dns, (value) {
|
return $DnsCopyWith<$Res>(_self.dns, (value) {
|
||||||
return _then(_self.copyWith(dns: value));
|
return _then(_self.copyWith(dns: value));
|
||||||
});
|
});
|
||||||
}/// Create a copy of PatchClashConfig
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$GeoXUrlCopyWith<$Res> get geoXUrl {
|
|
||||||
|
|
||||||
return $GeoXUrlCopyWith<$Res>(_self.geoXUrl, (value) {
|
|
||||||
return _then(_self.copyWith(geoXUrl: value));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4069,10 +3790,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'socks-port') int socksPort, @JsonKey(name: 'port') int port, @JsonKey(name: 'redir-port') int redirPort, @JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson) GeoXUrl geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'socks-port') int socksPort, @JsonKey(name: 'port') int port, @JsonKey(name: 'redir-port') int redirPort, @JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map<GeoResource, String> geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PatchClashConfig() when $default != null:
|
case _PatchClashConfig() when $default != null:
|
||||||
return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.keepAliveInterval,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.hosts);case _:
|
return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.keepAliveInterval,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4090,10 +3811,10 @@ return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'socks-port') int socksPort, @JsonKey(name: 'port') int port, @JsonKey(name: 'redir-port') int redirPort, @JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson) GeoXUrl geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'socks-port') int socksPort, @JsonKey(name: 'port') int port, @JsonKey(name: 'redir-port') int redirPort, @JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map<GeoResource, String> geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PatchClashConfig():
|
case _PatchClashConfig():
|
||||||
return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.keepAliveInterval,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.hosts);case _:
|
return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.keepAliveInterval,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _:
|
||||||
throw StateError('Unexpected subclass');
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4110,10 +3831,10 @@ return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'socks-port') int socksPort, @JsonKey(name: 'port') int port, @JsonKey(name: 'redir-port') int redirPort, @JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson) GeoXUrl geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'socks-port') int socksPort, @JsonKey(name: 'port') int port, @JsonKey(name: 'redir-port') int redirPort, @JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map<GeoResource, String> geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PatchClashConfig() when $default != null:
|
case _PatchClashConfig() when $default != null:
|
||||||
return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.keepAliveInterval,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.hosts);case _:
|
return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.keepAliveInterval,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4125,7 +3846,7 @@ return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _PatchClashConfig implements PatchClashConfig {
|
class _PatchClashConfig implements PatchClashConfig {
|
||||||
const _PatchClashConfig({@JsonKey(name: 'mixed-port') this.mixedPort = defaultMixedPort, @JsonKey(name: 'socks-port') this.socksPort = 0, @JsonKey(name: 'port') this.port = 0, @JsonKey(name: 'redir-port') this.redirPort = 0, @JsonKey(name: 'tproxy-port') this.tproxyPort = 0, this.mode = Mode.rule, @JsonKey(name: 'allow-lan') this.allowLan = false, @JsonKey(name: 'log-level') this.logLevel = LogLevel.error, this.ipv6 = false, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) this.findProcessMode = FindProcessMode.always, @JsonKey(name: 'keep-alive-interval') this.keepAliveInterval = defaultKeepAliveInterval, @JsonKey(name: 'unified-delay') this.unifiedDelay = true, @JsonKey(name: 'tcp-concurrent') this.tcpConcurrent = true, @JsonKey(fromJson: Tun.safeFormJson) this.tun = defaultTun, @JsonKey(fromJson: Dns.safeDnsFromJson) this.dns = defaultDns, @JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson) this.geoXUrl = defaultGeoXUrl, @JsonKey(name: 'geodata-loader') this.geodataLoader = GeodataLoader.memconservative, @JsonKey(name: 'global-ua') this.globalUa, @JsonKey(name: 'external-controller') this.externalController = ExternalControllerStatus.close, final Map<String, String> hosts = const {}}): _hosts = hosts;
|
const _PatchClashConfig({@JsonKey(name: 'mixed-port') this.mixedPort = defaultMixedPort, @JsonKey(name: 'socks-port') this.socksPort = 0, @JsonKey(name: 'port') this.port = 0, @JsonKey(name: 'redir-port') this.redirPort = 0, @JsonKey(name: 'tproxy-port') this.tproxyPort = 0, this.mode = Mode.rule, @JsonKey(name: 'allow-lan') this.allowLan = false, @JsonKey(name: 'log-level') this.logLevel = LogLevel.error, this.ipv6 = false, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) this.findProcessMode = FindProcessMode.always, @JsonKey(name: 'keep-alive-interval') this.keepAliveInterval = defaultKeepAliveInterval, @JsonKey(name: 'unified-delay') this.unifiedDelay = true, @JsonKey(name: 'tcp-concurrent') this.tcpConcurrent = true, @JsonKey(fromJson: Tun.safeFormJson) this.tun = defaultTun, @JsonKey(fromJson: Dns.safeDnsFromJson) this.dns = defaultDns, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) final Map<GeoResource, String> geoXUrl = defaultGeoXUrl, @JsonKey(name: 'geodata-loader') this.geodataLoader = GeodataLoader.memconservative, @JsonKey(name: 'global-ua') this.globalUa, @JsonKey(name: 'external-controller') this.externalController = ExternalControllerStatus.close, final Map<String, String> hosts = const {}, @JsonKey(name: 'geo-auto-update') this.geoAutoUpdate = false, @JsonKey(name: 'geo-update-interval') this.geoUpdateInterval = 24}): _geoXUrl = geoXUrl,_hosts = hosts;
|
||||||
factory _PatchClashConfig.fromJson(Map<String, dynamic> json) => _$PatchClashConfigFromJson(json);
|
factory _PatchClashConfig.fromJson(Map<String, dynamic> json) => _$PatchClashConfigFromJson(json);
|
||||||
|
|
||||||
@override@JsonKey(name: 'mixed-port') final int mixedPort;
|
@override@JsonKey(name: 'mixed-port') final int mixedPort;
|
||||||
@@ -4143,7 +3864,13 @@ class _PatchClashConfig implements PatchClashConfig {
|
|||||||
@override@JsonKey(name: 'tcp-concurrent') final bool tcpConcurrent;
|
@override@JsonKey(name: 'tcp-concurrent') final bool tcpConcurrent;
|
||||||
@override@JsonKey(fromJson: Tun.safeFormJson) final Tun tun;
|
@override@JsonKey(fromJson: Tun.safeFormJson) final Tun tun;
|
||||||
@override@JsonKey(fromJson: Dns.safeDnsFromJson) final Dns dns;
|
@override@JsonKey(fromJson: Dns.safeDnsFromJson) final Dns dns;
|
||||||
@override@JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson) final GeoXUrl geoXUrl;
|
final Map<GeoResource, String> _geoXUrl;
|
||||||
|
@override@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map<GeoResource, String> get geoXUrl {
|
||||||
|
if (_geoXUrl is EqualUnmodifiableMapView) return _geoXUrl;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_geoXUrl);
|
||||||
|
}
|
||||||
|
|
||||||
@override@JsonKey(name: 'geodata-loader') final GeodataLoader geodataLoader;
|
@override@JsonKey(name: 'geodata-loader') final GeodataLoader geodataLoader;
|
||||||
@override@JsonKey(name: 'global-ua') final String? globalUa;
|
@override@JsonKey(name: 'global-ua') final String? globalUa;
|
||||||
@override@JsonKey(name: 'external-controller') final ExternalControllerStatus externalController;
|
@override@JsonKey(name: 'external-controller') final ExternalControllerStatus externalController;
|
||||||
@@ -4154,6 +3881,8 @@ class _PatchClashConfig implements PatchClashConfig {
|
|||||||
return EqualUnmodifiableMapView(_hosts);
|
return EqualUnmodifiableMapView(_hosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override@JsonKey(name: 'geo-auto-update') final bool geoAutoUpdate;
|
||||||
|
@override@JsonKey(name: 'geo-update-interval') final int geoUpdateInterval;
|
||||||
|
|
||||||
/// Create a copy of PatchClashConfig
|
/// Create a copy of PatchClashConfig
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -4168,16 +3897,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PatchClashConfig&&(identical(other.mixedPort, mixedPort) || other.mixedPort == mixedPort)&&(identical(other.socksPort, socksPort) || other.socksPort == socksPort)&&(identical(other.port, port) || other.port == port)&&(identical(other.redirPort, redirPort) || other.redirPort == redirPort)&&(identical(other.tproxyPort, tproxyPort) || other.tproxyPort == tproxyPort)&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.allowLan, allowLan) || other.allowLan == allowLan)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.keepAliveInterval, keepAliveInterval) || other.keepAliveInterval == keepAliveInterval)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.dns, dns) || other.dns == dns)&&(identical(other.geoXUrl, geoXUrl) || other.geoXUrl == geoXUrl)&&(identical(other.geodataLoader, geodataLoader) || other.geodataLoader == geodataLoader)&&(identical(other.globalUa, globalUa) || other.globalUa == globalUa)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&const DeepCollectionEquality().equals(other._hosts, _hosts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PatchClashConfig&&(identical(other.mixedPort, mixedPort) || other.mixedPort == mixedPort)&&(identical(other.socksPort, socksPort) || other.socksPort == socksPort)&&(identical(other.port, port) || other.port == port)&&(identical(other.redirPort, redirPort) || other.redirPort == redirPort)&&(identical(other.tproxyPort, tproxyPort) || other.tproxyPort == tproxyPort)&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.allowLan, allowLan) || other.allowLan == allowLan)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.keepAliveInterval, keepAliveInterval) || other.keepAliveInterval == keepAliveInterval)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.dns, dns) || other.dns == dns)&&const DeepCollectionEquality().equals(other._geoXUrl, _geoXUrl)&&(identical(other.geodataLoader, geodataLoader) || other.geodataLoader == geodataLoader)&&(identical(other.globalUa, globalUa) || other.globalUa == globalUa)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&const DeepCollectionEquality().equals(other._hosts, _hosts)&&(identical(other.geoAutoUpdate, geoAutoUpdate) || other.geoAutoUpdate == geoAutoUpdate)&&(identical(other.geoUpdateInterval, geoUpdateInterval) || other.geoUpdateInterval == geoUpdateInterval));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,mixedPort,socksPort,port,redirPort,tproxyPort,mode,allowLan,logLevel,ipv6,findProcessMode,keepAliveInterval,unifiedDelay,tcpConcurrent,tun,dns,geoXUrl,geodataLoader,globalUa,externalController,const DeepCollectionEquality().hash(_hosts)]);
|
int get hashCode => Object.hashAll([runtimeType,mixedPort,socksPort,port,redirPort,tproxyPort,mode,allowLan,logLevel,ipv6,findProcessMode,keepAliveInterval,unifiedDelay,tcpConcurrent,tun,dns,const DeepCollectionEquality().hash(_geoXUrl),geodataLoader,globalUa,externalController,const DeepCollectionEquality().hash(_hosts),geoAutoUpdate,geoUpdateInterval]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PatchClashConfig(mixedPort: $mixedPort, socksPort: $socksPort, port: $port, redirPort: $redirPort, tproxyPort: $tproxyPort, mode: $mode, allowLan: $allowLan, logLevel: $logLevel, ipv6: $ipv6, findProcessMode: $findProcessMode, keepAliveInterval: $keepAliveInterval, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, tun: $tun, dns: $dns, geoXUrl: $geoXUrl, geodataLoader: $geodataLoader, globalUa: $globalUa, externalController: $externalController, hosts: $hosts)';
|
return 'PatchClashConfig(mixedPort: $mixedPort, socksPort: $socksPort, port: $port, redirPort: $redirPort, tproxyPort: $tproxyPort, mode: $mode, allowLan: $allowLan, logLevel: $logLevel, ipv6: $ipv6, findProcessMode: $findProcessMode, keepAliveInterval: $keepAliveInterval, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, tun: $tun, dns: $dns, geoXUrl: $geoXUrl, geodataLoader: $geodataLoader, globalUa: $globalUa, externalController: $externalController, hosts: $hosts, geoAutoUpdate: $geoAutoUpdate, geoUpdateInterval: $geoUpdateInterval)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4188,11 +3917,11 @@ abstract mixin class _$PatchClashConfigCopyWith<$Res> implements $PatchClashConf
|
|||||||
factory _$PatchClashConfigCopyWith(_PatchClashConfig value, $Res Function(_PatchClashConfig) _then) = __$PatchClashConfigCopyWithImpl;
|
factory _$PatchClashConfigCopyWith(_PatchClashConfig value, $Res Function(_PatchClashConfig) _then) = __$PatchClashConfigCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'socks-port') int socksPort,@JsonKey(name: 'port') int port,@JsonKey(name: 'redir-port') int redirPort,@JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode,@JsonKey(name: 'keep-alive-interval') int keepAliveInterval,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(fromJson: Tun.safeFormJson) Tun tun,@JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,@JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson) GeoXUrl geoXUrl,@JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader,@JsonKey(name: 'global-ua') String? globalUa,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts
|
@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'socks-port') int socksPort,@JsonKey(name: 'port') int port,@JsonKey(name: 'redir-port') int redirPort,@JsonKey(name: 'tproxy-port') int tproxyPort, Mode mode,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.always) FindProcessMode findProcessMode,@JsonKey(name: 'keep-alive-interval') int keepAliveInterval,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(fromJson: Tun.safeFormJson) Tun tun,@JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map<GeoResource, String> geoXUrl,@JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader,@JsonKey(name: 'global-ua') String? globalUa,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, Map<String, String> hosts,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $TunCopyWith<$Res> get tun;@override $DnsCopyWith<$Res> get dns;@override $GeoXUrlCopyWith<$Res> get geoXUrl;
|
@override $TunCopyWith<$Res> get tun;@override $DnsCopyWith<$Res> get dns;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -4205,7 +3934,7 @@ class __$PatchClashConfigCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of PatchClashConfig
|
/// Create a copy of PatchClashConfig
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? mixedPort = null,Object? socksPort = null,Object? port = null,Object? redirPort = null,Object? tproxyPort = null,Object? mode = null,Object? allowLan = null,Object? logLevel = null,Object? ipv6 = null,Object? findProcessMode = null,Object? keepAliveInterval = null,Object? unifiedDelay = null,Object? tcpConcurrent = null,Object? tun = null,Object? dns = null,Object? geoXUrl = null,Object? geodataLoader = null,Object? globalUa = freezed,Object? externalController = null,Object? hosts = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? mixedPort = null,Object? socksPort = null,Object? port = null,Object? redirPort = null,Object? tproxyPort = null,Object? mode = null,Object? allowLan = null,Object? logLevel = null,Object? ipv6 = null,Object? findProcessMode = null,Object? keepAliveInterval = null,Object? unifiedDelay = null,Object? tcpConcurrent = null,Object? tun = null,Object? dns = null,Object? geoXUrl = null,Object? geodataLoader = null,Object? globalUa = freezed,Object? externalController = null,Object? hosts = null,Object? geoAutoUpdate = null,Object? geoUpdateInterval = null,}) {
|
||||||
return _then(_PatchClashConfig(
|
return _then(_PatchClashConfig(
|
||||||
mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable
|
mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable
|
||||||
as int,socksPort: null == socksPort ? _self.socksPort : socksPort // ignore: cast_nullable_to_non_nullable
|
as int,socksPort: null == socksPort ? _self.socksPort : socksPort // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -4222,12 +3951,14 @@ as int,unifiedDelay: null == unifiedDelay ? _self.unifiedDelay : unifiedDelay //
|
|||||||
as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurrent // ignore: cast_nullable_to_non_nullable
|
as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurrent // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable
|
as bool,tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable
|
||||||
as Tun,dns: null == dns ? _self.dns : dns // ignore: cast_nullable_to_non_nullable
|
as Tun,dns: null == dns ? _self.dns : dns // ignore: cast_nullable_to_non_nullable
|
||||||
as Dns,geoXUrl: null == geoXUrl ? _self.geoXUrl : geoXUrl // ignore: cast_nullable_to_non_nullable
|
as Dns,geoXUrl: null == geoXUrl ? _self._geoXUrl : geoXUrl // ignore: cast_nullable_to_non_nullable
|
||||||
as GeoXUrl,geodataLoader: null == geodataLoader ? _self.geodataLoader : geodataLoader // ignore: cast_nullable_to_non_nullable
|
as Map<GeoResource, String>,geodataLoader: null == geodataLoader ? _self.geodataLoader : geodataLoader // ignore: cast_nullable_to_non_nullable
|
||||||
as GeodataLoader,globalUa: freezed == globalUa ? _self.globalUa : globalUa // ignore: cast_nullable_to_non_nullable
|
as GeodataLoader,globalUa: freezed == globalUa ? _self.globalUa : globalUa // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable
|
as String?,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable
|
||||||
as ExternalControllerStatus,hosts: null == hosts ? _self._hosts : hosts // ignore: cast_nullable_to_non_nullable
|
as ExternalControllerStatus,hosts: null == hosts ? _self._hosts : hosts // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, String>,
|
as Map<String, String>,geoAutoUpdate: null == geoAutoUpdate ? _self.geoAutoUpdate : geoAutoUpdate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,geoUpdateInterval: null == geoUpdateInterval ? _self.geoUpdateInterval : geoUpdateInterval // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4249,15 +3980,6 @@ $DnsCopyWith<$Res> get dns {
|
|||||||
return $DnsCopyWith<$Res>(_self.dns, (value) {
|
return $DnsCopyWith<$Res>(_self.dns, (value) {
|
||||||
return _then(_self.copyWith(dns: value));
|
return _then(_self.copyWith(dns: value));
|
||||||
});
|
});
|
||||||
}/// Create a copy of PatchClashConfig
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$GeoXUrlCopyWith<$Res> get geoXUrl {
|
|
||||||
|
|
||||||
return $GeoXUrlCopyWith<$Res>(_self.geoXUrl, (value) {
|
|
||||||
return _then(_self.copyWith(geoXUrl: value));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -295,28 +295,6 @@ const _$DnsModeEnumMap = {
|
|||||||
DnsMode.hosts: 'hosts',
|
DnsMode.hosts: 'hosts',
|
||||||
};
|
};
|
||||||
|
|
||||||
_GeoXUrl _$GeoXUrlFromJson(Map<String, dynamic> json) => _GeoXUrl(
|
|
||||||
mmdb:
|
|
||||||
json['mmdb'] as String? ??
|
|
||||||
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb',
|
|
||||||
asn:
|
|
||||||
json['asn'] as String? ??
|
|
||||||
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb',
|
|
||||||
geoip:
|
|
||||||
json['geoip'] as String? ??
|
|
||||||
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat',
|
|
||||||
geosite:
|
|
||||||
json['geosite'] as String? ??
|
|
||||||
'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat',
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$GeoXUrlToJson(_GeoXUrl instance) => <String, dynamic>{
|
|
||||||
'mmdb': instance.mmdb,
|
|
||||||
'asn': instance.asn,
|
|
||||||
'geoip': instance.geoip,
|
|
||||||
'geosite': instance.geosite,
|
|
||||||
};
|
|
||||||
|
|
||||||
_Rule _$RuleFromJson(Map<String, dynamic> json) => _Rule(
|
_Rule _$RuleFromJson(Map<String, dynamic> json) => _Rule(
|
||||||
id: (json['id'] as num?)?.toInt() ?? -1,
|
id: (json['id'] as num?)?.toInt() ?? -1,
|
||||||
ruleAction:
|
ruleAction:
|
||||||
@@ -451,7 +429,7 @@ _PatchClashConfig _$PatchClashConfigFromJson(Map<String, dynamic> json) =>
|
|||||||
: Dns.safeDnsFromJson(json['dns'] as Map<String, Object?>),
|
: Dns.safeDnsFromJson(json['dns'] as Map<String, Object?>),
|
||||||
geoXUrl: json['geox-url'] == null
|
geoXUrl: json['geox-url'] == null
|
||||||
? defaultGeoXUrl
|
? defaultGeoXUrl
|
||||||
: GeoXUrl.safeFormJson(json['geox-url'] as Map<String, Object?>?),
|
: _geoXUrlFromJson(json['geox-url'] as Map<String, Object?>?),
|
||||||
geodataLoader:
|
geodataLoader:
|
||||||
$enumDecodeNullable(_$GeodataLoaderEnumMap, json['geodata-loader']) ??
|
$enumDecodeNullable(_$GeodataLoaderEnumMap, json['geodata-loader']) ??
|
||||||
GeodataLoader.memconservative,
|
GeodataLoader.memconservative,
|
||||||
@@ -467,6 +445,8 @@ _PatchClashConfig _$PatchClashConfigFromJson(Map<String, dynamic> json) =>
|
|||||||
(k, e) => MapEntry(k, e as String),
|
(k, e) => MapEntry(k, e as String),
|
||||||
) ??
|
) ??
|
||||||
const {},
|
const {},
|
||||||
|
geoAutoUpdate: json['geo-auto-update'] as bool? ?? false,
|
||||||
|
geoUpdateInterval: (json['geo-update-interval'] as num?)?.toInt() ?? 24,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$PatchClashConfigToJson(_PatchClashConfig instance) =>
|
Map<String, dynamic> _$PatchClashConfigToJson(_PatchClashConfig instance) =>
|
||||||
@@ -486,12 +466,14 @@ Map<String, dynamic> _$PatchClashConfigToJson(_PatchClashConfig instance) =>
|
|||||||
'tcp-concurrent': instance.tcpConcurrent,
|
'tcp-concurrent': instance.tcpConcurrent,
|
||||||
'tun': instance.tun,
|
'tun': instance.tun,
|
||||||
'dns': instance.dns,
|
'dns': instance.dns,
|
||||||
'geox-url': instance.geoXUrl,
|
'geox-url': _geoXUrlToJson(instance.geoXUrl),
|
||||||
'geodata-loader': _$GeodataLoaderEnumMap[instance.geodataLoader]!,
|
'geodata-loader': _$GeodataLoaderEnumMap[instance.geodataLoader]!,
|
||||||
'global-ua': instance.globalUa,
|
'global-ua': instance.globalUa,
|
||||||
'external-controller':
|
'external-controller':
|
||||||
_$ExternalControllerStatusEnumMap[instance.externalController]!,
|
_$ExternalControllerStatusEnumMap[instance.externalController]!,
|
||||||
'hosts': instance.hosts,
|
'hosts': instance.hosts,
|
||||||
|
'geo-auto-update': instance.geoAutoUpdate,
|
||||||
|
'geo-update-interval': instance.geoUpdateInterval,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$ModeEnumMap = {
|
const _$ModeEnumMap = {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$AppSettingProps {
|
mixin _$AppSettingProps {
|
||||||
|
|
||||||
String? get locale;@JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> get dashboardWidgets; bool get onlyStatisticsProxy; bool get autoLaunch; bool get silentLaunch; bool get autoRun; bool get openLogs; bool get closeConnections; String get testUrl; bool get isAnimateToPage; bool get autoCheckUpdate; bool get showLabel; bool get disclaimerAccepted; bool get crashlyticsTip; bool get crashlytics; bool get minimizeOnExit; bool get hidden; bool get developerMode; RestoreStrategy get restoreStrategy; bool get showTrayTitle;
|
String? get locale;@JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> get dashboardWidgets; bool get onlyStatisticsProxy; bool get autoLaunch; bool get silentLaunch; bool get autoRun; bool get openLogs; bool get closeConnections; String get testUrl; bool get isAnimateToPage; bool get autoCheckUpdate; bool get showLabel; bool get disclaimerAccepted; bool get crashlyticsTip; bool get crashlytics; bool get minimizeOnExit; bool get hidden; bool get developerMode; RestoreStrategy get restoreStrategy; bool get showTrayTitle; String get customUserAgent;
|
||||||
/// Create a copy of AppSettingProps
|
/// Create a copy of AppSettingProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,16 +28,16 @@ $AppSettingPropsCopyWith<AppSettingProps> get copyWith => _$AppSettingPropsCopyW
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettingProps&&(identical(other.locale, locale) || other.locale == locale)&&const DeepCollectionEquality().equals(other.dashboardWidgets, dashboardWidgets)&&(identical(other.onlyStatisticsProxy, onlyStatisticsProxy) || other.onlyStatisticsProxy == onlyStatisticsProxy)&&(identical(other.autoLaunch, autoLaunch) || other.autoLaunch == autoLaunch)&&(identical(other.silentLaunch, silentLaunch) || other.silentLaunch == silentLaunch)&&(identical(other.autoRun, autoRun) || other.autoRun == autoRun)&&(identical(other.openLogs, openLogs) || other.openLogs == openLogs)&&(identical(other.closeConnections, closeConnections) || other.closeConnections == closeConnections)&&(identical(other.testUrl, testUrl) || other.testUrl == testUrl)&&(identical(other.isAnimateToPage, isAnimateToPage) || other.isAnimateToPage == isAnimateToPage)&&(identical(other.autoCheckUpdate, autoCheckUpdate) || other.autoCheckUpdate == autoCheckUpdate)&&(identical(other.showLabel, showLabel) || other.showLabel == showLabel)&&(identical(other.disclaimerAccepted, disclaimerAccepted) || other.disclaimerAccepted == disclaimerAccepted)&&(identical(other.crashlyticsTip, crashlyticsTip) || other.crashlyticsTip == crashlyticsTip)&&(identical(other.crashlytics, crashlytics) || other.crashlytics == crashlytics)&&(identical(other.minimizeOnExit, minimizeOnExit) || other.minimizeOnExit == minimizeOnExit)&&(identical(other.hidden, hidden) || other.hidden == hidden)&&(identical(other.developerMode, developerMode) || other.developerMode == developerMode)&&(identical(other.restoreStrategy, restoreStrategy) || other.restoreStrategy == restoreStrategy)&&(identical(other.showTrayTitle, showTrayTitle) || other.showTrayTitle == showTrayTitle));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettingProps&&(identical(other.locale, locale) || other.locale == locale)&&const DeepCollectionEquality().equals(other.dashboardWidgets, dashboardWidgets)&&(identical(other.onlyStatisticsProxy, onlyStatisticsProxy) || other.onlyStatisticsProxy == onlyStatisticsProxy)&&(identical(other.autoLaunch, autoLaunch) || other.autoLaunch == autoLaunch)&&(identical(other.silentLaunch, silentLaunch) || other.silentLaunch == silentLaunch)&&(identical(other.autoRun, autoRun) || other.autoRun == autoRun)&&(identical(other.openLogs, openLogs) || other.openLogs == openLogs)&&(identical(other.closeConnections, closeConnections) || other.closeConnections == closeConnections)&&(identical(other.testUrl, testUrl) || other.testUrl == testUrl)&&(identical(other.isAnimateToPage, isAnimateToPage) || other.isAnimateToPage == isAnimateToPage)&&(identical(other.autoCheckUpdate, autoCheckUpdate) || other.autoCheckUpdate == autoCheckUpdate)&&(identical(other.showLabel, showLabel) || other.showLabel == showLabel)&&(identical(other.disclaimerAccepted, disclaimerAccepted) || other.disclaimerAccepted == disclaimerAccepted)&&(identical(other.crashlyticsTip, crashlyticsTip) || other.crashlyticsTip == crashlyticsTip)&&(identical(other.crashlytics, crashlytics) || other.crashlytics == crashlytics)&&(identical(other.minimizeOnExit, minimizeOnExit) || other.minimizeOnExit == minimizeOnExit)&&(identical(other.hidden, hidden) || other.hidden == hidden)&&(identical(other.developerMode, developerMode) || other.developerMode == developerMode)&&(identical(other.restoreStrategy, restoreStrategy) || other.restoreStrategy == restoreStrategy)&&(identical(other.showTrayTitle, showTrayTitle) || other.showTrayTitle == showTrayTitle)&&(identical(other.customUserAgent, customUserAgent) || other.customUserAgent == customUserAgent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,locale,const DeepCollectionEquality().hash(dashboardWidgets),onlyStatisticsProxy,autoLaunch,silentLaunch,autoRun,openLogs,closeConnections,testUrl,isAnimateToPage,autoCheckUpdate,showLabel,disclaimerAccepted,crashlyticsTip,crashlytics,minimizeOnExit,hidden,developerMode,restoreStrategy,showTrayTitle]);
|
int get hashCode => Object.hashAll([runtimeType,locale,const DeepCollectionEquality().hash(dashboardWidgets),onlyStatisticsProxy,autoLaunch,silentLaunch,autoRun,openLogs,closeConnections,testUrl,isAnimateToPage,autoCheckUpdate,showLabel,disclaimerAccepted,crashlyticsTip,crashlytics,minimizeOnExit,hidden,developerMode,restoreStrategy,showTrayTitle,customUserAgent]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppSettingProps(locale: $locale, dashboardWidgets: $dashboardWidgets, onlyStatisticsProxy: $onlyStatisticsProxy, autoLaunch: $autoLaunch, silentLaunch: $silentLaunch, autoRun: $autoRun, openLogs: $openLogs, closeConnections: $closeConnections, testUrl: $testUrl, isAnimateToPage: $isAnimateToPage, autoCheckUpdate: $autoCheckUpdate, showLabel: $showLabel, disclaimerAccepted: $disclaimerAccepted, crashlyticsTip: $crashlyticsTip, crashlytics: $crashlytics, minimizeOnExit: $minimizeOnExit, hidden: $hidden, developerMode: $developerMode, restoreStrategy: $restoreStrategy, showTrayTitle: $showTrayTitle)';
|
return 'AppSettingProps(locale: $locale, dashboardWidgets: $dashboardWidgets, onlyStatisticsProxy: $onlyStatisticsProxy, autoLaunch: $autoLaunch, silentLaunch: $silentLaunch, autoRun: $autoRun, openLogs: $openLogs, closeConnections: $closeConnections, testUrl: $testUrl, isAnimateToPage: $isAnimateToPage, autoCheckUpdate: $autoCheckUpdate, showLabel: $showLabel, disclaimerAccepted: $disclaimerAccepted, crashlyticsTip: $crashlyticsTip, crashlytics: $crashlytics, minimizeOnExit: $minimizeOnExit, hidden: $hidden, developerMode: $developerMode, restoreStrategy: $restoreStrategy, showTrayTitle: $showTrayTitle, customUserAgent: $customUserAgent)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ abstract mixin class $AppSettingPropsCopyWith<$Res> {
|
|||||||
factory $AppSettingPropsCopyWith(AppSettingProps value, $Res Function(AppSettingProps) _then) = _$AppSettingPropsCopyWithImpl;
|
factory $AppSettingPropsCopyWith(AppSettingProps value, $Res Function(AppSettingProps) _then) = _$AppSettingPropsCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String? locale,@JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle
|
String? locale,@JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle, String customUserAgent
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ class _$AppSettingPropsCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of AppSettingProps
|
/// Create a copy of AppSettingProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? locale = freezed,Object? dashboardWidgets = null,Object? onlyStatisticsProxy = null,Object? autoLaunch = null,Object? silentLaunch = null,Object? autoRun = null,Object? openLogs = null,Object? closeConnections = null,Object? testUrl = null,Object? isAnimateToPage = null,Object? autoCheckUpdate = null,Object? showLabel = null,Object? disclaimerAccepted = null,Object? crashlyticsTip = null,Object? crashlytics = null,Object? minimizeOnExit = null,Object? hidden = null,Object? developerMode = null,Object? restoreStrategy = null,Object? showTrayTitle = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? locale = freezed,Object? dashboardWidgets = null,Object? onlyStatisticsProxy = null,Object? autoLaunch = null,Object? silentLaunch = null,Object? autoRun = null,Object? openLogs = null,Object? closeConnections = null,Object? testUrl = null,Object? isAnimateToPage = null,Object? autoCheckUpdate = null,Object? showLabel = null,Object? disclaimerAccepted = null,Object? crashlyticsTip = null,Object? crashlytics = null,Object? minimizeOnExit = null,Object? hidden = null,Object? developerMode = null,Object? restoreStrategy = null,Object? showTrayTitle = null,Object? customUserAgent = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
locale: freezed == locale ? _self.locale : locale // ignore: cast_nullable_to_non_nullable
|
locale: freezed == locale ? _self.locale : locale // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,dashboardWidgets: null == dashboardWidgets ? _self.dashboardWidgets : dashboardWidgets // ignore: cast_nullable_to_non_nullable
|
as String?,dashboardWidgets: null == dashboardWidgets ? _self.dashboardWidgets : dashboardWidgets // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -87,7 +87,8 @@ as bool,hidden: null == hidden ? _self.hidden : hidden // ignore: cast_nullable_
|
|||||||
as bool,developerMode: null == developerMode ? _self.developerMode : developerMode // ignore: cast_nullable_to_non_nullable
|
as bool,developerMode: null == developerMode ? _self.developerMode : developerMode // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,restoreStrategy: null == restoreStrategy ? _self.restoreStrategy : restoreStrategy // ignore: cast_nullable_to_non_nullable
|
as bool,restoreStrategy: null == restoreStrategy ? _self.restoreStrategy : restoreStrategy // ignore: cast_nullable_to_non_nullable
|
||||||
as RestoreStrategy,showTrayTitle: null == showTrayTitle ? _self.showTrayTitle : showTrayTitle // ignore: cast_nullable_to_non_nullable
|
as RestoreStrategy,showTrayTitle: null == showTrayTitle ? _self.showTrayTitle : showTrayTitle // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,customUserAgent: null == customUserAgent ? _self.customUserAgent : customUserAgent // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,10 +173,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? locale, @JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? locale, @JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle, String customUserAgent)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _AppSettingProps() when $default != null:
|
case _AppSettingProps() when $default != null:
|
||||||
return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_that.autoLaunch,_that.silentLaunch,_that.autoRun,_that.openLogs,_that.closeConnections,_that.testUrl,_that.isAnimateToPage,_that.autoCheckUpdate,_that.showLabel,_that.disclaimerAccepted,_that.crashlyticsTip,_that.crashlytics,_that.minimizeOnExit,_that.hidden,_that.developerMode,_that.restoreStrategy,_that.showTrayTitle);case _:
|
return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_that.autoLaunch,_that.silentLaunch,_that.autoRun,_that.openLogs,_that.closeConnections,_that.testUrl,_that.isAnimateToPage,_that.autoCheckUpdate,_that.showLabel,_that.disclaimerAccepted,_that.crashlyticsTip,_that.crashlytics,_that.minimizeOnExit,_that.hidden,_that.developerMode,_that.restoreStrategy,_that.showTrayTitle,_that.customUserAgent);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -193,10 +194,10 @@ return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_t
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? locale, @JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? locale, @JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle, String customUserAgent) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _AppSettingProps():
|
case _AppSettingProps():
|
||||||
return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_that.autoLaunch,_that.silentLaunch,_that.autoRun,_that.openLogs,_that.closeConnections,_that.testUrl,_that.isAnimateToPage,_that.autoCheckUpdate,_that.showLabel,_that.disclaimerAccepted,_that.crashlyticsTip,_that.crashlytics,_that.minimizeOnExit,_that.hidden,_that.developerMode,_that.restoreStrategy,_that.showTrayTitle);case _:
|
return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_that.autoLaunch,_that.silentLaunch,_that.autoRun,_that.openLogs,_that.closeConnections,_that.testUrl,_that.isAnimateToPage,_that.autoCheckUpdate,_that.showLabel,_that.disclaimerAccepted,_that.crashlyticsTip,_that.crashlytics,_that.minimizeOnExit,_that.hidden,_that.developerMode,_that.restoreStrategy,_that.showTrayTitle,_that.customUserAgent);case _:
|
||||||
throw StateError('Unexpected subclass');
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -213,10 +214,10 @@ return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_t
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? locale, @JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? locale, @JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle, String customUserAgent)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _AppSettingProps() when $default != null:
|
case _AppSettingProps() when $default != null:
|
||||||
return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_that.autoLaunch,_that.silentLaunch,_that.autoRun,_that.openLogs,_that.closeConnections,_that.testUrl,_that.isAnimateToPage,_that.autoCheckUpdate,_that.showLabel,_that.disclaimerAccepted,_that.crashlyticsTip,_that.crashlytics,_that.minimizeOnExit,_that.hidden,_that.developerMode,_that.restoreStrategy,_that.showTrayTitle);case _:
|
return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_that.autoLaunch,_that.silentLaunch,_that.autoRun,_that.openLogs,_that.closeConnections,_that.testUrl,_that.isAnimateToPage,_that.autoCheckUpdate,_that.showLabel,_that.disclaimerAccepted,_that.crashlyticsTip,_that.crashlytics,_that.minimizeOnExit,_that.hidden,_that.developerMode,_that.restoreStrategy,_that.showTrayTitle,_that.customUserAgent);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -228,7 +229,7 @@ return $default(_that.locale,_that.dashboardWidgets,_that.onlyStatisticsProxy,_t
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _AppSettingProps implements AppSettingProps {
|
class _AppSettingProps implements AppSettingProps {
|
||||||
const _AppSettingProps({this.locale, @JsonKey(fromJson: dashboardWidgetsSafeFormJson) final List<DashboardWidget> dashboardWidgets = defaultDashboardWidgets, this.onlyStatisticsProxy = false, this.autoLaunch = false, this.silentLaunch = false, this.autoRun = false, this.openLogs = false, this.closeConnections = true, this.testUrl = defaultTestUrl, this.isAnimateToPage = true, this.autoCheckUpdate = true, this.showLabel = false, this.disclaimerAccepted = false, this.crashlyticsTip = false, this.crashlytics = false, this.minimizeOnExit = true, this.hidden = false, this.developerMode = false, this.restoreStrategy = RestoreStrategy.compatible, this.showTrayTitle = true}): _dashboardWidgets = dashboardWidgets;
|
const _AppSettingProps({this.locale, @JsonKey(fromJson: dashboardWidgetsSafeFormJson) final List<DashboardWidget> dashboardWidgets = defaultDashboardWidgets, this.onlyStatisticsProxy = false, this.autoLaunch = false, this.silentLaunch = false, this.autoRun = false, this.openLogs = false, this.closeConnections = true, this.testUrl = defaultTestUrl, this.isAnimateToPage = true, this.autoCheckUpdate = true, this.showLabel = false, this.disclaimerAccepted = false, this.crashlyticsTip = false, this.crashlytics = false, this.minimizeOnExit = true, this.hidden = false, this.developerMode = false, this.restoreStrategy = RestoreStrategy.compatible, this.showTrayTitle = true, this.customUserAgent = ''}): _dashboardWidgets = dashboardWidgets;
|
||||||
factory _AppSettingProps.fromJson(Map<String, dynamic> json) => _$AppSettingPropsFromJson(json);
|
factory _AppSettingProps.fromJson(Map<String, dynamic> json) => _$AppSettingPropsFromJson(json);
|
||||||
|
|
||||||
@override final String? locale;
|
@override final String? locale;
|
||||||
@@ -257,6 +258,7 @@ class _AppSettingProps implements AppSettingProps {
|
|||||||
@override@JsonKey() final bool developerMode;
|
@override@JsonKey() final bool developerMode;
|
||||||
@override@JsonKey() final RestoreStrategy restoreStrategy;
|
@override@JsonKey() final RestoreStrategy restoreStrategy;
|
||||||
@override@JsonKey() final bool showTrayTitle;
|
@override@JsonKey() final bool showTrayTitle;
|
||||||
|
@override@JsonKey() final String customUserAgent;
|
||||||
|
|
||||||
/// Create a copy of AppSettingProps
|
/// Create a copy of AppSettingProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -271,16 +273,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettingProps&&(identical(other.locale, locale) || other.locale == locale)&&const DeepCollectionEquality().equals(other._dashboardWidgets, _dashboardWidgets)&&(identical(other.onlyStatisticsProxy, onlyStatisticsProxy) || other.onlyStatisticsProxy == onlyStatisticsProxy)&&(identical(other.autoLaunch, autoLaunch) || other.autoLaunch == autoLaunch)&&(identical(other.silentLaunch, silentLaunch) || other.silentLaunch == silentLaunch)&&(identical(other.autoRun, autoRun) || other.autoRun == autoRun)&&(identical(other.openLogs, openLogs) || other.openLogs == openLogs)&&(identical(other.closeConnections, closeConnections) || other.closeConnections == closeConnections)&&(identical(other.testUrl, testUrl) || other.testUrl == testUrl)&&(identical(other.isAnimateToPage, isAnimateToPage) || other.isAnimateToPage == isAnimateToPage)&&(identical(other.autoCheckUpdate, autoCheckUpdate) || other.autoCheckUpdate == autoCheckUpdate)&&(identical(other.showLabel, showLabel) || other.showLabel == showLabel)&&(identical(other.disclaimerAccepted, disclaimerAccepted) || other.disclaimerAccepted == disclaimerAccepted)&&(identical(other.crashlyticsTip, crashlyticsTip) || other.crashlyticsTip == crashlyticsTip)&&(identical(other.crashlytics, crashlytics) || other.crashlytics == crashlytics)&&(identical(other.minimizeOnExit, minimizeOnExit) || other.minimizeOnExit == minimizeOnExit)&&(identical(other.hidden, hidden) || other.hidden == hidden)&&(identical(other.developerMode, developerMode) || other.developerMode == developerMode)&&(identical(other.restoreStrategy, restoreStrategy) || other.restoreStrategy == restoreStrategy)&&(identical(other.showTrayTitle, showTrayTitle) || other.showTrayTitle == showTrayTitle));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettingProps&&(identical(other.locale, locale) || other.locale == locale)&&const DeepCollectionEquality().equals(other._dashboardWidgets, _dashboardWidgets)&&(identical(other.onlyStatisticsProxy, onlyStatisticsProxy) || other.onlyStatisticsProxy == onlyStatisticsProxy)&&(identical(other.autoLaunch, autoLaunch) || other.autoLaunch == autoLaunch)&&(identical(other.silentLaunch, silentLaunch) || other.silentLaunch == silentLaunch)&&(identical(other.autoRun, autoRun) || other.autoRun == autoRun)&&(identical(other.openLogs, openLogs) || other.openLogs == openLogs)&&(identical(other.closeConnections, closeConnections) || other.closeConnections == closeConnections)&&(identical(other.testUrl, testUrl) || other.testUrl == testUrl)&&(identical(other.isAnimateToPage, isAnimateToPage) || other.isAnimateToPage == isAnimateToPage)&&(identical(other.autoCheckUpdate, autoCheckUpdate) || other.autoCheckUpdate == autoCheckUpdate)&&(identical(other.showLabel, showLabel) || other.showLabel == showLabel)&&(identical(other.disclaimerAccepted, disclaimerAccepted) || other.disclaimerAccepted == disclaimerAccepted)&&(identical(other.crashlyticsTip, crashlyticsTip) || other.crashlyticsTip == crashlyticsTip)&&(identical(other.crashlytics, crashlytics) || other.crashlytics == crashlytics)&&(identical(other.minimizeOnExit, minimizeOnExit) || other.minimizeOnExit == minimizeOnExit)&&(identical(other.hidden, hidden) || other.hidden == hidden)&&(identical(other.developerMode, developerMode) || other.developerMode == developerMode)&&(identical(other.restoreStrategy, restoreStrategy) || other.restoreStrategy == restoreStrategy)&&(identical(other.showTrayTitle, showTrayTitle) || other.showTrayTitle == showTrayTitle)&&(identical(other.customUserAgent, customUserAgent) || other.customUserAgent == customUserAgent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,locale,const DeepCollectionEquality().hash(_dashboardWidgets),onlyStatisticsProxy,autoLaunch,silentLaunch,autoRun,openLogs,closeConnections,testUrl,isAnimateToPage,autoCheckUpdate,showLabel,disclaimerAccepted,crashlyticsTip,crashlytics,minimizeOnExit,hidden,developerMode,restoreStrategy,showTrayTitle]);
|
int get hashCode => Object.hashAll([runtimeType,locale,const DeepCollectionEquality().hash(_dashboardWidgets),onlyStatisticsProxy,autoLaunch,silentLaunch,autoRun,openLogs,closeConnections,testUrl,isAnimateToPage,autoCheckUpdate,showLabel,disclaimerAccepted,crashlyticsTip,crashlytics,minimizeOnExit,hidden,developerMode,restoreStrategy,showTrayTitle,customUserAgent]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppSettingProps(locale: $locale, dashboardWidgets: $dashboardWidgets, onlyStatisticsProxy: $onlyStatisticsProxy, autoLaunch: $autoLaunch, silentLaunch: $silentLaunch, autoRun: $autoRun, openLogs: $openLogs, closeConnections: $closeConnections, testUrl: $testUrl, isAnimateToPage: $isAnimateToPage, autoCheckUpdate: $autoCheckUpdate, showLabel: $showLabel, disclaimerAccepted: $disclaimerAccepted, crashlyticsTip: $crashlyticsTip, crashlytics: $crashlytics, minimizeOnExit: $minimizeOnExit, hidden: $hidden, developerMode: $developerMode, restoreStrategy: $restoreStrategy, showTrayTitle: $showTrayTitle)';
|
return 'AppSettingProps(locale: $locale, dashboardWidgets: $dashboardWidgets, onlyStatisticsProxy: $onlyStatisticsProxy, autoLaunch: $autoLaunch, silentLaunch: $silentLaunch, autoRun: $autoRun, openLogs: $openLogs, closeConnections: $closeConnections, testUrl: $testUrl, isAnimateToPage: $isAnimateToPage, autoCheckUpdate: $autoCheckUpdate, showLabel: $showLabel, disclaimerAccepted: $disclaimerAccepted, crashlyticsTip: $crashlyticsTip, crashlytics: $crashlytics, minimizeOnExit: $minimizeOnExit, hidden: $hidden, developerMode: $developerMode, restoreStrategy: $restoreStrategy, showTrayTitle: $showTrayTitle, customUserAgent: $customUserAgent)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -291,7 +293,7 @@ abstract mixin class _$AppSettingPropsCopyWith<$Res> implements $AppSettingProps
|
|||||||
factory _$AppSettingPropsCopyWith(_AppSettingProps value, $Res Function(_AppSettingProps) _then) = __$AppSettingPropsCopyWithImpl;
|
factory _$AppSettingPropsCopyWith(_AppSettingProps value, $Res Function(_AppSettingProps) _then) = __$AppSettingPropsCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String? locale,@JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle
|
String? locale,@JsonKey(fromJson: dashboardWidgetsSafeFormJson) List<DashboardWidget> dashboardWidgets, bool onlyStatisticsProxy, bool autoLaunch, bool silentLaunch, bool autoRun, bool openLogs, bool closeConnections, String testUrl, bool isAnimateToPage, bool autoCheckUpdate, bool showLabel, bool disclaimerAccepted, bool crashlyticsTip, bool crashlytics, bool minimizeOnExit, bool hidden, bool developerMode, RestoreStrategy restoreStrategy, bool showTrayTitle, String customUserAgent
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -308,7 +310,7 @@ class __$AppSettingPropsCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of AppSettingProps
|
/// Create a copy of AppSettingProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? locale = freezed,Object? dashboardWidgets = null,Object? onlyStatisticsProxy = null,Object? autoLaunch = null,Object? silentLaunch = null,Object? autoRun = null,Object? openLogs = null,Object? closeConnections = null,Object? testUrl = null,Object? isAnimateToPage = null,Object? autoCheckUpdate = null,Object? showLabel = null,Object? disclaimerAccepted = null,Object? crashlyticsTip = null,Object? crashlytics = null,Object? minimizeOnExit = null,Object? hidden = null,Object? developerMode = null,Object? restoreStrategy = null,Object? showTrayTitle = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? locale = freezed,Object? dashboardWidgets = null,Object? onlyStatisticsProxy = null,Object? autoLaunch = null,Object? silentLaunch = null,Object? autoRun = null,Object? openLogs = null,Object? closeConnections = null,Object? testUrl = null,Object? isAnimateToPage = null,Object? autoCheckUpdate = null,Object? showLabel = null,Object? disclaimerAccepted = null,Object? crashlyticsTip = null,Object? crashlytics = null,Object? minimizeOnExit = null,Object? hidden = null,Object? developerMode = null,Object? restoreStrategy = null,Object? showTrayTitle = null,Object? customUserAgent = null,}) {
|
||||||
return _then(_AppSettingProps(
|
return _then(_AppSettingProps(
|
||||||
locale: freezed == locale ? _self.locale : locale // ignore: cast_nullable_to_non_nullable
|
locale: freezed == locale ? _self.locale : locale // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,dashboardWidgets: null == dashboardWidgets ? _self._dashboardWidgets : dashboardWidgets // ignore: cast_nullable_to_non_nullable
|
as String?,dashboardWidgets: null == dashboardWidgets ? _self._dashboardWidgets : dashboardWidgets // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -330,7 +332,8 @@ as bool,hidden: null == hidden ? _self.hidden : hidden // ignore: cast_nullable_
|
|||||||
as bool,developerMode: null == developerMode ? _self.developerMode : developerMode // ignore: cast_nullable_to_non_nullable
|
as bool,developerMode: null == developerMode ? _self.developerMode : developerMode // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,restoreStrategy: null == restoreStrategy ? _self.restoreStrategy : restoreStrategy // ignore: cast_nullable_to_non_nullable
|
as bool,restoreStrategy: null == restoreStrategy ? _self.restoreStrategy : restoreStrategy // ignore: cast_nullable_to_non_nullable
|
||||||
as RestoreStrategy,showTrayTitle: null == showTrayTitle ? _self.showTrayTitle : showTrayTitle // ignore: cast_nullable_to_non_nullable
|
as RestoreStrategy,showTrayTitle: null == showTrayTitle ? _self.showTrayTitle : showTrayTitle // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,customUserAgent: null == customUserAgent ? _self.customUserAgent : customUserAgent // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ _AppSettingProps _$AppSettingPropsFromJson(Map<String, dynamic> json) =>
|
|||||||
) ??
|
) ??
|
||||||
RestoreStrategy.compatible,
|
RestoreStrategy.compatible,
|
||||||
showTrayTitle: json['showTrayTitle'] as bool? ?? true,
|
showTrayTitle: json['showTrayTitle'] as bool? ?? true,
|
||||||
|
customUserAgent: json['customUserAgent'] as String? ?? '',
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$AppSettingPropsToJson(_AppSettingProps instance) =>
|
Map<String, dynamic> _$AppSettingPropsToJson(_AppSettingProps instance) =>
|
||||||
@@ -61,6 +62,7 @@ Map<String, dynamic> _$AppSettingPropsToJson(_AppSettingProps instance) =>
|
|||||||
'developerMode': instance.developerMode,
|
'developerMode': instance.developerMode,
|
||||||
'restoreStrategy': _$RestoreStrategyEnumMap[instance.restoreStrategy]!,
|
'restoreStrategy': _$RestoreStrategyEnumMap[instance.restoreStrategy]!,
|
||||||
'showTrayTitle': instance.showTrayTitle,
|
'showTrayTitle': instance.showTrayTitle,
|
||||||
|
'customUserAgent': instance.customUserAgent,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$RestoreStrategyEnumMap = {
|
const _$RestoreStrategyEnumMap = {
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ as String,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$UpdateParams {
|
mixin _$UpdateParams {
|
||||||
|
|
||||||
Tun get tun;@JsonKey(name: 'mixed-port') int get mixedPort;@JsonKey(name: 'allow-lan') bool get allowLan;@JsonKey(name: 'find-process-mode') FindProcessMode get findProcessMode; Mode get mode;@JsonKey(name: 'log-level') LogLevel get logLevel; bool get ipv6;@JsonKey(name: 'tcp-concurrent') bool get tcpConcurrent;@JsonKey(name: 'external-controller') ExternalControllerStatus get externalController;@JsonKey(name: 'unified-delay') bool get unifiedDelay;
|
Tun get tun;@JsonKey(name: 'mixed-port') int get mixedPort;@JsonKey(name: 'allow-lan') bool get allowLan;@JsonKey(name: 'find-process-mode') FindProcessMode get findProcessMode; Mode get mode;@JsonKey(name: 'log-level') LogLevel get logLevel; bool get ipv6;@JsonKey(name: 'tcp-concurrent') bool get tcpConcurrent;@JsonKey(name: 'external-controller') ExternalControllerStatus get externalController;@JsonKey(name: 'unified-delay') bool get unifiedDelay;@JsonKey(name: 'geo-auto-update') bool get geoAutoUpdate;@JsonKey(name: 'geo-update-interval') int get geoUpdateInterval;
|
||||||
/// Create a copy of UpdateParams
|
/// Create a copy of UpdateParams
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -300,16 +300,16 @@ $UpdateParamsCopyWith<UpdateParams> get copyWith => _$UpdateParamsCopyWithImpl<U
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is UpdateParams&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.mixedPort, mixedPort) || other.mixedPort == mixedPort)&&(identical(other.allowLan, allowLan) || other.allowLan == allowLan)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is UpdateParams&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.mixedPort, mixedPort) || other.mixedPort == mixedPort)&&(identical(other.allowLan, allowLan) || other.allowLan == allowLan)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay)&&(identical(other.geoAutoUpdate, geoAutoUpdate) || other.geoAutoUpdate == geoAutoUpdate)&&(identical(other.geoUpdateInterval, geoUpdateInterval) || other.geoUpdateInterval == geoUpdateInterval));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,tun,mixedPort,allowLan,findProcessMode,mode,logLevel,ipv6,tcpConcurrent,externalController,unifiedDelay);
|
int get hashCode => Object.hash(runtimeType,tun,mixedPort,allowLan,findProcessMode,mode,logLevel,ipv6,tcpConcurrent,externalController,unifiedDelay,geoAutoUpdate,geoUpdateInterval);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'UpdateParams(tun: $tun, mixedPort: $mixedPort, allowLan: $allowLan, findProcessMode: $findProcessMode, mode: $mode, logLevel: $logLevel, ipv6: $ipv6, tcpConcurrent: $tcpConcurrent, externalController: $externalController, unifiedDelay: $unifiedDelay)';
|
return 'UpdateParams(tun: $tun, mixedPort: $mixedPort, allowLan: $allowLan, findProcessMode: $findProcessMode, mode: $mode, logLevel: $logLevel, ipv6: $ipv6, tcpConcurrent: $tcpConcurrent, externalController: $externalController, unifiedDelay: $unifiedDelay, geoAutoUpdate: $geoAutoUpdate, geoUpdateInterval: $geoUpdateInterval)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ abstract mixin class $UpdateParamsCopyWith<$Res> {
|
|||||||
factory $UpdateParamsCopyWith(UpdateParams value, $Res Function(UpdateParams) _then) = _$UpdateParamsCopyWithImpl;
|
factory $UpdateParamsCopyWith(UpdateParams value, $Res Function(UpdateParams) _then) = _$UpdateParamsCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
Tun tun,@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController,@JsonKey(name: 'unified-delay') bool unifiedDelay
|
Tun tun,@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ class _$UpdateParamsCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of UpdateParams
|
/// Create a copy of UpdateParams
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? tun = null,Object? mixedPort = null,Object? allowLan = null,Object? findProcessMode = null,Object? mode = null,Object? logLevel = null,Object? ipv6 = null,Object? tcpConcurrent = null,Object? externalController = null,Object? unifiedDelay = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? tun = null,Object? mixedPort = null,Object? allowLan = null,Object? findProcessMode = null,Object? mode = null,Object? logLevel = null,Object? ipv6 = null,Object? tcpConcurrent = null,Object? externalController = null,Object? unifiedDelay = null,Object? geoAutoUpdate = null,Object? geoUpdateInterval = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable
|
tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable
|
||||||
as Tun,mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable
|
as Tun,mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -349,7 +349,9 @@ as LogLevel,ipv6: null == ipv6 ? _self.ipv6 : ipv6 // ignore: cast_nullable_to_n
|
|||||||
as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurrent // ignore: cast_nullable_to_non_nullable
|
as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurrent // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable
|
as bool,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable
|
||||||
as ExternalControllerStatus,unifiedDelay: null == unifiedDelay ? _self.unifiedDelay : unifiedDelay // ignore: cast_nullable_to_non_nullable
|
as ExternalControllerStatus,unifiedDelay: null == unifiedDelay ? _self.unifiedDelay : unifiedDelay // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,geoAutoUpdate: null == geoAutoUpdate ? _self.geoAutoUpdate : geoAutoUpdate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,geoUpdateInterval: null == geoUpdateInterval ? _self.geoUpdateInterval : geoUpdateInterval // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of UpdateParams
|
/// Create a copy of UpdateParams
|
||||||
@@ -443,10 +445,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, @JsonKey(name: 'unified-delay') bool unifiedDelay)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _UpdateParams() when $default != null:
|
case _UpdateParams() when $default != null:
|
||||||
return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.unifiedDelay);case _:
|
return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.unifiedDelay,_that.geoAutoUpdate,_that.geoUpdateInterval);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -464,10 +466,10 @@ return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, @JsonKey(name: 'unified-delay') bool unifiedDelay) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _UpdateParams():
|
case _UpdateParams():
|
||||||
return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.unifiedDelay);case _:
|
return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.unifiedDelay,_that.geoAutoUpdate,_that.geoUpdateInterval);case _:
|
||||||
throw StateError('Unexpected subclass');
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -484,10 +486,10 @@ return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, @JsonKey(name: 'unified-delay') bool unifiedDelay)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _UpdateParams() when $default != null:
|
case _UpdateParams() when $default != null:
|
||||||
return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.unifiedDelay);case _:
|
return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.unifiedDelay,_that.geoAutoUpdate,_that.geoUpdateInterval);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -499,7 +501,7 @@ return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _UpdateParams implements UpdateParams {
|
class _UpdateParams implements UpdateParams {
|
||||||
const _UpdateParams({required this.tun, @JsonKey(name: 'mixed-port') required this.mixedPort, @JsonKey(name: 'allow-lan') required this.allowLan, @JsonKey(name: 'find-process-mode') required this.findProcessMode, required this.mode, @JsonKey(name: 'log-level') required this.logLevel, required this.ipv6, @JsonKey(name: 'tcp-concurrent') required this.tcpConcurrent, @JsonKey(name: 'external-controller') required this.externalController, @JsonKey(name: 'unified-delay') required this.unifiedDelay});
|
const _UpdateParams({required this.tun, @JsonKey(name: 'mixed-port') required this.mixedPort, @JsonKey(name: 'allow-lan') required this.allowLan, @JsonKey(name: 'find-process-mode') required this.findProcessMode, required this.mode, @JsonKey(name: 'log-level') required this.logLevel, required this.ipv6, @JsonKey(name: 'tcp-concurrent') required this.tcpConcurrent, @JsonKey(name: 'external-controller') required this.externalController, @JsonKey(name: 'unified-delay') required this.unifiedDelay, @JsonKey(name: 'geo-auto-update') this.geoAutoUpdate = false, @JsonKey(name: 'geo-update-interval') this.geoUpdateInterval = 24});
|
||||||
factory _UpdateParams.fromJson(Map<String, dynamic> json) => _$UpdateParamsFromJson(json);
|
factory _UpdateParams.fromJson(Map<String, dynamic> json) => _$UpdateParamsFromJson(json);
|
||||||
|
|
||||||
@override final Tun tun;
|
@override final Tun tun;
|
||||||
@@ -512,6 +514,8 @@ class _UpdateParams implements UpdateParams {
|
|||||||
@override@JsonKey(name: 'tcp-concurrent') final bool tcpConcurrent;
|
@override@JsonKey(name: 'tcp-concurrent') final bool tcpConcurrent;
|
||||||
@override@JsonKey(name: 'external-controller') final ExternalControllerStatus externalController;
|
@override@JsonKey(name: 'external-controller') final ExternalControllerStatus externalController;
|
||||||
@override@JsonKey(name: 'unified-delay') final bool unifiedDelay;
|
@override@JsonKey(name: 'unified-delay') final bool unifiedDelay;
|
||||||
|
@override@JsonKey(name: 'geo-auto-update') final bool geoAutoUpdate;
|
||||||
|
@override@JsonKey(name: 'geo-update-interval') final int geoUpdateInterval;
|
||||||
|
|
||||||
/// Create a copy of UpdateParams
|
/// Create a copy of UpdateParams
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -526,16 +530,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpdateParams&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.mixedPort, mixedPort) || other.mixedPort == mixedPort)&&(identical(other.allowLan, allowLan) || other.allowLan == allowLan)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpdateParams&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.mixedPort, mixedPort) || other.mixedPort == mixedPort)&&(identical(other.allowLan, allowLan) || other.allowLan == allowLan)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay)&&(identical(other.geoAutoUpdate, geoAutoUpdate) || other.geoAutoUpdate == geoAutoUpdate)&&(identical(other.geoUpdateInterval, geoUpdateInterval) || other.geoUpdateInterval == geoUpdateInterval));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,tun,mixedPort,allowLan,findProcessMode,mode,logLevel,ipv6,tcpConcurrent,externalController,unifiedDelay);
|
int get hashCode => Object.hash(runtimeType,tun,mixedPort,allowLan,findProcessMode,mode,logLevel,ipv6,tcpConcurrent,externalController,unifiedDelay,geoAutoUpdate,geoUpdateInterval);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'UpdateParams(tun: $tun, mixedPort: $mixedPort, allowLan: $allowLan, findProcessMode: $findProcessMode, mode: $mode, logLevel: $logLevel, ipv6: $ipv6, tcpConcurrent: $tcpConcurrent, externalController: $externalController, unifiedDelay: $unifiedDelay)';
|
return 'UpdateParams(tun: $tun, mixedPort: $mixedPort, allowLan: $allowLan, findProcessMode: $findProcessMode, mode: $mode, logLevel: $logLevel, ipv6: $ipv6, tcpConcurrent: $tcpConcurrent, externalController: $externalController, unifiedDelay: $unifiedDelay, geoAutoUpdate: $geoAutoUpdate, geoUpdateInterval: $geoUpdateInterval)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -546,7 +550,7 @@ abstract mixin class _$UpdateParamsCopyWith<$Res> implements $UpdateParamsCopyWi
|
|||||||
factory _$UpdateParamsCopyWith(_UpdateParams value, $Res Function(_UpdateParams) _then) = __$UpdateParamsCopyWithImpl;
|
factory _$UpdateParamsCopyWith(_UpdateParams value, $Res Function(_UpdateParams) _then) = __$UpdateParamsCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
Tun tun,@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController,@JsonKey(name: 'unified-delay') bool unifiedDelay
|
Tun tun,@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -563,7 +567,7 @@ class __$UpdateParamsCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of UpdateParams
|
/// Create a copy of UpdateParams
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? tun = null,Object? mixedPort = null,Object? allowLan = null,Object? findProcessMode = null,Object? mode = null,Object? logLevel = null,Object? ipv6 = null,Object? tcpConcurrent = null,Object? externalController = null,Object? unifiedDelay = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? tun = null,Object? mixedPort = null,Object? allowLan = null,Object? findProcessMode = null,Object? mode = null,Object? logLevel = null,Object? ipv6 = null,Object? tcpConcurrent = null,Object? externalController = null,Object? unifiedDelay = null,Object? geoAutoUpdate = null,Object? geoUpdateInterval = null,}) {
|
||||||
return _then(_UpdateParams(
|
return _then(_UpdateParams(
|
||||||
tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable
|
tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable
|
||||||
as Tun,mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable
|
as Tun,mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -575,7 +579,9 @@ as LogLevel,ipv6: null == ipv6 ? _self.ipv6 : ipv6 // ignore: cast_nullable_to_n
|
|||||||
as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurrent // ignore: cast_nullable_to_non_nullable
|
as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurrent // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable
|
as bool,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable
|
||||||
as ExternalControllerStatus,unifiedDelay: null == unifiedDelay ? _self.unifiedDelay : unifiedDelay // ignore: cast_nullable_to_non_nullable
|
as ExternalControllerStatus,unifiedDelay: null == unifiedDelay ? _self.unifiedDelay : unifiedDelay // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,geoAutoUpdate: null == geoAutoUpdate ? _self.geoAutoUpdate : geoAutoUpdate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,geoUpdateInterval: null == geoUpdateInterval ? _self.geoUpdateInterval : geoUpdateInterval // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ _UpdateParams _$UpdateParamsFromJson(Map<String, dynamic> json) =>
|
|||||||
json['external-controller'],
|
json['external-controller'],
|
||||||
),
|
),
|
||||||
unifiedDelay: json['unified-delay'] as bool,
|
unifiedDelay: json['unified-delay'] as bool,
|
||||||
|
geoAutoUpdate: json['geo-auto-update'] as bool? ?? false,
|
||||||
|
geoUpdateInterval: (json['geo-update-interval'] as num?)?.toInt() ?? 24,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$UpdateParamsToJson(_UpdateParams instance) =>
|
Map<String, dynamic> _$UpdateParamsToJson(_UpdateParams instance) =>
|
||||||
@@ -50,6 +52,8 @@ Map<String, dynamic> _$UpdateParamsToJson(_UpdateParams instance) =>
|
|||||||
'external-controller':
|
'external-controller':
|
||||||
_$ExternalControllerStatusEnumMap[instance.externalController]!,
|
_$ExternalControllerStatusEnumMap[instance.externalController]!,
|
||||||
'unified-delay': instance.unifiedDelay,
|
'unified-delay': instance.unifiedDelay,
|
||||||
|
'geo-auto-update': instance.geoAutoUpdate,
|
||||||
|
'geo-update-interval': instance.geoUpdateInterval,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$FindProcessModeEnumMap = {
|
const _$FindProcessModeEnumMap = {
|
||||||
@@ -164,6 +168,7 @@ const _$CoreEventTypeEnumMap = {
|
|||||||
CoreEventType.request: 'request',
|
CoreEventType.request: 'request',
|
||||||
CoreEventType.loaded: 'loaded',
|
CoreEventType.loaded: 'loaded',
|
||||||
CoreEventType.crash: 'crash',
|
CoreEventType.crash: 'crash',
|
||||||
|
CoreEventType.geoUpdate: 'geoUpdate',
|
||||||
};
|
};
|
||||||
|
|
||||||
_InvokeMessage _$InvokeMessageFromJson(Map<String, dynamic> json) =>
|
_InvokeMessage _$InvokeMessageFromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
|||||||
if (file == null) {
|
if (file == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final res = utf8.decode(file.bytes?.toList() ?? []);
|
final res = utf8.decode(await file.readBytes());
|
||||||
_controller.text = res;
|
_controller.text = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +150,7 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
|||||||
title: appLocalizations.import,
|
title: appLocalizations.import,
|
||||||
value: '',
|
value: '',
|
||||||
labelText: appLocalizations.url,
|
labelText: appLocalizations.url,
|
||||||
|
inputFormatters: TextInputLimits.limit(TextInputLimits.url),
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return appLocalizations.emptyTip(appLocalizations.value);
|
return appLocalizations.emptyTip(appLocalizations.value);
|
||||||
@@ -442,7 +443,11 @@ class FindPanel extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [bar, const SizedBox(height: 12), _buildFindInput(context, value)],
|
children: [
|
||||||
|
bar,
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
_buildFindInput(context, value),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return bar;
|
return bar;
|
||||||
@@ -499,6 +504,7 @@ class FindPanel extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
inputFormatters: TextInputLimits.limit(TextInputLimits.search),
|
||||||
style: context.textTheme.bodyMedium,
|
style: context.textTheme.bodyMedium,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import 'package:fl_clash/providers/providers.dart';
|
|||||||
import 'package:fl_clash/state.dart';
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:fl_clash/widgets/widgets.dart';
|
import 'package:fl_clash/widgets/widgets.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
@@ -30,9 +29,6 @@ class HomePage extends StatelessWidget {
|
|||||||
child: Consumer(
|
child: Consumer(
|
||||||
builder: (context, ref, child) {
|
builder: (context, ref, child) {
|
||||||
final state = ref.watch(navigationStateProvider);
|
final state = ref.watch(navigationStateProvider);
|
||||||
final systemUiOverlayStyle = ref.read(
|
|
||||||
systemUiOverlayStyleStateProvider,
|
|
||||||
);
|
|
||||||
final isMobile = state.viewMode == ViewMode.mobile;
|
final isMobile = state.viewMode == ViewMode.mobile;
|
||||||
final navigationItems = state.navigationItems;
|
final navigationItems = state.navigationItems;
|
||||||
final currentIndex = state.currentIndex;
|
final currentIndex = state.currentIndex;
|
||||||
@@ -54,34 +50,28 @@ class HomePage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return Column(
|
||||||
value: systemUiOverlayStyle.copyWith(
|
children: [
|
||||||
systemNavigationBarColor:
|
Flexible(
|
||||||
context.colorScheme.surfaceContainer,
|
flex: 1,
|
||||||
),
|
child: MediaQuery.removePadding(
|
||||||
child: Column(
|
removeTop: false,
|
||||||
children: [
|
removeBottom: true,
|
||||||
Flexible(
|
|
||||||
flex: 1,
|
|
||||||
child: MediaQuery.removePadding(
|
|
||||||
removeTop: false,
|
|
||||||
removeBottom: true,
|
|
||||||
removeLeft: true,
|
|
||||||
removeRight: true,
|
|
||||||
context: context,
|
|
||||||
child: child!,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
MediaQuery.removePadding(
|
|
||||||
removeTop: true,
|
|
||||||
removeBottom: false,
|
|
||||||
removeLeft: true,
|
removeLeft: true,
|
||||||
removeRight: true,
|
removeRight: true,
|
||||||
context: context,
|
context: context,
|
||||||
child: bottomNavigationBar,
|
child: child!,
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
MediaQuery.removePadding(
|
||||||
|
removeTop: true,
|
||||||
|
removeBottom: false,
|
||||||
|
removeLeft: true,
|
||||||
|
removeRight: true,
|
||||||
|
context: context,
|
||||||
|
child: bottomNavigationBar,
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return child!;
|
return child!;
|
||||||
@@ -287,7 +277,7 @@ class HomeBackScopeContainer extends ConsumerWidget {
|
|||||||
} else {
|
} else {
|
||||||
await globalState.container
|
await globalState.container
|
||||||
.read(systemActionProvider.notifier)
|
.read(systemActionProvider.notifier)
|
||||||
.handleBackOrExit();
|
.handleClose();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -61,7 +61,10 @@ class _ScanPageState extends State<ScanPage> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final double sideLength = min(400, MediaQuery.of(context).size.width * 0.67);
|
final double sideLength = min(
|
||||||
|
400,
|
||||||
|
MediaQuery.of(context).size.width * 0.67,
|
||||||
|
);
|
||||||
final scanWindow = Rect.fromCenter(
|
final scanWindow = Rect.fromCenter(
|
||||||
center: MediaQuery.sizeOf(context).center(Offset.zero),
|
center: MediaQuery.sizeOf(context).center(Offset.zero),
|
||||||
width: sideLength,
|
width: sideLength,
|
||||||
|
|||||||
@@ -53,9 +53,7 @@ class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool?> requestNotificationsPermission() async {
|
Future<bool?> requestNotificationsPermission() async {
|
||||||
return methodChannel.invokeMethod<bool>(
|
return methodChannel.invokeMethod<bool>('requestNotificationsPermission');
|
||||||
'requestNotificationsPermission',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> openFile(String path) async {
|
Future<bool> openFile(String path) async {
|
||||||
@@ -74,9 +72,7 @@ class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool?> tip(String? message) async {
|
Future<bool?> tip(String? message) async {
|
||||||
return methodChannel.invokeMethod<bool>('tip', {
|
return methodChannel.invokeMethod<bool>('tip', {'message': '$message'});
|
||||||
'message': '$message',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool?> initShortcuts() async {
|
Future<bool?> initShortcuts() async {
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ class SetupAction extends _$SetupAction {
|
|||||||
final message = await coreController.updateConfig(
|
final message = await coreController.updateConfig(
|
||||||
updateParams.copyWith.tun(enable: realTunEnable),
|
updateParams.copyWith.tun(enable: realTunEnable),
|
||||||
);
|
);
|
||||||
|
ref.read(checkIpNumProvider.notifier).add();
|
||||||
if (message.isNotEmpty) throw message;
|
if (message.isNotEmpty) throw message;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -254,7 +255,6 @@ class SetupAction extends _$SetupAction {
|
|||||||
.read(proxiesActionProvider.notifier)
|
.read(proxiesActionProvider.notifier)
|
||||||
.updateCurrentGroupName(GroupName.GLOBAL.name);
|
.updateCurrentGroupName(GroupName.GLOBAL.name);
|
||||||
}
|
}
|
||||||
ref.read(checkIpNumProvider.notifier).add();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void autoApplyProfile() {
|
void autoApplyProfile() {
|
||||||
@@ -593,9 +593,11 @@ class SystemAction extends _$SystemAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleBackOrExit() async {
|
Future<void> handleClose([bool exit = true]) async {
|
||||||
if (ref.read(backBlockProvider)) return;
|
if (!system.isDesktop) {
|
||||||
if (ref.read(appSettingProvider).minimizeOnExit) {
|
if (ref.read(backBlockProvider)) return;
|
||||||
|
}
|
||||||
|
if (ref.read(appSettingProvider).minimizeOnExit || !exit) {
|
||||||
if (system.isDesktop) {
|
if (system.isDesktop) {
|
||||||
await preferences.saveConfig(ref.read(configProvider));
|
await preferences.saveConfig(ref.read(configProvider));
|
||||||
}
|
}
|
||||||
@@ -910,14 +912,14 @@ class ProfilesAction extends _$ProfilesAction {
|
|||||||
|
|
||||||
Future<void> addProfileFormFile() async {
|
Future<void> addProfileFormFile() async {
|
||||||
final platformFile = await globalState.safeRun(picker.pickerFile);
|
final platformFile = await globalState.safeRun(picker.pickerFile);
|
||||||
final bytes = platformFile?.bytes;
|
if (platformFile == null) return;
|
||||||
if (bytes == null) return;
|
final bytes = await platformFile.readBytes();
|
||||||
globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst);
|
globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst);
|
||||||
ref.read(currentPageLabelProvider.notifier).toProfiles();
|
ref.read(currentPageLabelProvider.notifier).toProfiles();
|
||||||
final profile = await globalState.loadingRun(
|
final profile = await globalState.loadingRun(
|
||||||
tag: LoadingTag.profiles,
|
tag: LoadingTag.profiles,
|
||||||
() async {
|
() async {
|
||||||
return Profile.normal(label: platformFile?.name).saveFile(bytes);
|
return Profile.normal(label: platformFile.name).saveFile(bytes);
|
||||||
},
|
},
|
||||||
title: currentAppLocalizations.addProfile,
|
title: currentAppLocalizations.addProfile,
|
||||||
);
|
);
|
||||||
@@ -973,3 +975,22 @@ class ProfilesAction extends _$ProfilesAction {
|
|||||||
await coreController.deleteFile(providersDirPath);
|
await coreController.deleteFile(providersDirPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Riverpod(keepAlive: true)
|
||||||
|
class GeoResourceAction extends _$GeoResourceAction {
|
||||||
|
@override
|
||||||
|
void build() {}
|
||||||
|
|
||||||
|
Future<void> updateGeoResource(GeoResource geoResource) async {
|
||||||
|
await coreController.updateGeoData(geoResource.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateGeoResourceUrl(GeoResource geoResource, String newUrl) {
|
||||||
|
if (!newUrl.isUrl) {
|
||||||
|
throw 'Invalid url';
|
||||||
|
}
|
||||||
|
ref.read(patchClashConfigProvider.notifier).update((state) {
|
||||||
|
return state.copyWith(geoXUrl: {...state.geoXUrl, geoResource: newUrl});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||