# UI Components - Quick Reference Guide ## Component Overview | Component | Purpose | Extends | Key Responsibilities | |-----------|---------|---------|----------------------| | **main.ts** | App bootstrap | Component | Register pages, init ViewManager & ToastManager | | **PageLoading.ts** | Splash screen | Component | Load data, sync progress, detect share code | | **PageHome.ts** | Landing page | BaseView | Navigation hub (game/PK buttons) | | **PageLevel.ts** | Game level | BaseView | Core gameplay (timer, hints, scoring, input) | | **PagePreviewLevels.ts** | Level preview | BaseView | Scrollable list of selected levels | | **PassModal.ts** | Completion modal | BaseView | Next level & share buttons, success sound | | **Toast.ts** | Notification | Component | Display message with fade animation | | **ToastManager.ts** | Toast system | Singleton | Centralized toast creation & display | | **BaseView.ts** | Page base class | Component | Lifecycle interface for all pages | | **ViewManager.ts** | Page manager | Singleton | Navigation, stacking, caching, lifecycle | --- ## Lifecycle Stages ### Page Lifecycle (BaseView) ``` onViewLoad() → onViewShow() → onViewHide() → onViewDestroy() (once) (each show) (each hide) (on destroy) ``` ### App Startup Flow ``` main.onLoad() ↓ (Initialize ViewManager + register pages) PageLoading.start() ↓ (Load auth + levels in parallel, check share code) PageHome (normal) OR PageLevel (share mode) ``` --- ## Key Data Flows ### Level Progression ``` PageLevel loads config → Displays image + clue1 → User enters answer ↓ (correct) → Earn points → Show PassModal → Next level ↓ (wrong) → Show toast → Continue playing ↓ (timeout) → Play fail sound ``` ### Hint Unlocking ``` User clicks unlock button → Check points available ↓ (yes) → Consume point from UserAssetsManager ↓ → Hide unlock button, show clue ↓ (no) → Show "insufficient points" toast ``` ### Share Challenge Mode ``` WeChat link → PageLoading detects share code ↓ → ShareManager.joinShare(code) ↓ → Play through shared levels (doesn't save local progress) ↓ → Report progress to server ↓ → Return to PageHome ``` --- ## Component Properties Summary ### PageLevel (Most Complex) **UI Elements:** - inputLayout, submitButton, inputTemplate, actionNode - iconSetting (back button) - tipsLayout, tipsItem1/2/3 (clues) - unLockItem2/3 (unlock buttons) - clockLabel (timer), liveLabel (points) - mainImage (level image) **Audio:** - clickAudio, successAudio, failAudio **Internal State:** - _countdown (60 sec timer) - _isTimeUp (timer expired flag) - _currentConfig (level data) - _isTransitioning (prevent double-submit) - _isUnlocking (prevent double-click unlock) - _passModalNode (modal reference) - _isShareMode (shared vs normal) **Key Methods:** - onViewLoad/Show/Hide/Destroy (lifecycle) - initLevel() (async load config) - createSingleInput(length) (input box) - onUnlockClue(index) (consume points for hints) - onSubmitAnswer() (check answer) - showSuccess() (correct: earn points, show modal) - showError() (wrong: toast + vibration) - nextLevel() (progress to next) - startCountdown() / onCountdownTick() (60s timer) --- ## Points & Scoring System **Earning Points:** - `UserAssetsManager.earnPoint(levelId, timeSpent)` - Called in PageLevel.showSuccess() - Time spent = 60 - countdown **Consuming Points:** - `UserAssetsManager.consumePoint(levelId, hintIndex)` - Called in PageLevel.onUnlockClue() - Check `StorageManager.hasPoints()` before consuming **Displaying Points:** - `StorageManager.getPoints()` → Display as "x {points}" - Called in PageLevel.updatePointsLabel() --- ## Timer System **60-Second Countdown:** - Starts when level loads: `startCountdown()` - Ticks every 1 second: `onCountdownTick()` - Displayed as: "60s", "59s", ..., "0s" - On timeout: plays fail sound, doesn't end game **Stop Timer:** - `stopCountdown()` called when: - Answer submitted (correct) - Page destroyed - All levels completed --- ## Hint/Clue System **3 Clues Per Level:** 1. **Clue 1** - Always visible (free) 2. **Clue 2** - Unlock button, costs points 3. **Clue 3** - Unlock button, costs points **Display:** - Text in tipsItem1/2/3 nodes - Hidden if locked (tipsItem.active = false) - Unlock button visible if locked **Unlock Flow:** 1. User clicks unLockItem2 or unLockItem3 2. Check points: `StorageManager.hasPoints()` 3. Consume: `UserAssetsManager.consumePoint(levelId, index)` 4. Hide button, show clue, update UI --- ## Navigation Stack **Structure:** - LIFO stack managed by ViewManager - Each open() adds to stack - back() pops from stack - replace() swaps top **Example Session:** ``` [PageHome] ↓ open PageLevel [PageHome, PageLevel] ↓ open PassModal (or inline) [PageHome, PageLevel, PassModal?] ↓ close/back [PageHome] ``` **Methods:** - `ViewManager.open(viewId, options?)` - Push to stack - `ViewManager.back()` - Pop from stack, show previous - `ViewManager.replace(viewId, options?)` - Pop current, push new --- ## Caching Strategy **Cached Views (default):** - Instance reused on re-open - onViewLoad() called once - onViewShow() called each time - Memory persists **Non-Cached Views:** - New instance each time - onViewLoad() called each time - Memory released on close **Configuration:** ```typescript // In main.ts registration ViewManager.instance.register('PageHome', { prefab: pageHomePrefab, cache: true, // ← Reuse instance zIndex: 0 // ← Layer depth }); ``` --- ## Toast System **Show Toast:** ```typescript ToastManager.show("消息内容", 2000); // duration in ms ``` **Initialization (main.ts):** ```typescript ToastManager.instance.init(toastPrefab, canvasNode); ``` **Toast Behavior:** - Creates Toast instance from prefab - Displays for duration (default 2000ms) - Fades out over 300ms - Auto-destroys --- ## WeChat Integration **Share Initialization (PageHome):** ```typescript WxSDK.initShare({ title: '写英语', imageUrl: '', query: '' }); ``` **Share in Challenge (PassModal):** ```typescript WxSDK.shareAppMessage({ title: '快来一起玩这款游戏吧', query: `level={levelIndex}` }); ``` **Share Code Detection (PageLoading):** ```typescript const shareCode = WxSDK.getShareCodeFromLaunch(); if (shareCode) { const joined = await ShareManager.instance.joinShare(shareCode); // Launch PageLevel in share mode } ``` **Other WeChat Features:** - `WxSDK.vibrateLong()` - Haptic feedback on wrong answer - `WxSDK.isWechat()` - Check if running in WeChat - `checkPrivacySetting()` - Check privacy authorization - `requirePrivacyAuthorize()` - Prompt for privacy consent --- ## Error Handling & Edge Cases **Level Loading:** - Try cache first, then async load - Preload next level without blocking - Handle missing config gracefully **Point Consumption:** - Check availability before consuming - Show toast if insufficient - Prevent double-click with flag **Answer Submission:** - Prevent multiple submissions with transition flag - Trim whitespace from answer - Case-sensitive comparison **Page Navigation:** - Share mode: clears share state before returning home - Normal mode: simple back() navigation - Modal: stays on top (z-index 999) --- ## Common Tasks ### Add Toast ```typescript ToastManager.show('提示信息'); ``` ### Navigate to Page ```typescript ViewManager.instance.open('PageLevel'); // Push ViewManager.instance.back(); // Pop ViewManager.instance.replace('PageHome');// Swap ``` ### Get Current Level ```typescript const index = StorageManager.getCurrentLevelIndex(); ``` ### Check/Consume Points ```typescript if (StorageManager.hasPoints()) { await UserAssetsManager.consumePoint(levelId, hintIndex); } ``` ### Start Game ```typescript // From PageHome ViewManager.instance.open('PageLevel'); ``` ### Create & Share Challenge ```typescript // User flow: PageHome → [PK Button] → PageWriteLevels [Select 6] → PagePreviewLevels [Verify] → PassModal [Share Button] → WxSDK.shareAppMessage() ``` --- ## File Size & Complexity | File | Lines | Complexity | |------|-------|-----------| | main.ts | 92 | Simple (init only) | | PageLoading.ts | 141 | Medium (parallel loading, sync) | | PageHome.ts | 119 | Simple (two buttons) | | PageLevel.ts | 823 | **Very High** (core game logic) | | PagePreviewLevels.ts | 247 | Medium (scroll list) | | PassModal.ts | 155 | Simple (two buttons) | | Toast.ts | 50 | Simple (fade animation) | | ToastManager.ts | 59 | Simple (factory pattern) | | BaseView.ts | 132 | Medium (lifecycle) | | ViewManager.ts | 320 | High (stack navigation) | **Total: ~2,138 lines** | **Focal Point: PageLevel.ts (38% of code)**