Skip to content

Commit 670a98d

Browse files
committed
Add custom overwrite
Optimize windows ipc Optimize windows arm64 Optimize some details Update core
1 parent 672eacc commit 670a98d

320 files changed

Lines changed: 31962 additions & 7672 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/commands/i18n.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
Scan `lib/` for hardcoded Chinese strings and internationalize them following the project's ARB conventions.
2+
3+
## Instructions
4+
5+
You are performing i18n extraction for a Flutter project that uses the Flutter Intl plugin with ARB files.
6+
7+
### Project localization context
8+
9+
- **ARB files**: `arb/intl_en.arb`, `arb/intl_zh_CN.arb`, `arb/intl_ja.arb`, `arb/intl_ru.arb`
10+
- **Key conventions**: camelCase, flat keys (no nesting, no `@` metadata), semantic naming
11+
- Short labels: `rule`, `global`, `direct`, `edit`, `confirm`
12+
- Descriptive suffix `Desc`: `themeDesc`, `tunDesc`, `logsDesc`
13+
- Validation suffix: `profileNameNullValidationDesc`
14+
- **Generated code**: `lib/l10n/l10n.dart` (DO NOT edit generated files)
15+
- **Access patterns**:
16+
- In widgets with BuildContext: `context.appLocalizations.key` (import `common.dart`)
17+
- In controllers/providers/non-widget code: `currentAppLocalizations.key` (import `app_localizations.dart`)
18+
19+
### Step 1: Find hardcoded Chinese strings
20+
21+
Use Grep to search `lib/` for Chinese characters. The regex pattern for Chinese characters is `[\x{4e00}-\x{9fff}]`.
22+
23+
Important filters:
24+
- **Exclude** `lib/l10n/` (generated localization files)
25+
- **Exclude** lines that already use `appLocalizations` or `currentAppLocalizations`
26+
- **Exclude** false positives that are NOT Chinese text:
27+
- Arrow symbols: `` `` `` `` (Unicode arrows, not CJK)
28+
- Middle dot: `·` (U+00B7, not CJK)
29+
- Command symbol: `` (U+2318, not CJK)
30+
- Other CJK punctuation that is used as UI symbols, not translatable text
31+
32+
For each match, read the surrounding context (5-10 lines) to understand:
33+
- What the string represents (label, error message, tooltip, dialog text, etc.)
34+
- Whether it's inside a widget (has `BuildContext` available) or non-widget code
35+
- Whether it appears in a `Text()`, `TextSpan()`, `title:`, `label:`, or other text position
36+
37+
### Step 2: Generate ARB keys
38+
39+
For each hardcoded Chinese string:
40+
41+
1. **Choose a key name** following project conventions:
42+
- Use the Chinese meaning to derive an English camelCase key
43+
- Keep it concise: `createConfig` not `createAConfigurationForTheProfile`
44+
- Use `Desc` suffix for descriptive/explanatory text
45+
- Use existing similar keys as reference (check `arb/intl_en.arb` for patterns)
46+
47+
2. **Determine the English translation** (the value for `intl_en.arb`)
48+
49+
3. **Determine the Chinese translation** (the value for `intl_zh_CN.arb`) — this is the original hardcoded string
50+
51+
4. **For ja and ru**: use the English translation as a placeholder (translators will fill these in later)
52+
53+
### Step 3: Update ARB files
54+
55+
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).
56+
57+
Format: add a new line like `"keyName": "value",` before the closing `}`.
58+
59+
### Step 4: Replace hardcoded strings in Dart files
60+
61+
Replace each hardcoded Chinese string with the appropriate localization call:
62+
63+
- If inside a widget BuildContext: `context.appLocalizations.keyName`
64+
- If in controller/provider code: `currentAppLocalizations.keyName`
65+
66+
Ensure the correct import exists:
67+
- For `context.appLocalizations`: the file should import `common.dart` (check if it already does)
68+
- For `currentAppLocalizations`: the file should import `app_localizations.dart` (check if it already does)
69+
70+
If the file uses string interpolation (e.g., `'创建 $name 配置'`), convert to the ARB parameterized format:
71+
- In ARB: `"keyName": "Create $name config"`
72+
- In Dart: `currentAppLocalizations.keyName(name)`
73+
74+
### Step 5: Report changes
75+
76+
After all modifications, output a summary:
77+
1. List each file modified and what changed
78+
2. List each new ARB key added with its translations
79+
3. Remind the user to run code generation if needed:
80+
```
81+
dart run build_runner build --delete-conflicting-outputs
82+
```
83+
or trigger Flutter Intl regeneration in their IDE.
84+
85+
### Important notes
86+
87+
- Only extract strings that are user-facing UI text. Do NOT extract:
88+
- Comments (lines starting with `//`)
89+
- Log messages (unless they appear in the UI)
90+
- Variable names or identifiers
91+
- String literals used as keys/identifiers (not displayed to users)
92+
- If a Chinese string is split across multiple lines or concatenations, merge them into a single ARB entry
93+
- If a string contains dynamic content (variables, URLs), use ARB parameter syntax `$variableName`

