기본 local 테스트 환경이 standard remote runner라는 전제에 맞춰 문서와 로드맵 기준을 정리한다. Core compose host publish 기본값을 18010으로 맞추고 8080 호환은 명시적 override로 남긴다.
120 lines
8.5 KiB
Markdown
120 lines
8.5 KiB
Markdown
# nomadcode-app
|
|
|
|
The Flutter-first NomadCode client application.
|
|
|
|
## Client Module Standard
|
|
|
|
The Flutter host application in this monorepo is standardized under `apps/client/`. This directory serves as the reference architecture for other projects (such as `../iop` and `../alt`) to replicate.
|
|
|
|
### Directory Layout
|
|
- **`lib/src/app/`**: Root application routing, workbench shell, bootstrap settings (`bootstrap.dart`), global configurations, and state setup.
|
|
- **`lib/src/features/`**: Feature-specific UI surfaces, business logic, and local UI state. Keep layout decoupled from shared integration protocols.
|
|
- **`lib/src/integrations/`**: Adapters and lifecycle hooks for external system boundaries. Any connection initialization or platform-specific service logic should reside here under strict interfaces.
|
|
|
|
### Naming Conventions
|
|
- **Flutter Host Path**: Always kept as `apps/client/` to act as the primary client skeleton.
|
|
- **Dart Package Name**: Standardized as `nomadcode_app`. When cloning, this package name can be customized to match target project identities (e.g. `iop_client_app`, `alt_client_app`) in `pubspec.yaml`, while maintaining the same directory layout.
|
|
|
|
---
|
|
|
|
## Workbench Shell
|
|
|
|
`lib/src/app/nomadcode_workbench_shell.dart` owns the current NomadCode client shell. It provides a top titlebar, a right-side activity rail, center content switching, and an Agent dock panel attached to the right rail. The rail keeps product/workflow placeholder icons near the top and the IOP entry at the bottom.
|
|
|
|
The Agent dock uses the sibling `agent_shell` package as a product-neutral chat/agent surface. Workflow, Web Context, and optional IOP management areas are mounted as center content sections. IOP-specific UI should be composed through an IOP-owned package or widget boundary via the optional `iopContent` slot rather than copied into NomadCode client code.
|
|
|
|
`WorkspaceHomePage` can hide its own app bar through `showAppBar: false` when it is mounted inside the workbench shell.
|
|
|
|
---
|
|
|
|
## Bootstrap
|
|
|
|
NomadCode features a standardized, platform-safe bootstrap layer in `lib/src/app/bootstrap.dart`:
|
|
- **Common Initialization Path**: `bootstrapNomadCodeClient()` performs synchronous preparation, setups UI configurations (e.g., fullscreen system overlays), and initializes Firebase + Mattermost push notification boundaries.
|
|
- **Platform-Specific Guard**: Native modules and background tasks (such as Firebase Messaging background handlers) are cleanly guarded inside integration-specific or native layers, preventing background crashes or initialization collision.
|
|
- **No-Op Defaults**: External transport components (such as the proto-socket lifecycle engine) initialize with safe no-op adapters by default to guarantee bootstrap safety.
|
|
|
|
---
|
|
|
|
## Platform Targets
|
|
|
|
We prioritize and validate two primary platforms in this milestone, while ensuring others can be added seamlessly:
|
|
- **Web & Android (Primary Targets)**: Fully validated in the main bootstrap configuration. Local notification integration and web socket configurations are verified to build and bootstrap without compilation errors.
|
|
- **iOS (Future Expansion)**: iOS is treated as a first-class citizen using the same Dart APIs and integration facade boundaries (`MattermostPushClient`, `ProtoSocketLifecycle`). Native iOS APNS and notification delegate handlers can be wired later into the same Dart interfaces without modifying the core bootstrap logic.
|
|
|
|
---
|
|
|
|
## Integration Boundaries
|
|
|
|
`apps/client/lib/src/integrations/` groups all external-system adapters behind small Dart interfaces:
|
|
|
|
- `integrations/mattermost/` — `MattermostPushClient` interface, `MattermostPushPluginClient` adapter (the only production reference to `NexoMessagingPlugin.instance`), `MattermostPushHostIntegration` (initialize + auth handoff + navigation callbacks), and `MattermostAuthService`.
|
|
- `integrations/proto_socket/` — `ProtoSocketEndpointConfig` and `ProtoSocketLifecycle` facade over the local `proto_socket` Dart path dependency. Bootstrap does not auto-connect; enabling and wiring a real connector are deferred to the next milestone.
|
|
|
|
For detailed integration boundaries, platform targets, and clone handoff guidelines, see [push-notification-todo.md](push-notification-todo.md).
|
|
|
|
---
|
|
|
|
## Web Preview Ports
|
|
|
|
Human Flutter web preview through code-server should use the `/proxy/<port>/` base href. For stable workspace previews, prefer `13010` and then `13011`, `13012`, and so on for parallel previews. Existing ad hoc local smoke flows that use a fresh port such as `8081` remain valid compatibility checks.
|
|
|
|
The mock workspace `codeServerUrl` values that point at `http://localhost:8080/?folder=...` are code-server workspace entry links, not Flutter web preview ports. Keep them separate from the `13010+` preview band.
|
|
|
|
---
|
|
|
|
## Mattermost Push Notification Integration
|
|
|
|
Mattermost push notification delivery is implemented via the local `nexo_messaging` path dependency at `../nexo/packages/messaging_flutter`.
|
|
|
|
### Architecture & Responsibility Split
|
|
|
|
To maintain a clean and maintainable codebase, the responsibilities are split between the host application and the plugin as follows:
|
|
|
|
#### Host Application (`apps/client`) Responsibilities:
|
|
- **Firebase Configuration**: Contains the standard Firebase configuration files (`android/app/google-services.json`) and performs the standard `Firebase.initializeApp()` call in Dart main.
|
|
- **Mattermost Authentication**: Handles login and session lifecycles, and passes the user authentication token and server signing key through the `MattermostPushClient` boundary. The production `MattermostPushPluginClient` adapter owns the plugin singleton calls. Local smoke credentials may be provided as ignored `assets/mattermost_credentials.json`.
|
|
- **Navigation Callbacks**: Registers standard Flutter navigation callbacks `onNavigateToChannel` and `onNavigateToThread` to handle workspace channel and CRT thread routing upon user interaction.
|
|
- **FCM Token Sync**: Listens to device token registrations via `onDeviceTokenReady` and registers the token with the Mattermost server.
|
|
|
|
#### Nexo Messaging Plugin (`nexo_messaging`) Responsibilities:
|
|
- **Native Android FCM Service**: Intercepts background/foreground FCM notifications securely via a custom Kotlin FCM service.
|
|
- **Signature Verification**: Validates incoming push payload signatures against stored public signing keys (using `JJWT`).
|
|
- **System Notification Builder**: Displays structured notifications with local avatar caches, thread summaries, and action buttons.
|
|
- **Inline Reply / Dismiss Actions**: Receives native background actions, records responses in a Room database, and forwards replies/ACKs directly to the Mattermost API via custom OkHttp adapters.
|
|
|
|
---
|
|
|
|
## Cloning & Handoff Checklist
|
|
|
|
For sibling repositories (`../iop` and `../alt`) aiming to align with this standard structure:
|
|
|
|
### Sibling Specific Alignment Guidelines:
|
|
- **`../iop`**: Avoid emphasizing legacy Portal naming conventions. Reorganize/rename legacy mobile paths to the `apps/client` standard. Align folder structures under `src/app`, `src/features`, and `src/integrations`. Do not clone NomadCode product-specific screens—only the integration and bootstrap skeletons.
|
|
- **`../alt`**: Retain ALT-specific Riverpod-based dependency graph and `go_router` for app routing. However, extract external adapters into `lib/src/integrations/` matching the common Dart facade interfaces (`MattermostPushClient`, `ProtoSocketLifecycle`) to align the bootstrap pipeline.
|
|
|
|
### Common Replacement Checklist:
|
|
When cloning this host template into a new environment, replace the following values:
|
|
1. **Dart Package Name**: Rename `nomadcode_app` to your target app package identifier in `pubspec.yaml`.
|
|
2. **Display & App Naming**: Adjust launcher configurations, bundle identifiers, and target product names in native assets (`android/app/src/main/AndroidManifest.xml`, `ios/Runner/Info.plist`).
|
|
3. **Firebase Configuration**: Replace `google-services.json` (Android) and `GoogleService-Info.plist` (iOS) with target project project credentials.
|
|
4. **Endpoint Defaults**: Update `ProtoSocketEndpointConfig` initialization defaults in environment configurations to route to your target backends.
|
|
5. **Mattermost Server Configurations**: Update server URLs, authentications, and asymmetrical public keys matching the target deployment environment.
|
|
|
|
---
|
|
|
|
## Verification
|
|
|
|
To ensure code stability and structure correctness, run the following verification checks within this directory:
|
|
- **Unit Tests**:
|
|
```bash
|
|
flutter test
|
|
```
|
|
- **Static Analysis**:
|
|
```bash
|
|
flutter analyze --no-fatal-infos
|
|
```
|
|
- **Web Build Validation**:
|
|
```bash
|
|
flutter build web
|
|
```
|