diff --git a/doc/audit/platform-conditional-exports-audit.md b/doc/audit/platform-conditional-exports-audit.md new file mode 100644 index 000000000..8b82e00c0 --- /dev/null +++ b/doc/audit/platform-conditional-exports-audit.md @@ -0,0 +1,287 @@ +# Platform Conditional Exports Audit Report + +**Project**: PrivacyGUI +**Date**: 2026-01-09 +**Updated**: 2026-01-09T20:01 +**Author**: Antigravity Agent + +--- + +## Executive Summary + +This audit analyzes the PrivacyGUI project to identify platform-specific code that requires Conditional Exports (Stub Pattern) for proper cross-platform (Web/Native) support. + +### Key Findings + +| Category | Count | Status | +|----------|-------|--------| +| ✅ **Fully Encapsulated (Entry Point Pattern)** | 9 groups | Compliant | +| ⚠️ **Uses `dart:io` I/O Operations (Needs Stub)** | 4 files | Needs Refactoring | +| ✅ **Uses `dart:io` Constants Only** | 10+ files | No Action Needed | +| 🔶 **Runtime Platform Check Dependencies** | 7+ files | Acceptable | + +> [!IMPORTANT] +> **Correction (2026-01-09)**: Previously identified `HttpHeaders.*` and `HttpStatus.*` usage from `dart:io` as requiring refactoring. After verification, `flutter build web` succeeds without errors. Dart SDK provides stub implementations for `dart:io` constants on Web, so files using only constants (not actual I/O operations) do **not** require changes. + +--- + +## Problem Statement + +- **`dart:io`** is not fully available on Web, but the Dart SDK provides stubs for constants +- **`dart:html`** cannot be used in Native builds +- **Actual I/O operations** (File, Socket, InternetAddress) throw errors on Web + +### When to Use Conditional Exports + +| Usage | Needs Stub Pattern? | +|-------|---------------------| +| `HttpHeaders.authorizationHeader` (constant) | ❌ No - SDK provides stub | +| `HttpStatus.ok` (constant) | ❌ No - SDK provides stub | +| `File.writeAsBytes()` (I/O operation) | ✅ Yes | +| `InternetAddress.lookup()` (I/O operation) | ✅ Yes | +| `Platform.isIOS` (platform check) | ⚠️ Depends on usage | + +--- + +## Part 1: Fully Encapsulated Implementations ✅ + +These modules have a proper entry point file that hides the conditional import logic. + +### 1.1 gRPC Transport Factory (usp_client_core) ✅ +**Location**: `packages/usp_client_core/lib/src/grpc_creator/` + +| File | Purpose | +|------|---------| +| [grpc_creator.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/packages/usp_client_core/lib/src/grpc_creator/grpc_creator.dart) | **Entry Point** | +| [transport_factory_stub.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/packages/usp_client_core/lib/src/grpc_creator/transport_factory_stub.dart) | Stub | +| [transport_factory_io.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/packages/usp_client_core/lib/src/grpc_creator/transport_factory_io.dart) | Native | +| [transport_factory_web.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/packages/usp_client_core/lib/src/grpc_creator/transport_factory_web.dart) | Web | + +### 1.2 HTTP Client Factory ✅ +**Location**: `lib/core/http/` + +| File | Purpose | +|------|---------| +| [linksys_http_client.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/http/linksys_http_client.dart) | **Entry Point** | +| [client/get_client.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/http/client/get_client.dart) | Stub | +| [client/mobile_client.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/http/client/mobile_client.dart) | Native | +| [client/web_client.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/http/client/web_client.dart) | Web | + +### 1.3 Cache Manager Factory ✅ +**Location**: `lib/core/cache/` + +| File | Purpose | +|------|---------| +| [linksys_cache_manager.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cache/linksys_cache_manager.dart) | **Entry Point** | +| [cache_manager_base.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cache/cache_manager_base.dart) | Stub | +| [cache_manager_mobile.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cache/cache_manager_mobile.dart) | Native | +| [cache_manager_web.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cache/cache_manager_web.dart) | Web | + +### 1.4 IP Getter ✅ `[NEW - 2026-01-09]` +**Location**: `lib/core/utils/ip_getter/` + +| File | Purpose | +|------|---------| +| [ip_getter.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/ip_getter/ip_getter.dart) | **Entry Point** | +| [get_local_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/ip_getter/get_local_ip.dart) | Stub | +| [mobile_get_local_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/ip_getter/mobile_get_local_ip.dart) | Native | +| [web_get_local_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/ip_getter/web_get_local_ip.dart) | Web | + +### 1.5 URL Helper ✅ `[NEW - 2026-01-09]` +**Location**: `lib/util/url_helper/` + +| File | Purpose | +|------|---------| +| [url_helper.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/url_helper/url_helper.dart) | **Entry Point** | +| [url_helper_stub.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/url_helper/url_helper_stub.dart) | Stub | +| [url_helper_mobile.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/url_helper/url_helper_mobile.dart) | Native | +| [url_helper_web.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/url_helper/url_helper_web.dart) | Web | + +### 1.6 Export Selector ✅ `[NEW - 2026-01-09]` +**Location**: `lib/util/export_selector/` + +| File | Purpose | +|------|---------| +| [export_selector.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/export_selector/export_selector.dart) | **Entry Point** | +| [export_base.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/export_selector/export_base.dart) | Stub | +| [export_mobile.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/export_selector/export_mobile.dart) | Native | +| [export_web.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/export_selector/export_web.dart) | Web | + +### 1.7 Get Log Selector ✅ `[NEW - 2026-01-09]` +**Location**: `lib/util/get_log_selector/` + +| File | Purpose | +|------|---------| +| [get_log_selector.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/get_log_selector/get_log_selector.dart) | **Entry Point** | +| [get_log_base.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/get_log_selector/get_log_base.dart) | Stub | +| [get_log_mobile.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/get_log_selector/get_log_mobile.dart) | Native | +| [get_log_web.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/util/get_log_selector/get_log_web.dart) | Web | + +### 1.8 Client Type Constants ✅ `[NEW - 2026-01-09]` +**Location**: `lib/constants/client_type/` + +| File | Purpose | +|------|---------| +| [client_type.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/constants/client_type/client_type.dart) | **Entry Point** | +| [get_client_type.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/constants/client_type/get_client_type.dart) | Stub | +| [mobile_client_type.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/constants/client_type/mobile_client_type.dart) | Native | +| [web_client_type.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/constants/client_type/web_client_type.dart) | Web | + +### 1.9 Assign IP ✅ `[NEW - 2026-01-09]` +**Location**: `lib/core/utils/assign_ip/` + +| File | Purpose | +|------|---------| +| [assign_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/assign_ip/assign_ip.dart) | **Entry Point** | +| [base_assign_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/assign_ip/base_assign_ip.dart) | Stub | +| [mobile_assign_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/assign_ip/mobile_assign_ip.dart) | Native (no-op) | +| [web_assign_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/assign_ip/web_assign_ip.dart) | Web | + +--- + +## Part 2: Files Using `dart:io` I/O Operations (May Need Attention) ⚠️ + +These files use actual I/O operations from `dart:io` that may not work on Web: + +| File | I/O Operations Used | Status | +|------|---------------------|--------| +| [logger.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/logger.dart) | `File.writeAsBytes()`, `stdout.supportsAnsiEscapes` | ⚠️ Guarded by `kIsWeb` | +| [storage.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/storage.dart) | `File`, `Directory` | ⚠️ Guarded by `kIsWeb` | +| [mixin.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/providers/connectivity/mixin.dart) | `InternetAddress.lookup()` | ⚠️ Guarded by `kIsWeb` | +| [main.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/main.dart) | `HttpOverrides.global` | ✅ Guarded by `!kIsWeb` | + +> [!NOTE] +> These files are already protected by `kIsWeb` runtime checks, so they work correctly. Consider migrating to Stub Pattern for cleaner architecture if desired. + +--- + +## Part 3: Files Using `dart:io` Constants Only ✅ NO ACTION NEEDED + +These files import `dart:io` but only use **constants** (not I/O operations). The Dart SDK provides stub implementations for these constants on Web, so **no changes are required**. + +| File | Constants Used | +|------|----------------| +| [authorization_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/authorization_service.dart) | `HttpHeaders.authorizationHeader`, `HttpHeaders.contentTypeHeader` | +| [device_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/device_service.dart) | `HttpHeaders.authorizationHeader` | +| [event_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/event_service.dart) | `HttpHeaders.authorizationHeader` | +| [user_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/user_service.dart) | `HttpHeaders.authorizationHeader` | +| [remote_assistance_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/remote_assistance_service.dart) | `HttpHeaders.authorizationHeader` | +| [asset_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/asset_service.dart) | `HttpHeaders.*` | +| [ping_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/ping_service.dart) | `HttpStatus.*` | +| [guardians_remote_assistance_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/guardians_remote_assistance_service.dart) | `HttpHeaders.*` | +| [linksys_cloud_repository.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_cloud_repository.dart) | `HttpStatus.ok`, `HttpStatus.noContent` | +| [router_repository.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/jnap/router_repository.dart) | `HttpHeaders.*`, `HttpStatus.*` | +| [base_http_command.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/jnap/command/http/base_http_command.dart) | `HttpStatus.*` | +| [linksys_http_client.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/http/linksys_http_client.dart) | `HttpHeaders.*`, `ContentType.*` | + +--- + +## Part 4: Special Cases + +### 4.1 smart_device_service.dart + +| File | Issue | +|------|-------| +| [smart_device_service.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/cloud/linksys_requests/smart_device_service.dart) | Uses `Platform.isIOS` for `tokenType` | + +This file uses `Platform.isIOS` to determine push notification token type ('APNS' vs 'GCM'). Since this is mobile-specific functionality (push notifications), it may not be used on Web at all. **No action needed** if this code path is not executed on Web. + +### 4.2 Assign IP (Incomplete Pattern) +**Location**: `lib/core/utils/assign_ip/` + +| File | Status | +|------|--------| +| [base_assign_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/assign_ip/base_assign_ip.dart) | ⚠️ Missing entry point | +| [web_assign_ip.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/utils/assign_ip/web_assign_ip.dart) | ⚠️ Missing native impl | + +> [!WARNING] +> Missing `mobile_assign_ip.dart` and conditional export entry point. Low priority if not actively used. + +--- + +## Part 5: Files Using `kIsWeb` Runtime Checks ✅ + +These files use runtime platform detection, which is an acceptable pattern for UI/behavior branching: + +| File | Usage | +|------|-------| +| [build_config.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/constants/build_config.dart) | `!kIsWeb` for debug panel | +| [app.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/app.dart) | `kIsWeb` for page transitions | +| [router_repository.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/core/jnap/router_repository.dart) | `kIsWeb` for URL building | +| [connectivity_provider.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/providers/connectivity/connectivity_provider.dart) | `!kIsWeb` for connectivity | +| [local_network_settings_view.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/page/advanced_settings/local_network_settings/views/local_network_settings_view.dart) | `kIsWeb` for redirect | +| [internet_settings_view.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/page/advanced_settings/internet_settings/views/internet_settings_view.dart) | `kIsWeb` for redirect | +| [dashboard_menu_view.dart](file:///Users/austin.chang/flutter-workspaces/privacyGUI/PrivacyGUI/lib/page/dashboard/views/dashboard_menu_view.dart) | `kIsWeb` for menu options | + +> [!TIP] +> Runtime `kIsWeb` checks are an acceptable pattern and do not require refactoring to Stub Pattern. + +--- + +## Part 6: Verification Checklist + +| Check | Status | +|-------|--------| +| `flutter build web` completes without errors | ✅ Verified | +| `flutter analyze` passes | ✅ Verified | +| Consumers only import entry point files | ✅ Phase 1 Complete | +| All new entry points have documentation | ✅ Complete | + +--- + +## Appendix A: Change Log + +### 2026-01-09T20:01 - Analysis Correction + +**Correction**: Removed `HttpHeaders.*` and `HttpStatus.*` from "needs refactoring" list. After verifying `flutter build web` succeeds, confirmed that Dart SDK provides stub implementations for `dart:io` constants on Web. Only actual I/O operations require Stub Pattern. + +### 2026-01-09T19:50 - Phase 1 Completed + +**New Entry Point Files Created**: +- `lib/core/utils/ip_getter/ip_getter.dart` +- `lib/util/url_helper/url_helper.dart` +- `lib/util/url_helper/url_helper_stub.dart` +- `lib/util/export_selector/export_selector.dart` +- `lib/util/get_log_selector/get_log_selector.dart` +- `lib/constants/client_type/client_type.dart` +- `lib/core/utils/assign_ip/assign_ip.dart` +- `lib/core/utils/assign_ip/mobile_assign_ip.dart` + +**Consumer Files Updated** (17 files): +- `lib/core/jnap/router_repository.dart` +- `lib/core/cloud/linksys_cloud_repository.dart` +- `lib/core/cloud/linksys_device_cloud_service.dart` +- `lib/route/router_provider.dart` +- `lib/page/instant_admin/providers/manual_firmware_update_provider.dart` +- `lib/constants/url_links.dart` +- `lib/page/health_check/widgets/speed_test_external_widget.dart` +- `lib/page/health_check/views/speed_test_external.dart` +- `lib/page/dashboard/views/components/widgets/parts/external_speed_test_links.dart` +- `lib/page/advanced_settings/internet_settings/widgets/wan_forms/bridge_form.dart` +- `lib/utils.dart` +- `lib/page/dashboard/views/components/widgets/parts/wifi_card.dart` +- `lib/constants/cloud_const.dart` +- `lib/page/dashboard/views/dashboard_home_view.dart` +- `lib/page/advanced_settings/local_network_settings/views/local_network_settings_view.dart` +- `lib/page/advanced_settings/internet_settings/views/internet_settings_view.dart` + +**Branch**: `austin/platform-conditional-exports-encapsulation` + +--- + +## Appendix B: Files Excluded from Analysis + +The following files import `dart:io` but are **test/tooling scripts** (not part of production build): + +- `test_scripts/grep_loc_fils.dart` +- `test_scripts/test_result_parser.dart` +- `test_scripts/combine_results.dart` +- `test/common/theme_data.dart` +- `tools/generate_screenshot_test_cases_report.dart` +- `tools/delete_mockito_mocks.dart` +- `tools/remove_unused_strings.dart` +- `tools/run_screenshot_tests.dart` + +--- + +*End of Audit Report* diff --git a/doc/audit/service-decoupling-audit.md b/doc/audit/service-decoupling-audit.md new file mode 100644 index 000000000..aa614d7b4 --- /dev/null +++ b/doc/audit/service-decoupling-audit.md @@ -0,0 +1,259 @@ +# Service Decoupling Audit Report + +**Generated**: 2026-01-09 +**Project**: PrivacyGUI +**Purpose**: Document JNAP coupling status for future USP/TR migration + +--- + +## Executive Summary + +| Metric | Value | +|--------|-------| +| Total Service Files | 53 | +| Services with JNAP Dependency | 34 (64%) | +| RouterRepository References | 85 | +| Domain Models (JNAP) | 54 | +| Unique JNAP Actions Used | 110+ | +| **Architecture Violations** | **32** | + +**Current Status**: 🔴 **High Coupling** — Most services directly depend on JNAP-specific types. + +--- + +## ⚠️ Architecture Compliance Violations + +The following sections document violations of the **Provider → Service → Repository** architecture pattern. + +### RouterRepository Usage Outside Services (8 files) + +These files directly access `routerRepositoryProvider` instead of going through a Service: + +| File | Layer | Severity | +|------|-------|----------| +| `lib/page/advanced_settings/local_network_settings/views/local_network_settings_view.dart` | View | 🔴 High | +| `lib/page/dashboard/views/prepare_dashboard_view.dart` | View | 🔴 High | +| `lib/page/ai_assistant/views/router_assistant_view.dart` | View | 🔴 High | +| `lib/page/instant_setup/troubleshooter/views/pnp_no_internet_connection_view.dart` | View | 🔴 High | +| `lib/page/select_network/providers/select_network_provider.dart` | Provider | 🟡 Medium | +| `lib/page/vpn/providers/vpn_notifier.dart` | Provider | 🟡 Medium | +| `lib/page/wifi_settings/providers/channelfinder_provider.dart` | Provider | 🟡 Medium | +| `lib/page/instant_setup/troubleshooter/providers/_providers.dart` | Provider | 🟡 Medium | + +### JNAPAction Usage Outside Services (3 files) + +These files directly reference `JNAPAction` enum: + +| File | Violation | Code Example | +|------|-----------|--------------| +| `select_network_provider.dart` | Direct JNAP call | `JNAPAction.isAdminPasswordDefault` | +| `prepare_dashboard_view.dart` | Direct JNAP call | `JNAPAction.getDeviceInfo` | +| `vpn_service.dart` | In service (acceptable) | - | + +### JNAP Models Imported in Views/Providers (24 files) + +Files that import `jnap/models/*` or `jnap/result/*` outside the Service layer: + +**Views (14 files)**: +| File | Models Used | +|------|-------------| +| `dmz_settings_view.dart` | DMZ models | +| `internet_settings_view.dart` | WAN settings | +| `local_network_settings_view.dart` | LAN settings | +| `dashboard_home_view.dart` | Device info | +| `prepare_dashboard_view.dart` | Device info | +| `firmware_update_process_view.dart` | Firmware status | +| `instant_admin_view.dart` | Time settings | +| `node_detail_view.dart` | Node models | +| `instant_topology_view.dart` | Topology models | +| `instant_verify_view.dart` | Verify models | +| `login_local_view.dart` | Auth models | +| `pnp_*_view.dart` | ISP settings | + +**Providers (10 files)**: +| File | Models Used | +|------|-------------| +| `node_light_settings_provider.dart` | LED settings | +| `channelfinder_provider.dart` | Radio info | +| `wifi_bundle_provider.dart` | WiFi settings | +| `select_network_provider.dart` | Network models | +| `wan_external_provider.dart` | WAN status | +| Others... | Various | + +### Compliance Summary + +| Violation Type | Count | Impact | +|----------------|-------|--------| +| **RouterRepository in Views** | 4 | 🔴 High - Direct protocol dependency | +| **RouterRepository in Providers** | 4 | 🟡 Medium - Should use Services | +| **JNAPAction in non-Services** | 2 | 🔴 High - Protocol leakage | +| **JNAP Models in Views** | 14 | 🟡 Medium - Model coupling | +| **JNAP Models in Providers** | 10 | 🟡 Medium - Model coupling | +| **Total Violations** | **34** | - | + +### Recommended Fixes + +1. **Views should NOT directly use RouterRepository** + - Create/use appropriate Services for these operations + - Pass data through Providers + +2. **Providers should use Services, not RouterRepository** + - `VpnNotifier` should use `VpnService` + - `ChannelFinderProvider` should use `ChannelFinderService` + +3. **Consider Domain Models separate from JNAP Models** + - Create UI-specific models in `lib/page/**/models/` + - Transform JNAP models to domain models in Services + +--- + +## Service Inventory + +### Core Services (`lib/core/data/services/`) + +| Service | JNAP Coupled | Primary Functions | +|---------|--------------|-------------------| +| `polling_service.dart` | 🔴 Yes | Core data polling, transaction building | +| `dashboard_manager_service.dart` | 🔴 Yes | Dashboard state, device info | +| `device_manager_service.dart` | 🔴 Yes | Device CRUD, backhaul info | +| `firmware_update_service.dart` | 🔴 Yes | Firmware check/update | + +### Feature Services (`lib/page/**/services/`) + +| Category | Services | JNAP Coupled | +|----------|----------|--------------| +| **WiFi Settings** | `wifi_settings_service.dart`, `channel_finder_service.dart` | 🔴 Yes | +| **Network Settings** | `local_network_settings_service.dart`, `internet_settings_service.dart` | 🔴 Yes | +| **Security** | `firewall_settings_service.dart`, `dmz_settings_service.dart` | 🔴 Yes | +| **Instant Features** | `instant_privacy_service.dart`, `instant_safety_service.dart`, `instant_verify_service.dart`, `instant_topology_service.dart` | 🔴 Yes | +| **Administration** | `administration_settings_service.dart`, `router_password_service.dart`, `timezone_service.dart`, `power_table_service.dart` | 🔴 Yes | +| **Advanced Settings** | `static_routing_service.dart`, `ddns_service.dart`, port services | 🔴 Yes | +| **Nodes** | `node_detail_service.dart`, `add_nodes_service.dart`, `add_wired_nodes_service.dart`, `node_light_settings_service.dart` | 🔴 Yes | +| **Health Check** | `health_check_service.dart` | 🔴 Yes | +| **Setup** | `pnp_service.dart`, `pnp_isp_service.dart`, `auto_parent_first_login_service.dart` | 🔴 Yes | + +### Non-JNAP Services (Cloud/Auth) + +| Service | Purpose | +|---------|---------| +| `auth_service.dart` | Authentication (uses JNAP for local login) | +| `connectivity_service.dart` | Network connectivity check | +| Cloud services (`lib/core/cloud/`) | Linksys Cloud API (separate protocol) | + +--- + +## JNAP Action Usage (Top 20) + +| Action | Usage Count | Used By Services | +|--------|-------------|------------------| +| `getGuestRadioSettings` | 10 | wifi_settings, polling | +| `getLANSettings` | 9 | local_network_settings, internet_settings | +| `getWANStatus` | 8 | polling, dashboard, instant_verify | +| `getRadioInfo` | 8 | wifi_settings, polling, dashboard | +| `getDevices` | 8 | device_manager, polling | +| `getDeviceInfo` | 8 | dashboard, polling, side_effect | +| `getFirmwareUpdateSettings` | 6 | firmware_update, polling | +| `setFirmwareUpdateSettings` | 4 | firmware_update | +| `reboot` | 4 | administration, pnp | +| `getMACFilterSettings` | 4 | wifi_settings | +| `getInternetConnectionStatus` | 4 | polling, pnp | +| `getBackhaulInfo` | 4 | device_manager, polling | +| `factoryReset` | 4 | administration | + +--- + +## Service Contracts Summary + +### Core Read Operations + +| Domain | Operation | JNAP Action | USP Equivalent (TBD) | +|--------|-----------|-------------|----------------------| +| Device | Get device info | `getDeviceInfo` | `Device.DeviceInfo.` | +| Device | Get device list | `getDevices` | `Device.Hosts.Host.` | +| Network | Get WAN status | `getWANStatus` | `Device.IP.Interface.` | +| WiFi | Get radio info | `getRadioInfo` | `Device.WiFi.Radio.` | +| WiFi | Get guest settings | `getGuestRadioSettings` | `Device.WiFi.SSID.` | +| System | Get system stats | `getSystemStats` | TBD | + +### Core Write Operations + +| Domain | Operation | JNAP Action | Side Effects | +|--------|-----------|-------------|--------------| +| Device | Set device name | `setDeviceProperties` | None | +| WiFi | Set radio settings | `setRadioSettings` | WiFi restart | +| System | Reboot | `reboot` | Device restart | +| System | Factory reset | `factoryReset` | Device restart | +| Firmware | Start update | `updateFirmwareNow` | Device restart | + +--- + +## Migration Readiness + +### Ready for Migration (After Protocol Defined) +- Services with clean separation between JNAP calls and business logic +- Services using `RouterRepository` through dependency injection + +### Requires Refactoring +- Services with inline JNAP action handling +- Services with complex transaction building logic + +### Special Considerations +- **Polling**: Batch transaction pattern may differ in USP +- **Side Effects**: Device restart handling needs protocol-agnostic abstraction +- **Real-time Updates**: USP supports WebSocket subscriptions + +--- + +## Recommendations + +### Short Term (Now) +1. ✅ Document all service contracts (this report) +2. Keep new services clean with single responsibility +3. Avoid spreading JNAP dependencies to Providers + +### Medium Term (When USP Spec Available) +1. Review USP data model mapping +2. Identify common vs protocol-specific operations +3. Design protocol adapter interface based on actual needs + +### Long Term (Migration) +1. Implement `UspAdapter` alongside `JnapAdapter` +2. Migrate services one by one with feature flags +3. Maintain parallel support during transition period + +--- + +## Appendix: Service File Locations + +### Core Services +``` +lib/core/data/services/ +├── polling_service.dart +├── dashboard_manager_service.dart +├── device_manager_service.dart +└── firmware_update_service.dart +``` + +### Feature Services +``` +lib/page/ +├── advanced_settings/ +│ ├── administration/services/ +│ ├── apps_and_gaming/ddns/services/ +│ ├── apps_and_gaming/ports/services/ +│ ├── dmz/services/ +│ ├── firewall/services/ +│ ├── internet_settings/services/ +│ ├── local_network_settings/services/ +│ └── static_routing/services/ +├── health_check/services/ +├── instant_admin/services/ +├── instant_privacy/services/ +├── instant_safety/services/ +├── instant_setup/services/ +├── instant_topology/services/ +├── instant_verify/services/ +├── login/auto_parent/services/ +├── nodes/services/ +└── wifi_settings/services/ +``` diff --git a/lib/constants/client_type/client_type.dart b/lib/constants/client_type/client_type.dart new file mode 100644 index 000000000..e0a3492e3 --- /dev/null +++ b/lib/constants/client_type/client_type.dart @@ -0,0 +1,17 @@ +/// Client Type - Cross-platform client type constants. +/// +/// This library provides platform-aware client type identification. +/// Consumers only need to import this file: +/// +/// ```dart +/// import 'package:privacy_gui/constants/client_type/client_type.dart'; +/// +/// final type = clientType; // automatically returns correct platform value +/// ``` +/// +/// The correct platform implementation is automatically selected at compile time. +library; + +export 'get_client_type.dart' + if (dart.library.io) 'mobile_client_type.dart' + if (dart.library.html) 'web_client_type.dart'; diff --git a/lib/constants/cloud_const.dart b/lib/constants/cloud_const.dart index 8f2ea0c21..ffa125605 100644 --- a/lib/constants/cloud_const.dart +++ b/lib/constants/cloud_const.dart @@ -1,8 +1,6 @@ import 'build_config.dart'; -import 'client_type/get_client_type.dart' - if (dart.library.io) 'client_type/mobile_client_type.dart' - if (dart.library.html) 'client_type/web_client_type.dart'; +import 'client_type/client_type.dart'; const kCloudBase = 'CLOUD_BASE_URL'; const kCloudJNAP = 'CLOUD_JNAP_BASE_URL'; diff --git a/lib/constants/url_links.dart b/lib/constants/url_links.dart index 28d09a291..76c827570 100644 --- a/lib/constants/url_links.dart +++ b/lib/constants/url_links.dart @@ -1,9 +1,7 @@ import 'dart:ui'; import 'package:privacy_gui/core/utils/logger.dart'; -import 'package:privacy_gui/util/url_helper/url_helper.dart' - if (dart.library.io) 'package:privacy_gui/util/url_helper/url_helper_mobile.dart' - if (dart.library.html) 'package:privacy_gui/util/url_helper/url_helper_web.dart'; +import 'package:privacy_gui/util/url_helper/url_helper.dart'; const officialWebHost = 'https://store.linksys.com'; const officialSupportHost = 'https://support.linksys.com'; diff --git a/lib/core/cloud/linksys_cloud_repository.dart b/lib/core/cloud/linksys_cloud_repository.dart index 860d6a0aa..b23a60bba 100644 --- a/lib/core/cloud/linksys_cloud_repository.dart +++ b/lib/core/cloud/linksys_cloud_repository.dart @@ -24,9 +24,7 @@ import 'package:privacy_gui/core/cloud/model/cloud_communication_method.dart'; import 'package:privacy_gui/core/cloud/model/cloud_network_model.dart'; import 'package:privacy_gui/core/cloud/model/cloud_session_model.dart'; import 'package:privacy_gui/providers/connectivity/_connectivity.dart'; -import 'package:privacy_gui/core/utils/ip_getter/get_local_ip.dart' - if (dart.library.io) 'package:privacy_gui/core/utils/ip_getter/mobile_get_local_ip.dart' - if (dart.library.html) 'package:privacy_gui/core/utils/ip_getter/web_get_local_ip.dart'; +import 'package:privacy_gui/core/utils/ip_getter/ip_getter.dart'; final cloudRepositoryProvider = Provider((ref) => LinksysCloudRepository( httpClient: LinksysHttpClient(getHost: () { diff --git a/lib/core/cloud/linksys_device_cloud_service.dart b/lib/core/cloud/linksys_device_cloud_service.dart index 7f783d5d9..627f49ae0 100644 --- a/lib/core/cloud/linksys_device_cloud_service.dart +++ b/lib/core/cloud/linksys_device_cloud_service.dart @@ -13,9 +13,7 @@ import 'package:privacy_gui/core/utils/devices.dart'; import 'package:privacy_gui/core/utils/logger.dart'; import 'package:privacy_gui/providers/connectivity/connectivity_info.dart'; import 'package:privacy_gui/providers/connectivity/connectivity_provider.dart'; -import 'package:privacy_gui/core/utils/ip_getter/get_local_ip.dart' - if (dart.library.io) 'package:privacy_gui/core/utils/ip_getter/mobile_get_local_ip.dart' - if (dart.library.html) 'package:privacy_gui/core/utils/ip_getter/web_get_local_ip.dart'; +import 'package:privacy_gui/core/utils/ip_getter/ip_getter.dart'; final deviceCloudServiceProvider = Provider((ref) => DeviceCloudService( httpClient: LinksysHttpClient(getHost: () { diff --git a/lib/core/jnap/router_repository.dart b/lib/core/jnap/router_repository.dart index 632c2ad4e..266dff7f0 100644 --- a/lib/core/jnap/router_repository.dart +++ b/lib/core/jnap/router_repository.dart @@ -27,9 +27,7 @@ import 'package:privacy_gui/core/data/providers/side_effect_provider.dart'; import 'package:privacy_gui/core/utils/logger.dart'; import 'package:privacy_gui/utils.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:privacy_gui/core/utils/ip_getter/get_local_ip.dart' - if (dart.library.io) 'package:privacy_gui/core/utils/ip_getter/mobile_get_local_ip.dart' - if (dart.library.html) 'package:privacy_gui/core/utils/ip_getter/web_get_local_ip.dart'; +import 'package:privacy_gui/core/utils/ip_getter/ip_getter.dart'; enum CommandType { remote, diff --git a/lib/core/utils/assign_ip/assign_ip.dart b/lib/core/utils/assign_ip/assign_ip.dart new file mode 100644 index 000000000..2df54f116 --- /dev/null +++ b/lib/core/utils/assign_ip/assign_ip.dart @@ -0,0 +1,19 @@ +/// Assign IP - Cross-platform web location manipulation. +/// +/// This library provides platform-aware web location functions. +/// Consumers only need to import this file: +/// +/// ```dart +/// import 'package:privacy_gui/core/utils/assign_ip/assign_ip.dart'; +/// +/// assignWebLocation('https://new-host.local'); +/// ``` +/// +/// The correct platform implementation is automatically selected at compile time. +/// - Web: Uses `window.location` APIs +/// - Native: No-op (these operations are web-specific) +library; + +export 'base_assign_ip.dart' + if (dart.library.io) 'mobile_assign_ip.dart' + if (dart.library.html) 'web_assign_ip.dart'; diff --git a/lib/core/utils/assign_ip/mobile_assign_ip.dart b/lib/core/utils/assign_ip/mobile_assign_ip.dart new file mode 100644 index 000000000..fb4b9aa34 --- /dev/null +++ b/lib/core/utils/assign_ip/mobile_assign_ip.dart @@ -0,0 +1,14 @@ +/// Mobile implementation of assign_ip functions. +/// These are no-op on native platforms as they are web-specific operations. + +void assignWebLocation(String url) { + // No-op on native - this is a web-specific operation +} + +void updateWebHost(String host) { + // No-op on native - this is a web-specific operation +} + +void reload() { + // No-op on native - this is a web-specific operation +} diff --git a/lib/core/utils/ip_getter/ip_getter.dart b/lib/core/utils/ip_getter/ip_getter.dart new file mode 100644 index 000000000..24bfe5571 --- /dev/null +++ b/lib/core/utils/ip_getter/ip_getter.dart @@ -0,0 +1,17 @@ +/// IP Getter - Cross-platform local IP address retrieval. +/// +/// This library provides platform-aware IP address retrieval functions. +/// Consumers only need to import this file: +/// +/// ```dart +/// import 'package:privacy_gui/core/utils/ip_getter/ip_getter.dart'; +/// +/// final ip = getLocalIp(ref); +/// ``` +/// +/// The correct platform implementation is automatically selected at compile time. +library; + +export 'get_local_ip.dart' + if (dart.library.io) 'mobile_get_local_ip.dart' + if (dart.library.html) 'web_get_local_ip.dart'; diff --git a/lib/page/advanced_settings/internet_settings/views/internet_settings_view.dart b/lib/page/advanced_settings/internet_settings/views/internet_settings_view.dart index a0b839b57..ee321b0ca 100644 --- a/lib/page/advanced_settings/internet_settings/views/internet_settings_view.dart +++ b/lib/page/advanced_settings/internet_settings/views/internet_settings_view.dart @@ -22,8 +22,7 @@ import 'package:privacy_gui/page/components/views/arguments_view.dart'; import 'package:privacy_gui/providers/redirection/redirection_provider.dart'; import 'package:privacy_gui/util/error_code_helper.dart'; import 'package:ui_kit_library/ui_kit.dart'; -import 'package:privacy_gui/core/utils/assign_ip/base_assign_ip.dart' - if (dart.library.html) 'package:privacy_gui/core/utils/assign_ip/web_assign_ip.dart'; +import 'package:privacy_gui/core/utils/assign_ip/assign_ip.dart'; enum InternetSettingsViewType { ipv4, diff --git a/lib/page/advanced_settings/internet_settings/widgets/wan_forms/bridge_form.dart b/lib/page/advanced_settings/internet_settings/widgets/wan_forms/bridge_form.dart index f106fd2c2..e3286dd14 100644 --- a/lib/page/advanced_settings/internet_settings/widgets/wan_forms/bridge_form.dart +++ b/lib/page/advanced_settings/internet_settings/widgets/wan_forms/bridge_form.dart @@ -4,9 +4,7 @@ import 'package:privacy_gui/localization/localization_hook.dart'; import 'package:privacy_gui/page/advanced_settings/internet_settings/providers/internet_settings_provider.dart'; import 'package:privacy_gui/page/advanced_settings/internet_settings/widgets/wan_forms/base_wan_form.dart'; import 'package:ui_kit_library/ui_kit.dart'; -import 'package:privacy_gui/util/url_helper/url_helper.dart' - if (dart.library.io) 'package:privacy_gui/util/url_helper/url_helper_mobile.dart' - if (dart.library.html) 'package:privacy_gui/util/url_helper/url_helper_web.dart'; +import 'package:privacy_gui/util/url_helper/url_helper.dart'; class BridgeForm extends BaseWanForm { const BridgeForm({ diff --git a/lib/page/advanced_settings/local_network_settings/views/local_network_settings_view.dart b/lib/page/advanced_settings/local_network_settings/views/local_network_settings_view.dart index 765600e9d..865aa0592 100644 --- a/lib/page/advanced_settings/local_network_settings/views/local_network_settings_view.dart +++ b/lib/page/advanced_settings/local_network_settings/views/local_network_settings_view.dart @@ -18,8 +18,7 @@ import 'package:privacy_gui/page/advanced_settings/local_network_settings/provid import 'package:privacy_gui/page/instant_safety/providers/instant_safety_provider.dart'; import 'package:privacy_gui/providers/redirection/redirection_provider.dart'; import 'package:ui_kit_library/ui_kit.dart'; -import 'package:privacy_gui/core/utils/assign_ip/base_assign_ip.dart' - if (dart.library.html) 'package:privacy_gui/core/utils/assign_ip/web_assign_ip.dart'; +import 'package:privacy_gui/core/utils/assign_ip/assign_ip.dart'; class LocalNetworkSettingsView extends ArgumentsConsumerStatefulView { const LocalNetworkSettingsView({ diff --git a/lib/page/dashboard/views/components/widgets/parts/external_speed_test_links.dart b/lib/page/dashboard/views/components/widgets/parts/external_speed_test_links.dart index 6eccdcfbb..e0a813033 100644 --- a/lib/page/dashboard/views/components/widgets/parts/external_speed_test_links.dart +++ b/lib/page/dashboard/views/components/widgets/parts/external_speed_test_links.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:privacy_gui/localization/localization_hook.dart'; import 'package:privacy_gui/page/dashboard/providers/dashboard_home_state.dart'; -import 'package:privacy_gui/util/url_helper/url_helper.dart' - if (dart.library.io) 'package:privacy_gui/util/url_helper/url_helper_mobile.dart' - if (dart.library.html) 'package:privacy_gui/util/url_helper/url_helper_web.dart'; +import 'package:privacy_gui/util/url_helper/url_helper.dart'; import 'package:ui_kit_library/ui_kit.dart'; /// Widget for external speed test links (Fast.com, Cloudflare). diff --git a/lib/page/dashboard/views/components/widgets/parts/wifi_card.dart b/lib/page/dashboard/views/components/widgets/parts/wifi_card.dart index dbfdad306..6e9e552ad 100644 --- a/lib/page/dashboard/views/components/widgets/parts/wifi_card.dart +++ b/lib/page/dashboard/views/components/widgets/parts/wifi_card.dart @@ -11,9 +11,7 @@ import 'package:privacy_gui/page/wifi_settings/providers/wifi_bundle_provider.da import 'package:privacy_gui/route/constants.dart'; import 'package:privacy_gui/util/qr_code.dart'; import 'package:privacy_gui/util/wifi_credential.dart'; -import 'package:privacy_gui/util/export_selector/export_base.dart' - if (dart.library.io) 'package:privacy_gui/util/export_selector/export_mobile.dart' - if (dart.library.html) 'package:privacy_gui/util/export_selector/export_web.dart'; +import 'package:privacy_gui/util/export_selector/export_selector.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:ui_kit_library/ui_kit.dart'; diff --git a/lib/page/dashboard/views/dashboard_home_view.dart b/lib/page/dashboard/views/dashboard_home_view.dart index dcf7a6a63..41f57ad5a 100644 --- a/lib/page/dashboard/views/dashboard_home_view.dart +++ b/lib/page/dashboard/views/dashboard_home_view.dart @@ -13,8 +13,7 @@ import 'package:privacy_gui/page/dashboard/_dashboard.dart'; import 'package:privacy_gui/page/dashboard/views/components/_components.dart'; import 'package:privacy_gui/page/dashboard/strategies/custom_dashboard_layout_strategy.dart'; import 'package:privacy_gui/page/vpn/views/vpn_status_tile.dart'; -import 'package:privacy_gui/core/utils/assign_ip/base_assign_ip.dart' - if (dart.library.html) 'package:privacy_gui/core/utils/assign_ip/web_assign_ip.dart'; +import 'package:privacy_gui/core/utils/assign_ip/assign_ip.dart'; import 'package:shared_preferences/shared_preferences.dart'; class DashboardHomeView extends ConsumerStatefulWidget { diff --git a/lib/page/health_check/views/speed_test_external.dart b/lib/page/health_check/views/speed_test_external.dart index c46417657..5deb79a8e 100644 --- a/lib/page/health_check/views/speed_test_external.dart +++ b/lib/page/health_check/views/speed_test_external.dart @@ -2,9 +2,7 @@ import 'package:flutter/material.dart'; import 'package:privacy_gui/localization/localization_hook.dart'; import 'package:privacy_gui/page/components/ui_kit_page_view.dart'; import 'package:ui_kit_library/ui_kit.dart'; -import 'package:privacy_gui/util/url_helper/url_helper.dart' - if (dart.library.io) 'package:privacy_gui/util/url_helper/url_helper_mobile.dart' - if (dart.library.html) 'package:privacy_gui/util/url_helper/url_helper_web.dart'; +import 'package:privacy_gui/util/url_helper/url_helper.dart'; class SpeedTestExternalView extends StatelessWidget { const SpeedTestExternalView({super.key}); diff --git a/lib/page/health_check/widgets/speed_test_external_widget.dart b/lib/page/health_check/widgets/speed_test_external_widget.dart index 0215a95db..e1c4382bb 100644 --- a/lib/page/health_check/widgets/speed_test_external_widget.dart +++ b/lib/page/health_check/widgets/speed_test_external_widget.dart @@ -2,9 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:privacy_gui/localization/localization_hook.dart'; import 'package:ui_kit_library/ui_kit.dart'; -import 'package:privacy_gui/util/url_helper/url_helper.dart' - if (dart.library.io) 'package:privacy_gui/util/url_helper/url_helper_mobile.dart' - if (dart.library.html) 'package:privacy_gui/util/url_helper/url_helper_web.dart'; +import 'package:privacy_gui/util/url_helper/url_helper.dart'; class SpeedTestExternalWidget extends ConsumerStatefulWidget { const SpeedTestExternalWidget({super.key}); diff --git a/lib/page/instant_admin/providers/manual_firmware_update_provider.dart b/lib/page/instant_admin/providers/manual_firmware_update_provider.dart index f7a5e1819..deb9c9cbf 100644 --- a/lib/page/instant_admin/providers/manual_firmware_update_provider.dart +++ b/lib/page/instant_admin/providers/manual_firmware_update_provider.dart @@ -6,9 +6,7 @@ import 'package:privacy_gui/core/data/providers/side_effect_provider.dart'; import 'package:privacy_gui/page/instant_admin/providers/manual_firmware_update_state.dart'; import 'package:privacy_gui/page/instant_admin/services/manual_firmware_update_service.dart'; import 'package:privacy_gui/providers/auth/auth_provider.dart'; -import 'package:privacy_gui/core/utils/ip_getter/get_local_ip.dart' - if (dart.library.io) 'package:privacy_gui/core/utils/ip_getter/mobile_get_local_ip.dart' - if (dart.library.html) 'package:privacy_gui/core/utils/ip_getter/web_get_local_ip.dart'; +import 'package:privacy_gui/core/utils/ip_getter/ip_getter.dart'; final manualFirmwareUpdateProvider = NotifierProvider.autoDispose< ManualFirmwareUpdateNotifier, ManualFirmwareUpdateState>( diff --git a/lib/route/router_provider.dart b/lib/route/router_provider.dart index 1e4a29d7a..a66697416 100644 --- a/lib/route/router_provider.dart +++ b/lib/route/router_provider.dart @@ -61,9 +61,7 @@ import 'package:privacy_gui/route/route_model.dart'; import 'package:privacy_gui/route/router_logger.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'constants.dart'; -import 'package:privacy_gui/core/utils/ip_getter/get_local_ip.dart' - if (dart.library.io) 'package:privacy_gui/core/utils/ip_getter/mobile_get_local_ip.dart' - if (dart.library.html) 'package:privacy_gui/core/utils/ip_getter/web_get_local_ip.dart'; +import 'package:privacy_gui/core/utils/ip_getter/ip_getter.dart'; import 'package:privacy_gui/page/instant_safety/providers/_providers.dart'; import 'package:privacy_gui/page/ai_assistant/views/router_assistant_view.dart'; diff --git a/lib/util/export_selector/export_selector.dart b/lib/util/export_selector/export_selector.dart new file mode 100644 index 000000000..c774676c3 --- /dev/null +++ b/lib/util/export_selector/export_selector.dart @@ -0,0 +1,17 @@ +/// Export Selector - Cross-platform file export functionality. +/// +/// This library provides platform-aware file export/share. +/// Consumers only need to import this file: +/// +/// ```dart +/// import 'package:privacy_gui/util/export_selector/export_selector.dart'; +/// +/// await exportFile(content: '...', fileName: 'log.txt'); +/// ``` +/// +/// The correct platform implementation is automatically selected at compile time. +library; + +export 'export_base.dart' + if (dart.library.io) 'export_mobile.dart' + if (dart.library.html) 'export_web.dart'; diff --git a/lib/util/get_log_selector/get_log_selector.dart b/lib/util/get_log_selector/get_log_selector.dart new file mode 100644 index 000000000..26f3b3e51 --- /dev/null +++ b/lib/util/get_log_selector/get_log_selector.dart @@ -0,0 +1,17 @@ +/// Get Log Selector - Cross-platform log retrieval functionality. +/// +/// This library provides platform-aware log retrieval. +/// Consumers only need to import this file: +/// +/// ```dart +/// import 'package:privacy_gui/util/get_log_selector/get_log_selector.dart'; +/// +/// final logContent = await getLog(context); +/// ``` +/// +/// The correct platform implementation is automatically selected at compile time. +library; + +export 'get_log_base.dart' + if (dart.library.io) 'get_log_mobile.dart' + if (dart.library.html) 'get_log_web.dart'; diff --git a/lib/util/url_helper/url_helper.dart b/lib/util/url_helper/url_helper.dart index 1a461ff65..d0310b16a 100644 --- a/lib/util/url_helper/url_helper.dart +++ b/lib/util/url_helper/url_helper.dart @@ -1,2 +1,19 @@ -void openUrl(String url) => - throw UnimplementedError('[Platform Error] Not implemented'); +/// URL Helper - Cross-platform URL opening functionality. +/// +/// This library provides platform-aware URL opening. +/// Consumers only need to import this file: +/// +/// ```dart +/// import 'package:privacy_gui/util/url_helper/url_helper.dart'; +/// +/// openUrl('https://example.com'); +/// ``` +/// +/// The correct platform implementation is automatically selected at compile time. +/// - Native (iOS/Android): Opens URL using in-app browser +/// - Web: Opens URL in new browser tab +library; + +export 'url_helper_stub.dart' + if (dart.library.io) 'url_helper_mobile.dart' + if (dart.library.html) 'url_helper_web.dart'; diff --git a/lib/util/url_helper/url_helper_stub.dart b/lib/util/url_helper/url_helper_stub.dart new file mode 100644 index 000000000..1a461ff65 --- /dev/null +++ b/lib/util/url_helper/url_helper_stub.dart @@ -0,0 +1,2 @@ +void openUrl(String url) => + throw UnimplementedError('[Platform Error] Not implemented'); diff --git a/lib/utils.dart b/lib/utils.dart index 4cc8bbf4a..bccad92c0 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -19,12 +19,8 @@ import 'package:ui_kit_library/ui_kit.dart'; import 'core/utils/logger.dart'; import 'core/utils/storage.dart'; import 'core/utils/fernet_manager.dart'; -import '../../../util/export_selector/export_base.dart' - if (dart.library.io) '../../../util/export_selector/export_mobile.dart' - if (dart.library.html) '../../../util/export_selector/export_web.dart'; -import '../../../util/get_log_selector/get_log_base.dart' - if (dart.library.io) '../../../util/get_log_selector/get_log_mobile.dart' - if (dart.library.html) '../../../util/get_log_selector/get_log_web.dart'; +import 'package:privacy_gui/util/export_selector/export_selector.dart'; +import 'package:privacy_gui/util/get_log_selector/get_log_selector.dart'; class Utils { static Future exportLogFile(BuildContext context) async { diff --git a/pubspec.yaml b/pubspec.yaml index 8f607e774..f285d2aa2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -68,13 +68,13 @@ dependencies: ui_kit_library: git: url: https://github.com/linksys/privacyGUI-UI-kit.git - ref: v2.10.3 + ref: v2.10.4 # ui_kit_library: # path: ../../ui_kit generative_ui: git: url: https://github.com/linksys/privacyGUI-UI-kit.git - ref: v2.10.3 + ref: v2.10.4 path: generative_ui flutter_blue_plus: ^1.4.0 crypto: ^3.0.2