.github/workflows/build.yaml

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,33 @@ env:
88
IS_STABLE: ${{ !contains(github.ref, '-') }}
99

1010
jobs:
11+
test:
12+
name: Test
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
with:
18+
submodules: recursive
19+
20+
- name: Setup Flutter
21+
uses: subosito/flutter-action@v2
22+
with:
23+
channel: stable
24+
flutter-version: 3.41.9
25+
cache: true
26+
27+
- name: Install dependencies
28+
run: flutter pub get
29+
30+
- name: Analyze
31+
run: flutter analyze --no-fatal-infos
32+
33+
- name: Run tests
34+
run: flutter test --reporter expanded
35+
1136
build:
37+
needs: [ test ]
1238
runs-on: ${{ matrix.os }}
1339
strategy:
1440
matrix:
@@ -27,9 +53,9 @@ jobs:
2753
- platform: macos
2854
os: macos-latest
2955
arch: arm64
30-
# - platform: windows
31-
# os: windows-11-arm
32-
# arch: arm64
56+
- platform: windows
57+
os: windows-11-arm
58+
arch: arm64
3359
- platform: linux
3460
os: ubuntu-24.04-arm
3561
arch: arm64
@@ -64,19 +90,23 @@ jobs:
6490
cache-dependency-path: |
6591
core/go.sum
6692
93+
- name: Enable git long paths (Windows)
94+
if: startsWith(matrix.os, 'windows')
95+
run: git config --global core.longpaths true
96+
6797
- name: Setup Flutter
6898
if: ${{ !(startsWith(matrix.os, 'windows-11-arm') || startsWith(matrix.os, 'ubuntu-24.04-arm')) }}
6999
uses: subosito/flutter-action@v2
70100
with:
71101
channel: stable
72-
flutter-version: 3.35.7
102+
flutter-version: 3.41.9
73103
cache: true
74104
- name: Setup Flutter With Other
75105
if: startsWith(matrix.os, 'windows-11-arm') || startsWith(matrix.os, 'ubuntu-24.04-arm')
76106
uses: subosito/flutter-action@v2
77107
with:
78108
channel: master
79-
flutter-version: 3.35.7
109+
flutter-version: 3.44.0-0.1.pre
80110
cache: true
81111

82112
- name: Get Flutter Dependency

.gitignore

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ app.*.symbols
4141
# Obfuscation related
4242
app.*.map.json
4343

44-
#AI generated
45-
CLAUDE.md
46-
/.claude
44+
# Claude Code - ignore user-specific settings only
45+
.claude/settings.local.json
4746

4847

4948
# Android Studio will place build artifacts here

