2026-02-27 15:22:42 +08:00
|
|
|
# Flutter Mobile Development Rules
|
2026-02-05 15:13:06 +08:00
|
|
|
|
2026-02-27 15:22:42 +08:00
|
|
|
This document defines Flutter mobile development constraints.
|
2026-02-24 18:18:42 +08:00
|
|
|
|
2026-02-27 15:22:42 +08:00
|
|
|
## Design System
|
2026-02-24 18:18:42 +08:00
|
|
|
|
2026-02-27 15:22:42 +08:00
|
|
|
### Design Tokens
|
2026-02-24 18:18:42 +08:00
|
|
|
|
2026-02-27 15:22:42 +08:00
|
|
|
All UI styling must use design tokens from `apps/lib/core/theme/design_tokens.dart`:
|
|
|
|
|
|
|
|
|
|
| Type | Usage |
|
|
|
|
|
|------|-------|
|
|
|
|
|
| Colors | `AppColors.primary`, `AppColors.slate500`, `AppColors.background` |
|
|
|
|
|
| Spacing | `AppSpacing.xs`, `AppSpacing.sm`, `AppSpacing.md` |
|
|
|
|
|
| Radius | `AppRadius.sm`, `AppRadius.md`, `AppRadius.lg` |
|
|
|
|
|
|
|
|
|
|
**NEVER hardcode colors, sizes, or spacing values.**
|
|
|
|
|
|
|
|
|
|
### Reuse Existing Components
|
|
|
|
|
|
|
|
|
|
Use pre-built components instead of creating custom ones:
|
|
|
|
|
- Buttons: Use `AppButton` widget from `apps/lib/shared/widgets/app_button.dart`
|
|
|
|
|
- Input fields: Use standard Flutter `TextField` with `InputDecoration`
|
|
|
|
|
- Loading states: Use built-in loading indicators
|
|
|
|
|
|
|
|
|
|
## New Page Design Workflow
|
|
|
|
|
|
|
|
|
|
1. **Analyze existing pages**: Study login, register, home screens for:
|
|
|
|
|
- Layout structure (centered form, padding, spacing)
|
|
|
|
|
- Typography hierarchy (title 28px bold, label 13px, hint 14px)
|
|
|
|
|
- Component usage (AppButton, TextField style)
|
|
|
|
|
- Color and spacing tokens
|
|
|
|
|
|
|
|
|
|
2. **Use frontend-design skill for mockups**:
|
|
|
|
|
```
|
|
|
|
|
Use the `frontend-design` skill to create HTML/CSS mockups for review
|
|
|
|
|
Match colors to `apps/lib/core/theme/design_tokens.dart`
|
|
|
|
|
Match spacing to `AppSpacing` values
|
|
|
|
|
Match radius to `AppRadius` values
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
3. **Verify design tokens**:
|
|
|
|
|
- All colors from `AppColors`
|
|
|
|
|
- All spacing from `AppSpacing`
|
|
|
|
|
- All radius from `AppRadius`
|
|
|
|
|
- NO hardcoded values
|
|
|
|
|
|
|
|
|
|
4. **Code review checklist**:
|
|
|
|
|
- [ ] All colors/spacing/radius use design tokens
|
|
|
|
|
- [ ] Reuses existing components (AppButton)
|
|
|
|
|
- [ ] Consistent with existing page patterns
|
|
|
|
|
- [ ] No magic numbers
|
2026-02-24 18:18:42 +08:00
|
|
|
|
|
|
|
|
## Layout Mapping Rules
|
|
|
|
|
|
|
|
|
|
Map design layout properties to Flutter explicitly:
|
|
|
|
|
|
|
|
|
|
1. **Always set `crossAxisAlignment` on `Row`/`Column`**:
|
|
|
|
|
- `alignItems: center` -> `CrossAxisAlignment.center`
|
|
|
|
|
- `alignItems: start` -> `CrossAxisAlignment.start`
|
|
|
|
|
- `alignItems: stretch` -> `CrossAxisAlignment.stretch`
|
|
|
|
|
2. **Map full container chain**: From root to leaf, ensure each `alignItems` and `justifyContent` has a Flutter equivalent.
|
2026-02-27 15:22:42 +08:00
|
|
|
3. **Analyze before coding**: Verify each container's alignment settings.
|
2026-02-24 18:18:42 +08:00
|
|
|
|
|
|
|
|
## Centering and Visual Balance
|
|
|
|
|
|
2026-02-27 15:22:42 +08:00
|
|
|
1. Centering must be evaluated inside **`SafeArea`** bounds, not full-screen bounds.
|
2026-02-24 18:18:42 +08:00
|
|
|
2. Avoid relying on proportional `Spacer` values as the only centering mechanism for critical content.
|
2026-02-27 15:22:42 +08:00
|
|
|
3. For layouts with persistent top/bottom regions (e.g., headers or footers), center the primary content in the remaining available region.
|
2026-02-24 18:18:42 +08:00
|
|
|
4. Distinguish geometric centering from visual centering; validate final visual balance with screenshot review.
|
|
|
|
|
|
|
|
|
|
## Quality Gate
|
|
|
|
|
|
|
|
|
|
For important screens, add widget tests that reduce layout-regression risk:
|
|
|
|
|
|
|
|
|
|
1. Verify primary content remains centered relative to the usable viewport.
|
|
|
|
|
2. Add at least one constrained viewport scenario (small height or large text scale).
|
|
|
|
|
|
|
|
|
|
## Prohibitions
|
|
|
|
|
|
2026-02-27 15:22:42 +08:00
|
|
|
- DO NOT use colors not defined in design tokens
|
|
|
|
|
- DO NOT skip design container layers
|
|
|
|
|
- DO NOT start implementation before retrieving design variables
|
|
|
|
|
- DO NOT hardcode colors; use design variables
|
2026-02-25 18:00:02 +08:00
|
|
|
|
|
|
|
|
## UI Feedback System
|
|
|
|
|
|
|
|
|
|
**MUST use the Toast system for all user feedback messages.**
|
|
|
|
|
|
|
|
|
|
### Components
|
|
|
|
|
|
|
|
|
|
| Component | Use Case | Example |
|
|
|
|
|
|-----------|----------|---------|
|
|
|
|
|
| `Toast.show()` | Global temporary notifications | Success/error feedback after action |
|
|
|
|
|
| `AppBanner` | Inline form validation errors | Login form error message |
|
|
|
|
|
|
|
|
|
|
### Toast Types
|
|
|
|
|
|
|
|
|
|
```dart
|
|
|
|
|
enum ToastType { info, success, warning, error }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Usage Examples
|
|
|
|
|
|
|
|
|
|
**Global Toast (auto-dismiss):**
|
|
|
|
|
```dart
|
|
|
|
|
Toast.show(context, '保存成功', type: ToastType.success);
|
|
|
|
|
Toast.show(context, '网络错误', type: ToastType.error);
|
|
|
|
|
Toast.show(context, '正在加载...', type: ToastType.info, duration: Duration(seconds: 3));
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Inline Banner (persistent):**
|
|
|
|
|
```dart
|
|
|
|
|
AppBanner(message: '邮箱或密码错误', type: ToastType.error)
|
|
|
|
|
AppBanner(message: '请检查输入', type: ToastType.warning)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Rules
|
|
|
|
|
|
|
|
|
|
- Use `Toast` for transient feedback that auto-dismisses
|
|
|
|
|
- Use `AppBanner` for persistent inline messages (form errors)
|
2026-02-27 15:22:42 +08:00
|
|
|
- DO NOT create custom SnackBar, Dialog, or Banner components
|
|
|
|
|
- DO NOT use raw `ScaffoldMessenger`
|
2026-03-02 10:55:46 +08:00
|
|
|
|
2026-03-02 11:17:20 +08:00
|
|
|
## Agent Chat (AG-UI Protocol)
|
|
|
|
|
|
|
|
|
|
**Agent chat functionality MUST follow the AG-UI protocol**, reference `docs/knowledges/ag-ui-llms-full.txt`.
|
|
|
|
|
|
|
|
|
|
### Core Requirements
|
|
|
|
|
|
|
|
|
|
1. **Event-Driven Architecture**: Implement event-driven streaming responses
|
|
|
|
|
2. **Event Types**: Must support the 16 standard event types:
|
|
|
|
|
- **Lifecycle**: `RUN_STARTED`, `RUN_FINISHED`, `RUN_ERROR`, `STEP_STARTED`, `STEP_FINISHED`
|
|
|
|
|
- **Text Message**: `TEXT_MESSAGE_START`, `TEXT_MESSAGE_CONTENT`, `TEXT_MESSAGE_END`
|
|
|
|
|
- **Tool Call**: `TOOL_CALL_START`, `TOOL_CALL_ARGS`, `TOOL_CALL_END`, `TOOL_CALL_RESULT`
|
|
|
|
|
- **State Management**: `STATE_SNAPSHOT`, `STATE_DELTA`, `MESSAGES_SNAPSHOT`
|
|
|
|
|
- **Special**: `RAW`, `CUSTOM`
|
|
|
|
|
|
|
|
|
|
3. **Transport**: Use Server-Sent Events (SSE) for streaming
|
|
|
|
|
|
|
|
|
|
4. **Event Flow**: Follow the standard pattern:
|
|
|
|
|
- `RUN_STARTED` (required) → [optional events] → `RUN_FINISHED` or `RUN_ERROR` (required)
|
|
|
|
|
- Text messages: `TEXT_MESSAGE_START` → `TEXT_MESSAGE_CONTENT` (delta) → `TEXT_MESSAGE_END`
|
|
|
|
|
|
|
|
|
|
5. **Frontend Integration**: Use AG-UI compatible client libraries
|
|
|
|
|
|
|
|
|
|
### Event Reference
|
|
|
|
|
|
|
|
|
|
| Event | Description |
|
|
|
|
|
|-------|-------------|
|
|
|
|
|
| `RUN_STARTED` | Signals the start of an agent run |
|
|
|
|
|
| `RUN_FINISHED` | Signals successful completion |
|
|
|
|
|
| `RUN_ERROR` | Signals an error during execution |
|
|
|
|
|
| `TEXT_MESSAGE_START` | Initializes a new text message with unique messageId |
|
|
|
|
|
| `TEXT_MESSAGE_CONTENT` | Delivers incremental text chunks (delta) |
|
|
|
|
|
| `TEXT_MESSAGE_END` | Marks message completion |
|
|
|
|
|
|
|
|
|
|
### Prohibitions
|
|
|
|
|
|
|
|
|
|
- DO NOT return non-streaming responses for agent chat
|
|
|
|
|
- DO NOT skip required lifecycle events (RUN_STARTED, RUN_FINISHED/RUN_ERROR)
|
|
|
|
|
- DO NOT use custom event formats outside of AG-UI specification
|
|
|
|
|
|
|
|
|
|
|
2026-03-02 10:55:46 +08:00
|
|
|
## App Debugging
|
|
|
|
|
|
|
|
|
|
**DO NOT automatically start Flutter app debugging.**
|
|
|
|
|
|
|
|
|
|
After completing code changes, inform the user to manually run:
|
|
|
|
|
```bash
|
|
|
|
|
flutter run --dart-define=MOCK_API=true -d emulator-5554
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Let the user control when to launch the app for testing.
|