94 lines
3.8 KiB
Markdown
94 lines
3.8 KiB
Markdown
---
|
|
phase: 42-wallpapers-social-format-conversion-voice
|
|
plan: 04
|
|
subsystem: ui
|
|
tags: [voice, whisper, offline-badge, react-hook, lucide-react, typescript]
|
|
|
|
# Dependency graph
|
|
requires:
|
|
- phase: 42-wallpapers-social-format-conversion-voice
|
|
provides: Plan 01 foundation types and server hardware route at /api/system/providers
|
|
affects:
|
|
- 42-06 (UI wiring — voice offline badge now visible in ChatInput)
|
|
|
|
provides:
|
|
- useSystemProviders hook fetching /api/system/providers and exposing whisperAvailable/piperAvailable
|
|
- Offline badge in ChatInput (WifiOff icon + "Offline" label) when local Whisper binary detected
|
|
|
|
# Tech tracking
|
|
tech-stack:
|
|
added: []
|
|
patterns:
|
|
- Simple one-shot fetch hook (no SWR/React Query) for UI capability flags
|
|
- Graceful degradation: badge absent when providers null (fetch error or Whisper not installed)
|
|
|
|
key-files:
|
|
created:
|
|
- ui/src/hooks/useSystemProviders.ts
|
|
modified:
|
|
- ui/src/components/ChatInput.tsx
|
|
|
|
key-decisions:
|
|
- "useSystemProviders uses plain useState+useEffect fetch (not React Query) — matches plan spec and keeps hook lightweight for a one-time capability probe"
|
|
- "Hook maps voiceCapability from HardwareInfo response shape — /api/system/providers returns full HardwareInfo, whisperAvailable lives in voiceCapability sub-object"
|
|
|
|
patterns-established:
|
|
- "Offline badge pattern: enableVoiceInput && providers?.whisperAvailable — double guard ensures badge only shows in voice mode with confirmed local model"
|
|
|
|
requirements-completed: [VOICE-01, VOICE-02, VOICE-03]
|
|
|
|
# Metrics
|
|
duration: 2min
|
|
completed: 2026-04-04
|
|
---
|
|
|
|
# Phase 42 Plan 04: Voice Offline Badge and useSystemProviders Hook
|
|
|
|
**useSystemProviders hook wires /api/system/providers to ChatInput offline badge, surfacing local Whisper availability via WifiOff icon when voice mode is active**
|
|
|
|
## Performance
|
|
|
|
- **Duration:** 2 min
|
|
- **Started:** 2026-04-04T22:12:11Z
|
|
- **Completed:** 2026-04-04T22:14:00Z
|
|
- **Tasks:** 2
|
|
- **Files modified:** 2 (1 created, 1 modified)
|
|
|
|
## Accomplishments
|
|
- Created useSystemProviders hook that fetches /api/system/providers once on mount, extracts voiceCapability.whisperAvailable, and returns null providers on error for graceful degradation
|
|
- Added WifiOff icon offline badge to ChatInput — renders only when enableVoiceInput=true AND providers.whisperAvailable=true
|
|
- Verified VoiceMicButton and VoiceModeToggle already rendering correctly from prior phase work (no changes needed)
|
|
|
|
## Task Commits
|
|
|
|
Each task was committed atomically:
|
|
|
|
1. **Task 1: Create useSystemProviders hook** - `768f62fa` (feat)
|
|
2. **Task 2: Add offline badge to ChatInput** - `69ae0a00` (feat)
|
|
|
|
## Files Created/Modified
|
|
- `ui/src/hooks/useSystemProviders.ts` - One-shot fetch hook for system providers; exports SystemProviders interface and useSystemProviders function
|
|
- `ui/src/components/ChatInput.tsx` - Added WifiOff import, useSystemProviders call, and offline badge JSX next to VoiceMicButton
|
|
|
|
## Decisions Made
|
|
- Used plain useState+useEffect pattern (not React Query / useHardwareInfo) as the plan specified — the hook is intentionally lightweight for a one-time capability probe
|
|
- Mapped voiceCapability sub-object from HardwareInfo since the /api/system/providers endpoint returns the full hardware info shape; whisperAvailable lives at `data.voiceCapability.whisperAvailable`
|
|
|
|
## Deviations from Plan
|
|
|
|
None - plan executed exactly as written.
|
|
|
|
## Issues Encountered
|
|
None.
|
|
|
|
## User Setup Required
|
|
None - no external service configuration required.
|
|
|
|
## Next Phase Readiness
|
|
- Offline badge available in ChatInput; voice UI feature surface is now complete
|
|
- Plan 06 (UI wiring) can wire enableVoiceInput prop from user settings/mode state
|
|
- Voice mode toggle and mic button confirmed rendering correctly when enableVoiceInput=true
|
|
|
|
---
|
|
*Phase: 42-wallpapers-social-format-conversion-voice*
|
|
*Completed: 2026-04-04*
|