CLAUDE.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
FlClash is a multi-platform proxy client based on ClashMeta (mihomo), built with Flutter. Supports Android, Windows,
8+
macOS, and Linux. Material You design with Surfboard-like UI.
9+
10+
## Common Development Commands
11+
12+
### Building
13+
14+
```bash
15+
# Update submodules first (ClashMeta Go core lives in core/Clash.Meta/)
16+
git submodule update --init --recursive
17+
18+
# Build core + Flutter app via setup.dart
19+
dart ./setup.dart android --arch arm64
20+
dart ./setup.dart android --arch arm --arch-name armeabi-v7a
21+
dart ./setup.dart android --arch amd64 --arch-name x86_64
22+
dart ./setup.dart macos --arch arm64
23+
dart ./setup.dart macos --arch amd64
24+
dart ./setup.dart linux --arch amd64
25+
dart ./setup.dart windows --arch amd64
26+
27+
# Build only the Go core (skip Flutter packaging)
28+
dart ./setup.dart android --arch arm64 --out core
29+
dart ./setup.dart macos --arch arm64 --out core
30+
```
31+
32+
### Flutter Development
33+
34+
```bash
35+
flutter pub get
36+
flutter run # Run on connected device/desktop
37+
flutter test # Run all tests (use flutter test, not dart test — models pull in Flutter types)
38+
```
39+
40+
### Code Generation
41+
42+
Required after modifying models, providers, or database schema:
43+
44+
```bash
45+
dart run build_runner build --delete-conflicting-outputs
46+
dart run build_runner watch # Continuous regeneration
47+
```
48+
49+
Code generation covers: Riverpod providers (`riverpod_generator`), models (`freezed`, `json_serializable`), and database
50+
tables (`drift_dev`).
51+
52+
### Testing
53+
54+
Tests use `package:test/test.dart` for pure Dart logic (common utils, models) and `flutter_test` for provider/widget tests.
55+
`mocktail` is the mocking framework.
56+
57+
```bash
58+
flutter test test/models/ # Model serialization & extension round-trip tests
59+
flutter test test/core/ # CoreController tests (mocked CoreHandlerInterface)
60+
flutter test test/providers/ # Riverpod provider tests (config & app state notifiers)
61+
flutter test test/common/ # Utility function tests (utils, string, iterable, fixed, etc.)
62+
flutter test test/database/ # Database type converter tests
63+
```
64+
65+
**Mocking `CoreHandlerInterface`:** Use `CoreController.test(mock)` to inject a mock interface. Call
66+
`CoreController.resetInstance()` in `tearDown` to clean up the singleton between tests. Remember to
67+
`registerFallbackValue()` for freezed params used with `any()` matchers.
68+
69+
**Provider tests:** Use `ProviderContainer` directly (no widget tree needed for simple notifiers). The Riverpod
70+
generated `update()` method takes a callback: `notifier.update((state) => newValue)`.
71+
72+
**Model round-trip tests:** Always go through `jsonEncode`/`jsonDecode` when testing freezed models with
73+
nested objects — `toJson()` stores child objects directly (not as maps), so direct `fromJson(toJson())`
74+
fails for nested freezed types.
75+
76+
### Build Dependencies
77+
78+
**Linux:** `sudo apt-get install libayatana-appindicator3-dev libkeybinder-3.0-dev`
79+
80+
**Windows:** GCC and Inno Setup. `ANDROID_NDK` env var for Android builds.
81+
82+
**macOS:** `npm install -g appdmg` for DMG creation.
83+
84+
## Architecture
85+
86+
### Core Integration (Go ClashMeta <-> Flutter)
87+
88+
This is the most important architectural concept. The Go proxy core (`core/`) operates in two modes:
89+
90+
- **Android (lib mode):** Go core compiled as C shared library (`libclash.so`) via `go build -buildmode=c-shared` with
91+
CGO. Flutter calls it via FFI through the `service` plugin. Dart-side: `lib/core/lib.dart` (`CoreLib` class).
92+
93+
- **Desktop (core mode):** Go core runs as a separate process with `CGO_ENABLED=0`. Flutter communicates via
94+
JSON-over-socket (Unix socket on macOS/Linux, TCP on Windows). Dart-side: `lib/core/service.dart` (`CoreService`
95+
class).
96+
97+
`lib/core/controller.dart` (`CoreController`) selects the implementation based on platform. `lib/core/interface.dart`
98+
defines the shared `CoreHandlerInterface`.
99+
100+
Go core key files: `core/hub.go` (handler functions), `core/action.go` (dispatch), `core/lib.go` (CGO exports),
101+
`core/server.go` (socket server).
102+
103+
### State Management (Riverpod)
104+
105+
Provider files in `lib/providers/`:
106+
107+
- `app.dart` - Runtime/UI state (logs, traffic, delays, loading, navigation)
108+
- `config.dart` - Persistent config providers (app settings, theme, VPN, proxy style)
109+
- `state.dart` - Derived/computed providers (navigation, proxy, tray, color scheme)
110+
- `action.dart` - Business logic notifiers (setup, backup, core lifecycle, proxy selection)
111+
- `database.dart` - Drift database provider wrappers
112+
113+
`globalState` (`lib/state.dart`) is a singleton holding app lifecycle, timers, theme, and the start/stop state.
114+
Providers are generated into `lib/providers/generated/`.
115+
116+
### Database (Drift/SQLite)
117+
118+
Type-safe SQLite via Drift in `lib/database/`. Tables: `Profiles`, `Scripts`, `ProxyGroups`, `GlobalRules`,
119+
`ProfileAddedRules`, `ProfileCustomRules`, `ProfileDisabledRuleIds`, `Icons`, `Links`. Uses fractional indexing for
120+
ordering.
121+
122+
### Manager Stack (Widget Tree)
123+
124+
Managers are nested InheritedWidgets/StatefulWidgets in `lib/application.dart`:
125+
126+
```
127+
AppEnvManager > StatusManager > ThemeManager
128+
> [Desktop: WindowManager > TrayManager > HotKeyManager > ProxyManager]
129+
> ConnectivityManager > CoreManager > AppStateManager
130+
> [Mobile: AndroidManager > VpnManager | Desktop: WindowHeaderContainer]
131+
```
132+
133+
Each manager in `lib/manager/` handles a specific platform concern. Desktop-only managers are conditionally inserted.
134+
135+
### Core Controller + Actions
136+
137+
`lib/core/controller.dart` (`CoreController`) is a singleton facade over `CoreHandlerInterface`. All 25+ public methods
138+
delegate to the platform-specific interface (Android FFI or desktop socket). Has `@visibleForTesting` constructor and
139+
`resetInstance()` for test injection.
140+
141+
Business logic lives in Riverpod notifier classes in `lib/providers/action.dart` (~960 lines, should be split):
142+
143+
- `CommonAction` — update check, common UI operations
144+
- `SetupAction` — config setup, TUN management
145+
- `BackupAction` — backup/restore with WebDAV sync
146+
- `CoreAction` — core lifecycle (init, connect, restart, shutdown)
147+
- `SystemAction` — system integration (tray, exit, brightness)
148+
- `StoreAction` — profile storage operations
149+
- `ThemeAction` — theme state updates
150+
- `ProxiesAction` — group management, proxy selection
151+
- `ProfilesAction` — profile CRUD, auto-update, import
152+
153+
### Platform Managers (`lib/manager/`)
154+
155+
Desktop: `WindowManager`, `TrayManager`, `HotKeyManager`, `ProxyManager`
156+
Mobile: `AndroidManager`, `TileManager`, `VpnManager`
157+
Shared: `ConnectivityManager`, `CoreManager`, `AppStateManager`, `StatusManager`, `ThemeManager`
158+
159+
### Local Plugins (`plugins/`)
160+
161+
- `proxy` - System proxy configuration
162+
- `rust_api` - Flutter Rust Bridge FFI plugin (named pipe / local socket communication)
163+
- `tray_manager` - System tray (forked/custom)
164+
- `wifi_ssid` - Wi-Fi SSID detection
165+
- `window_ext` - Window extensions
166+
- `flutter_distributor` - App packaging/distribution
167+
168+
### Rust Helper Service (`services/helper/`)
169+
170+
Windows-only privileged helper for starting the core as admin and managing TUN. Built with
171+
`cargo build --release --features windows-service`. Token-based auth with Flutter app.
172+
173+
### Localization
174+
175+
ARB files in `arb/`. Generated via `flutter_intl` into `lib/l10n/`. Use `AppLocalizations.of(context)!` for strings.
176+
177+
**Supported locales:** `en`, `zh_CN`, `ja`, `ru`
178+
179+
**Access patterns:**
180+
181+
- In widgets with BuildContext: `context.appLocalizations.key` (import `common.dart`)
182+
- In controllers/providers/non-widget code: `currentAppLocalizations.key` (import `app_localizations.dart`)

0 commit comments

Comments
 (0)