2026-03-02 15:05:10 +08:00
# Flutter Mobile Development Constraints
2026-02-05 15:13:06 +08:00
2026-03-02 15:05:10 +08:00
This document defines **hard constraints ** for Flutter mobile development. Treat all items as **non-negotiable ** unless explicitly overridden.
2026-02-24 18:18:42 +08:00
2026-03-12 16:41:45 +08:00
## 0) Scope and Precedence (MUST)
- This file applies to all changes under `apps/**` .
- It extends root routing rules in `AGENTS.md` and workspace global runtime rules.
2026-03-13 14:10:13 +08:00
- It also incorporates the visual design language from `apps/rules/visual_design_language.md` as a binding constraint.
2026-03-12 16:41:45 +08:00
- If rules conflict, apply the stricter requirement.
- Keep Flutter-specific constraints in this file; avoid duplicating them in root `AGENTS.md` .
2026-03-02 15:05:10 +08:00
## 1) Design Tokens (MUST)
2026-02-24 18:18:42 +08:00
2026-03-02 15:05:10 +08:00
- **MUST** use design tokens from `apps/lib/core/theme/design_tokens.dart` :
- Colors: `AppColors.*`
- Spacing: `AppSpacing.*`
- Radius: `AppRadius.*`
2026-03-13 14:10:13 +08:00
- **MUST NOT** hardcode any visual values.
- Design tokens are the single source of truth for all visual values. Any missing visual semantics should be added to tokens, not approximated locally.
- This ensures consistency with the visual design language defined in `apps/rules/visual_design_language.md` .
2026-02-24 18:18:42 +08:00
2026-03-13 14:10:13 +08:00
## 2) Component Architecture (MUST)
2026-02-27 15:22:42 +08:00
2026-03-13 14:10:13 +08:00
- **SHOULD** extract repeated UI patterns into reusable components.
- **SHOULD** prefer existing shared components before creating new ones.
- **SHOULD** place reusable components in `apps/lib/shared/widgets/` following existing naming conventions.
- **MUST NOT** introduce parallel UI systems (e.g., custom button styles, custom loading indicators) that duplicate existing shared components.
- When creating new UI components, ensure they follow the design tokens and visual design language.
2026-02-27 15:22:42 +08:00
2026-03-18 13:35:25 +08:00
## 2.1) Navigation/Header Reuse Rules (MUST)
- For page groups with clear parent-child relationships (e.g., Settings and its subpages), **MUST ** use one shared header pattern: back button + page title.
- **MUST** extract shared page scaffolds/header wrappers instead of duplicating `SafeArea + header + scroll` structures across sibling pages.
- Detail-page right-side actions (edit/delete/share etc.) **MUST ** use a shared action-menu component, not per-page ad-hoc button groups.
- Header action menus **MUST NOT ** overlap the trigger button area; menu surfaces should open below/right-aligned to the trigger and preserve title readability.
## 2.2) Interaction Surface Reuse Rules (MUST)
- Repeated state-switch controls (toggle/switch UI) **MUST ** be extracted into shared widgets.
- Destructive confirmations (delete/remove) **MUST ** use shared project-style confirmation surfaces (e.g., unified action sheet), not platform-default dialog styles.
- **MUST NOT** use raw platform-default popup/dialog/dropdown visuals when they break project visual language; use token-driven shared components instead.
2026-03-02 15:05:10 +08:00
## 3) Layout Mapping & Alignment (MUST)
2026-02-27 15:22:42 +08:00
2026-03-02 15:05:10 +08:00
- **MUST** explicitly set `crossAxisAlignment` for every `Row` / `Column` (do not rely on defaults).
- **MUST** preserve layout semantics from root to leaf:
- alignment/justification intent must be explicitly represented in Flutter widgets.
- **MUST NOT** skip necessary container layers if doing so loses layout meaning or makes mapping non-traceable.
2026-02-27 15:22:42 +08:00
2026-03-02 15:05:10 +08:00
## 4) Centering & Visual Balance (MUST)
2026-02-27 15:22:42 +08:00
2026-03-02 15:05:10 +08:00
- **MUST** evaluate centering within `SafeArea` usable bounds (not full-screen bounds).
- **MUST NOT** rely on `Spacer` / proportional flex as the only centering mechanism for critical content.
- If persistent header/footer regions exist, **MUST ** center primary content within the remaining usable region.
- **MUST** prioritize * visual centering * over purely geometric centering when they differ.
2026-02-27 15:22:42 +08:00
2026-03-12 16:41:45 +08:00
## 5) Testing Strategy (MUST)
Follow lightweight testing strategy - prioritize value over coverage:
2026-02-27 15:22:42 +08:00
2026-03-12 16:41:45 +08:00
**Write tests for: **
- Model / DTO parsing (json → model)
- Service layer logic (business rules, API call handling)
- Complex custom widgets with rich interactions
2026-02-27 15:22:42 +08:00
2026-03-12 16:41:45 +08:00
**Skip for: **
- Simple UI pages, regular buttons, basic layouts
2026-02-27 15:22:42 +08:00
2026-03-02 15:05:10 +08:00
## 6) UI Feedback System (MUST)
2026-02-24 18:18:42 +08:00
2026-03-02 15:05:10 +08:00
- All user-facing feedback **MUST ** use the Toast system.
- Transient notifications: `Toast.show(...)`
- Persistent inline form errors: `AppBanner`
- **MUST NOT** create custom SnackBar/Dialog/Banner feedback components.
- **MUST NOT** use raw `ScaffoldMessenger` for feedback messaging.
2026-02-24 18:18:42 +08:00
2026-03-16 16:11:28 +08:00
## 6.1) Loading Indicator System (MUST)
- All loading spinners **MUST ** use `AppLoadingIndicator` from `apps/lib/shared/widgets/app_loading_indicator.dart` .
- **MUST NOT** use raw `CircularProgressIndicator` directly in feature/page code.
- Use variants consistently:
- page/surface loading: `AppLoadingVariant.surface`
- inline small loading (list/search/section): `AppLoadingVariant.inline`
- button loading: `AppLoadingVariant.button`
- If visual semantics are missing, extend `AppLoadingIndicator` variant mapping first; do not create ad-hoc loading styles in feature files.
2026-03-02 15:05:10 +08:00
## 7) Agent Chat (AG-UI Protocol) (MUST)
2026-02-24 18:18:42 +08:00
2026-03-02 17:02:09 +08:00
Agent chat functionality **MUST ** follow the AG-UI protocol. **Use the `ag-ui` skill ** for protocol reference and implementation guidance.
2026-02-24 18:18:42 +08:00
2026-03-02 15:05:10 +08:00
- **MUST** use Server-Sent Events (SSE) for streaming.
- **MUST** emit required lifecycle events:
- `RUN_STARTED` is required for every run
- End with exactly one of: `RUN_FINISHED` or `RUN_ERROR`
- **MUST** follow standard text streaming flow:
- `TEXT_MESSAGE_START` → `TEXT_MESSAGE_CONTENT` (delta) → `TEXT_MESSAGE_END`
- **MUST** support the standard AG-UI event type set as defined in the spec.
- **MUST NOT** return non-streaming responses for agent chat.
- **MUST NOT** omit required lifecycle events.
- **MUST NOT** use non-AG-UI event formats (except where the spec explicitly allows).
2026-03-13 14:10:13 +08:00
## 8) Visual Design Language (MUST)
All UI/UX work **MUST ** follow the visual design language defined in `apps/rules/visual_design_language.md` .
- **MUST** ensure screens feel like a premium personal assistant product, not a wireframe, admin console, or document page.
- **MUST** apply the surface-based design system (background, primary, secondary, interactive surfaces).
- **MUST** follow the motion and interaction feel guidelines (soft, responsive, premium).
- **MUST** achieve visual hierarchy through spacing, surface grouping, radius, depth, density, contrast, scale, and motion—not color alone.
2026-03-16 19:04:54 +08:00
- **MUST** prioritize compact informational delivery in top bars: when the page purpose can be clearly expressed by a concise header title, avoid repeating equivalent explanatory hints in the body.
- **MUST NOT** duplicate page identity text between header and first content block unless the repeated text introduces new decision-critical information.
2026-03-13 14:10:13 +08:00
- **MUST** follow the screen-level decision rules:
1. What is the primary focus?
2. What is the surface hierarchy?
3. What needs strongest emphasis?
4. What should be grouped?
5. What should be lightweight/secondary?
6. Where should motion reinforce understanding?
7. How can the result feel more like a premium assistant app and less like a document page?
- **MUST NOT** create UIs that match the anti-patterns listed in the visual design language document:
- plain document page, white slab with blue buttons, spreadsheet-like admin panel
- low-fidelity wireframe, default Flutter demo app, generic template marketplace screen
- full-screen flat white blocks, arbitrary shadow usage, inconsistent card treatments
- raw container stacking without surface semantics
Before finalizing any UI, mentally verify:
- Does this feel like a product, not a page?
- Is there clear hierarchy?
- Do surfaces feel intentional?
- Does the screen feel calm and premium?
- Is the assistant identity visually present?
- Would this look plausible in a polished shipping app?
2026-03-18 13:35:25 +08:00
## 9) Auth Global Module Rules (MUST)
Auth is a global module. All auth/session behavior MUST follow a single state machine.
- **MUST** treat `AuthBloc` as the single source of truth for authentication state.
- **MUST NOT** implement ad-hoc auth state in feature modules (no parallel flags, no local auth caches).
- **MUST** route all 401 refresh-failure handling through the global callback chain:
`ApiInterceptor -> ApiClient auth failure callback -> AuthBloc(AuthSessionInvalidated)` .
- **MUST NOT** clear tokens directly inside feature/page code.
- **MUST NOT** navigate to login directly from feature code on token errors; rely on router redirect driven by global auth state.
- **MUST** distinguish logout semantics:
- manual logout: revoke server session + clear local session
- auto expiry/logout on refresh failure: clear local session only
- **MUST** ensure startup session recovery has exception fallback and never leaves app stuck in boot/loading state.
- **MUST** add/maintain tests for:
- startup recovery fallback
- concurrent 401 refresh failure singleflight
- session invalidation -> unauthenticated redirect path
If a new auth-related requirement cannot fit this model, update this section first, then implement code.
2026-03-19 00:52:02 +08:00
## 10) Home Message Loading & Scroll Rules (MUST)
Home 首页历史消息加载与滚动策略属于高回归模块,必须遵循以下约束:
- **MUST** use event-driven viewport decisions for Home message list behavior.
- Use `HomeMessageViewportController` as the decision engine.
- **MUST NOT** drive auto-scroll directly from `items.length` diffs or ad-hoc boolean combinations.
- **MUST** distinguish semantic events at minimum:
- initial history loaded
- history prepend start/finish
- new message appended
- sub-route resume
- refresh completed
- user scroll state changed
- **MUST** preserve reading position when user is away from bottom.
- New messages while reading history should show unread indicator instead of forcing bottom jump.
- **MUST** preserve viewport anchor during history prepend.
- **MUST NOT** mix prepend restore with unconditional bottom auto-scroll.
- **MUST** use `returnToHomePreserveState` for business-subroute returns to Home (calendar/todo/message-related flows).
- **MUST NOT** introduce new direct business-route `go('/home')` shortcuts.
- Auth entry flows (login/register success) are allowed to navigate to Home directly.
- **MUST** add or update tests when touching Home message loading/scroll behavior:
- controller-level state transition tests
- widget-level unread indicator and scroll behavior tests
- route-return stability tests when navigation behavior changes