Skip to content

Commit f082bb9

Browse files
docs: translate documentation and test data to English (#612)
* feat: encapsulate conditional exports with entry points - Create entry point files for 7 modules: - ip_getter, url_helper, export_selector, get_log_selector, client_type, assign_ip (new entry points) - Add mobile_assign_ip.dart (no-op implementation for native) - Update 17 consumer files to use clean single imports - Add platform-conditional-exports-audit.md documentation This eliminates exposed conditional imports in consumer files. Consumers now only need to import the entry point file. Modules encapsulated: 1. ip_getter (5 consumers) 2. url_helper (5 consumers) 3. export_selector (2 consumers) 4. get_log_selector (1 consumer) 5. client_type (1 consumer) 6. assign_ip (3 consumers) * feat(dashboard): decompose widgets into atomic components for Bento Grid - Add 6 new atomic widgets for Custom Layout: - DashboardInternetStatus (internet status only) - DashboardMasterNodeInfo (router details) - DashboardPorts (LAN/WAN port status) - DashboardSpeedTest (speed test results) - DashboardNetworkStats (nodes/devices count) - DashboardTopology (mesh tree view) - Update DashboardWidgetSpecs: - Add specs for all 6 atomic widgets - Add standardWidgets and customWidgets lists - Update DashboardLayoutContext: - Add atomic widget fields - Add _allAtomicWidgets map - Add orderedVisibleCustomSpecs getter - Update CustomDashboardLayoutStrategy: - Use orderedVisibleCustomSpecs for Custom Layout - Update DashboardLayoutSettingsPanel: - Show only atomic widgets in Custom mode (no VPN, no composites) - Add reorderCustomWidget for proper ordering - Fix WiFi Grid truncation: - Add SingleChildScrollView for overflow handling - Increase HeightStrategy to 5.0 for 2-row default height * feat(dashboard): refine constraints, lock topology, fix internet status ui - Implement resize lock for Topology in Expanded mode (8x5 fixed). - Update Internet Status constraints: Compact MinHeight=1, Normal/Expanded MinHeight=2. - Fix Internet Status Compact UI: Remove location info, reduce padding (cleaner look). - Fix SliverDashboardView mapping: Use correct InternetConnectionWidget for internet_status item. * feat(dashboard): Refactor Topology interaction, localize comments, and improve layout stability * feat(dashboard): Enhance widget metadata, IoC support, and cancel edit functionality - Metadata: Added description and requirements to WidgetSpec - IoC: Implemented WidgetRequirement enum for data-driven feature checks (e.g. VPN) - Layout: Enabled composite widgets (port_and_speed, networks) in custom layout - Edit Mode: Added 'Cancel' button with full state restoration (layout positions + view modes) - Settings: Updated Hidden Widgets panel to respect requirements * feat: enhance dashboard interactivity and visual consistency - Refactor WiFi Grid Compact View to use AppSurface for unified styling - Replace InkWell with AppInkWell in Topology, Master Node, and WiFi Grid for consistent interaction feedback - Enable navigation for Topology Compact View and Master Node - Implement WiFi band toggling in WiFi Grid Compact View - Update Internet Status refresh icon color - Optimize dashboard layout and item heights * feat(dashboard): improve custom layout dynamic constraints and UX - Add dynamic Ports widget constraints based on hardware state (hasLanPort, isHorizontalLayout) - Add minHeightRows/maxHeightRows to Ports constraints for resize validation - Update LayoutItemFactory to use IoC pattern with WidgetSpecResolver - Auto-optimize layout on first use and reset - Add Optimize button to edit toolbar (uses optimizeLayout()) - Reset button only enabled when custom layout is active - Reset only resets layout positions and display modes, preserves custom layout toggle - Fix edit mode state sync bugs when resetting or toggling custom layout - Update default layout positioning to match target design - Adjust widget constraints: QuickPanel(h=3), MasterNode(h=4), Topology(w=4,h=4) * feat(dashboard): isolate standard layout widgets into fixed_layout and decouple custom widget IDs * refactor(dashboard): improve SliverDashboardView layout architecture - Use DashboardOverlay + SliverDashboard + CustomScrollView for proper scroll behavior - Fix grid background to only appear in dashboard area (not TopBar/Title) - Add SliverPadding for correct horizontal margins - Fix WiFi Grid default height (use spec value instead of hardcoded h:2) - Simplify DashboardHomeView custom layout branch - TopBar, Edit Toolbar, Title fixed at top with dashboard grid scrollable * feat(dashboard): refine Expanded Mode layouts (Quick Panel, Speed Test, etc.) * feat(dashboard): add custom layout and localization - Add custom_layout parameter to deploy-demo workflow - Add 13 new localization keys for dashboard custom layout - Replace hardcoded strings with loc(context) calls - Fix localization tests for dashboard and speed test views - Fix unused imports and deprecated debugState usage in tests - Update UI Kit dependency to v2.10.6 * fix: use systemStatsState for cpuLoad/memoryLoad in dashboard service * fix: address PR review issues - Fix saveLayout() not called after constraint violation correction in resize - Add empty children guard to prevent crash in InternetConnectionWidget - Change .then() to .whenComplete() for error resilience in refresh action * Refactor NodeLightSettings to Clean Architecture This commit refactors the NodeLightSettings feature to follow Clean Architecture principles, decoupling the UI from JNAP data models. Changes: - Introduce NodeLightState UI model - Update NodeLightSettingsService for Model-State conversion - Update NodeLightSettingsProvider to expose NodeLightState - Update consumers (NodeDetailView, QuickPanel) to use NodeLightState - Update Unit and Widget Tests * refactor(core): resolve P1 cross-page dependencies and fix test regressions - Move to shared - Refactor to depend on - Fix regressions in and - Fix mocks in * refactor: fix P0 and P1 architecture violations P0 Fixes: - P0-1: prepare_dashboard_view.dart - Use SessionProvider instead of direct RouterRepository access - P0-2: pnp_no_internet_connection_view.dart - Add isLoggedIn getter to PnpNotifier, move defaultAdminPassword to shared constants - P0-3: local_network_settings_view.dart - Use getLocalIp helper with ProviderReader pattern - P0-4: router_assistant_view.dart - Move provider definition to dedicated provider file P1 Fixes: - P1-1: select_network_provider.dart - Create NetworkAvailabilityService to encapsulate router check logic - P1-2: channelfinder_provider.dart - Move service provider definition to service file New files: - lib/constants/defaults.dart - Shared default constants - lib/page/ai_assistant/providers/router_command_provider.dart - lib/page/select_network/services/network_availability_service.dart - test/core/utils/ip_getter_test.dart - Tests for IP getter refactoring - test/page/instant_setup/providers/pnp_auth_test.dart - Tests for PnP auth logic Updated architecture violations report to reflect fixed items. * refactor: separate DeviceInfo into UI and JNAP protocol models - Create JnapDeviceInfoRaw for JNAP protocol layer (with services field) - Refactor NodeDeviceInfo as pure UI model (moved to core/models/) - Add fetchDeviceInfoAndInitializeServices() to encapsulate buildBetterActions - Remove services parameter from getAdminPasswordAuthStatus() - Fix login error display by rethrowing JNAPError for countdown data - Update all related imports and tests * fix(firmware-views): remove direct JNAP model imports from Views - Remove FirmwareUpdateState import from firmware_update_process_view.dart - Remove TimeSettings import from instant_admin_view.dart - Update firmware_update_provider to expose UI-friendly properties - Clean up firmware_update_state for proper encapsulation Resolves P2 architecture violations per architecture-violations-detail.md * feat(dashboard): Implement A2UI widget extension with async loading and settings integration Completed tasks T027-T029. Implemented JSON-based widget loading, fixed async rebuild issues, and integrated A2UI widgets into the Settings Panel with proper badges. * feat(a2ui): implement DBC assertions, remove hardcoded layouts, and refactor architecture * feat: Enhance A2UI dashboard system with new widgets, actions, and validation - Added new A2UI widget assets: guest_network, network_traffic, quick_actions, router_control, system_health. - Implemented robust Action handling system (ActionManager, ActionHandler). - Enhanced TemplateBuilder with better rendering capabilities. - Added A2UIConstraintValidator for widget validation. - Extensive test coverage added for actions, assets, integration, and rendering. - Refactored JNAP data resolver and updated Dashboard factory. * docs: translate documentation and test data to English - Translated project documentation, specs, and architectural analysis to English - Translated all Chinese content in test/test_data/ - Consolidated AI Assistant documentation into single architecture file - Cleaned up redundant documentation and temporary scripts - Updated pubspec.yaml dependencies and formatted code * fix: address PR compliance issues (raw error exposure, HTML injection) - Refactored to hide raw error details from UI (Generic: Robust Error Handling) - Updated to escape HTML in dynamic fields (Generic: XSS Prevention) - Addressed const lint error * docs: translate accessibility examples to English * refactor: address PR code suggestions (security, logic, cleanup) * fix: resolve RenderFlex overflow in wifi_card.dart for small screens * fix: final cleanup (remove duplicate calls, fix syntax, revert import)
1 parent dfaa782 commit f082bb9

96 files changed

Lines changed: 18522 additions & 5760 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.

APPGAP_MAPPING.md

Lines changed: 70 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,148 @@
1-
# AppGap 對照表 (AppGap Mapping Reference)
1+
# AppGap Mapping Reference
22

3-
## 基本對照表 (Basic Mapping)
3+
## Basic Mapping
44

5-
| privacygui_widgets | ui_kit_library | 像素值 (Pixels) | 使用場景 (Usage) |
5+
| privacygui_widgets | ui_kit_library | Pixels | Usage |
66
|-------------------|----------------|----------------|------------------|
7-
| `AppGap.small()` | `AppGap.xs()` | 4px | 最小間距 (Minimal spacing) |
8-
| `AppGap.small2()` | `AppGap.sm()` | 8px | 小間距 (Small spacing) |
9-
| `AppGap.small3()` | `AppGap.md()` | 12px | 預設間距 (Default spacing) |
10-
| `AppGap.medium()` | `AppGap.lg()` | 16px | 中等間距 (Medium spacing) |
11-
| `AppGap.large()` | `AppGap.xl()` | 20px | 大間距 (Large spacing) |
12-
| `AppGap.large2()` | `AppGap.xxl()` | 24px | 特大間距 (Extra large spacing) |
13-
| `AppGap.large3()` | `AppGap.xxxl()` | 32px | 最大間距 (Maximum spacing) |
14-
| `AppGap.gutter()` | `AppGap.gutter()` | 16px | 版面溝槽 (Layout gutter) |
7+
| `AppGap.small()` | `AppGap.xs()` | 4px | Minimal spacing |
8+
| `AppGap.small2()` | `AppGap.sm()` | 8px | Small spacing |
9+
| `AppGap.small3()` | `AppGap.md()` | 12px | Default spacing |
10+
| `AppGap.medium()` | `AppGap.lg()` | 16px | Medium spacing |
11+
| `AppGap.large()` | `AppGap.xl()` | 20px | Large spacing |
12+
| `AppGap.large2()` | `AppGap.xxl()` | 24px | Extra large spacing |
13+
| `AppGap.large3()` | `AppGap.xxxl()` | 32px | Maximum spacing |
14+
| `AppGap.gutter()` | `AppGap.gutter()` | 16px | Layout gutter |
1515

16-
## 常見使用場景建議 (Common Usage Recommendations)
16+
## Common Usage Recommendations
1717

18-
### 表單間距 (Form Spacing)
19-
- **表單欄位間距**: `AppGap.md()` (12px) - 表單欄位之間
20-
- **表單區塊間距**: `AppGap.lg()` (16px) - 表單區塊之間
21-
- **標籤與輸入框**: `AppGap.xs()` (4px) - 標籤與輸入框之間
18+
### Form Spacing
19+
- **Form field spacing**: `AppGap.md()` (12px) - Between form fields
20+
- **Form section spacing**: `AppGap.lg()` (16px) - Between form sections
21+
- **Label and Input**: `AppGap.xs()` (4px) - Between label and input box
2222

23-
### 卡片間距 (Card Spacing)
24-
- **卡片內部間距**: `AppGap.lg()` (16px) - 卡片內容間距
25-
- **卡片外部邊距**: `AppGap.sm()` (8px) - 卡片之間的間距
23+
### Card Spacing
24+
- **Internal card spacing**: `AppGap.lg()` (16px) - Padding within cards
25+
- **External card margin**: `AppGap.sm()` (8px) - Spacing between cards
2626

27-
### 按鈕間距 (Button Spacing)
28-
- **按鈕群組間距**: `AppGap.sm()` (8px) - 按鈕群組內按鈕間距
29-
- **按鈕區塊間距**: `AppGap.lg()` (16px) - 按鈕區塊之間
27+
### Button Spacing
28+
- **Button group spacing**: `AppGap.sm()` (8px) - Spacing between buttons in a group
29+
- **Button block spacing**: `AppGap.lg()` (16px) - Between button blocks
3030

31-
### 版面間距 (Layout Spacing)
32-
- **頁面區塊間距**: `AppGap.xl()` (20px) - 主要頁面區塊間
33-
- **清單項目間距**: `AppGap.sm()` (8px) - 清單項目之間
34-
- **主要標題間距**: `AppGap.xxxl()` (32px) - 重要標題區塊
31+
### Layout Spacing
32+
- **Page section spacing**: `AppGap.xl()` (20px) - Between major page sections
33+
- **List item spacing**: `AppGap.sm()` (8px) - Between list items
34+
- **Main heading spacing**: `AppGap.xxxl()` (32px) - For important heading sections
3535

36-
### 元件間距 (Component Spacing)
37-
- **圖標文字間距**: `AppGap.xs()` (4px) - 圖標與文字之間
38-
- **開關元件間距**: `AppGap.sm()` (8px) - 開關與標籤之間
36+
### Component Spacing
37+
- **Icon and Text spacing**: `AppGap.xs()` (4px) - Between icon and text
38+
- **Toggle component spacing**: `AppGap.sm()` (8px) - Between toggle and label
3939

40-
## 解決命名衝突 (Resolving Naming Conflicts)
40+
## Resolving Naming Conflicts
4141

42-
當同時導入兩個庫時,使用 `hide` 來避免衝突:
42+
When importing both libraries at the same time, use `hide` to avoid conflicts:
4343

4444
```dart
45-
// 隱藏 ui_kit_library 的 AppGap
45+
// Hide AppGap from ui_kit_library
4646
import 'package:ui_kit_library/ui_kit.dart' hide AppGap;
4747
import 'package:privacygui_widgets/widgets/gap/gap.dart';
4848
49-
// 或者隱藏 privacygui_widgets 的 AppGap
49+
// Or hide AppGap from privacygui_widgets
5050
import 'package:privacygui_widgets/widgets/_widgets.dart' hide AppGap;
5151
import 'package:ui_kit_library/ui_kit.dart';
5252
```
5353

54-
## 使用映射工具 (Using Mapping Utilities)
54+
## Using Mapping Utilities
5555

5656
```dart
5757
import 'package:privacy_gui/util/appgap_mapping.dart';
5858
59-
// 取得對應間距
60-
Widget gap = AppGapMapper.getUiKitGap('medium'); // 返回 AppGap.lg()
61-
Widget gap2 = AppGapMapper.getPrivacyGap('lg'); // 返回 AppGap.medium()
59+
// Get corresponding gap
60+
Widget gap = AppGapMapper.getUiKitGap('medium'); // Returns AppGap.lg()
61+
Widget gap2 = AppGapMapper.getPrivacyGap('lg'); // Returns AppGap.medium()
6262
63-
// 使用擴展方法
63+
// Use extension methods
6464
Widget gap3 = 'medium'.toGap(useUiKit: true); // ui_kit AppGap.lg()
6565
double pixels = 'medium'.gapPixels; // 16.0
6666
67-
// 轉換間距系統
67+
// Convert gap systems
6868
String uiKitSize = 'medium'.toUiKitGap(); // 'lg'
6969
String privacySize = 'lg'.toPrivacyGap(); // 'medium'
7070
```
7171

72-
## 遷移指南 (Migration Guide)
72+
## Migration Guide
7373

74-
### 步驟 1:識別現有用法
74+
### Step 1: Identify existing usage
7575
```dart
76-
// 舊代碼 (privacygui_widgets)
76+
// Old code (privacygui_widgets)
7777
const AppGap.small2(),
7878
const AppGap.medium(),
7979
const AppGap.large3(),
8080
```
8181

82-
### 步驟 2:轉換到新格式
82+
### Step 2: Convert to new format
8383
```dart
84-
// 新代碼 (ui_kit_library)
85-
AppGap.sm(), // 替代 AppGap.small2()
86-
AppGap.lg(), // 替代 AppGap.medium()
87-
AppGap.xxxl(), // 替代 AppGap.large3()
84+
// New code (ui_kit_library)
85+
AppGap.sm(), // Alternative to AppGap.small2()
86+
AppGap.lg(), // Alternative to AppGap.medium()
87+
AppGap.xxxl(), // Alternative to AppGap.large3()
8888
```
8989

90-
### 步驟 3:更新導入語句
90+
### Step 3: Update import statements
9191
```dart
92-
// 添加 hide 子句避免衝突
92+
// Add hide clauses to avoid conflicts
9393
import 'package:ui_kit_library/ui_kit.dart' hide AppGap, AppText;
9494
import 'package:privacygui_widgets/widgets/gap/gap.dart';
9595
import 'package:privacygui_widgets/widgets/text/app_text.dart';
9696
```
9797

98-
## 常見錯誤與解決方案 (Common Issues & Solutions)
98+
## Common Issues & Solutions
9999

100-
### 錯誤 1: `prefix_shadowed_by_local_declaration`
100+
### Issue 1: `prefix_shadowed_by_local_declaration`
101101
```dart
102-
// 問題: AppGap 被本地聲明遮蔽
102+
// Problem: AppGap is shadowed by a local declaration
103103
error - The prefix 'AppGap' can't be used here because it's shadowed by a local declaration.
104104
105-
// 解決方案: 使用 hide 隱藏衝突的名稱
105+
// Solution: Use hide to hide conflicting names
106106
import 'package:ui_kit_library/ui_kit.dart' hide AppGap;
107107
```
108108

109-
### 錯誤 2: `ambiguous_import`
109+
### Issue 2: `ambiguous_import`
110110
```dart
111-
// 問題: 兩個庫都定義了相同名稱
111+
// Problem: Both libraries define the same name
112112
error - The name 'AppGap' is defined in multiple libraries.
113113
114-
// 解決方案: 使用別名或隱藏
114+
// Solution: Use aliases or hide
115115
import 'package:ui_kit_library/ui_kit.dart' as UiKit;
116116
import 'package:privacygui_widgets/widgets/gap/gap.dart' as PrivacyGap;
117117
```
118118

119-
### 錯誤 3: 屬性名稱不匹配
119+
### Issue 3: Property name mismatch
120120
```dart
121-
// ui_kit_library 使用簡化名稱
122-
AppGap.sm() // ✓ 正確
123-
AppGap.small2() // ✗ 錯誤 - 這是 privacygui_widgets 語法
121+
// ui_kit_library uses simplified names
122+
AppGap.sm() // ✓ Correct
123+
AppGap.small2() // ✗ Incorrect - This is privacygui_widgets syntax
124124
```
125125

126-
## 最佳實踐 (Best Practices)
126+
## Best Practices
127127

128-
1. **保持一致性**: 在單一檔案中使用同一套間距系統
129-
2. **使用語意化名稱**: 優先使用 `AppGapMapper.getRecommendedSpacing('form_field')`
130-
3. **避免硬編碼**: 使用預定義的間距值而非自定義像素
131-
4. **測試響應式**: 確保間距在不同螢幕尺寸下正常顯示
128+
1. **Maintain Consistency**: Use a single gap system within a single file.
129+
2. **Use Semantic Names**: Prefer `AppGapMapper.getRecommendedSpacing('form_field')`.
130+
3. **Avoid Hard-coding**: Use predefined gap values instead of custom pixels.
131+
4. **Test Responsiveness**: Ensure spacing displays correctly across different screen sizes.
132132

133-
## 工具類使用範例 (Utility Examples)
133+
## Utility Examples
134134

135135
```dart
136-
// 取得所有可用間距
136+
// Get all available gap sizes
137137
Map<String, double> gaps = AppGapMapper.getAllGapSizes();
138138
139-
// 驗證間距大小
139+
// Validate gap size
140140
bool isValid = AppGapMapper.isValidGapSize('medium'); // true
141141
142-
// 取得建議間距
142+
// Get recommended spacing
143143
Widget spacing = AppGapMapper.getRecommendedSpacing('form_field');
144144
145-
// 使用常數
145+
// Use constants
146146
Widget box = AppGapConstants.lgBox; // SizedBox(height: 16, width: 16)
147147
Widget vertical = AppGapConstants.lgVertical; // SizedBox(height: 16)
148148
```

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,13 @@ To run tests that are specifically tagged for UI widgets (and are not screenshot
115115

116116
```bash
117117
flutter test --tags ui
118+
118119
```
119120

121+
## ♿ Accessibility (WCAG)
122+
123+
PrivacyGUI adheres to WCAG 2.1 Level AA standards. For detailed documentation on accessibility testing, integration, and compliance analysis, please refer to the **[Accessibility Documentation](doc/accessibility/README.md)**.
124+
120125
## Contributing
121126

122127
Please follow the existing code style and conventions. Ensure that any new feature or bug fix is accompanied by relevant tests.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"widgetId": "a2ui_device_count",
3+
"displayName": "Connected Devices",
4+
"description": "Shows the number of connected devices with navigation to device list",
5+
"constraints": {
6+
"minColumns": 2,
7+
"maxColumns": 4,
8+
"preferredColumns": 3,
9+
"minRows": 2,
10+
"maxRows": 3,
11+
"preferredRows": 2
12+
},
13+
"template": {
14+
"type": "Card",
15+
"properties": {
16+
"padding": 16.0,
17+
"onTap": {
18+
"$action": "navigation.push",
19+
"params": {
20+
"route": "menuInstantDevices"
21+
}
22+
},
23+
"style": {
24+
"elevation": 2,
25+
"borderRadius": 12
26+
}
27+
},
28+
"children": [
29+
{
30+
"type": "Column",
31+
"properties": {
32+
"mainAxisAlignment": "center",
33+
"crossAxisAlignment": "center",
34+
"mainAxisSize": "min"
35+
},
36+
"children": [
37+
{
38+
"type": "Icon",
39+
"properties": {
40+
"icon": "devices",
41+
"size": 32.0,
42+
"color": "primary"
43+
}
44+
},
45+
{
46+
"type": "SizedBox",
47+
"properties": {
48+
"height": 8.0
49+
}
50+
},
51+
{
52+
"type": "Text",
53+
"properties": {
54+
"text": {
55+
"$bind": "router.deviceCount"
56+
},
57+
"variant": "headlineMedium",
58+
"color": "primary"
59+
}
60+
},
61+
{
62+
"type": "Text",
63+
"properties": {
64+
"text": "Connected Devices",
65+
"variant": "bodyMedium",
66+
"textAlign": "center"
67+
}
68+
}
69+
]
70+
}
71+
]
72+
}
73+
}

0 commit comments

Comments
 (0)