Transcript Display
System Intent
- What this is: A React Native component (
main/app/components/memory/TranscriptDisplay.tsx) that fetches and renders the plaintext transcript for an audio memory. It is rendered below the AudioPlayer inside MemoryViewerModal whenever the active memory has type: "audio". The component calls getMemoryTranscript (main/app/lib/api/memory/transcript.ts) which hits GET /memories/{memory_id}/transcript. On success the full transcript is shown in a scrollable view. On error a retry button is offered. When no transcript exists the component shows a static placeholder. The component does not implement playback-position synchronisation or segment highlighting — it renders the full transcript as a flat block of text.
Mermaid Diagram
flowchart TD
Mount[TranscriptDisplay mounts] --> Fetch[getMemoryTranscript memory_id]
Fetch -->|success, transcript string| ShowText[ScrollView with transcript text]
Fetch -->|success, transcript empty or null| ShowPlaceholder[No transcript available]
Fetch -->|error| ShowError[Error message + Retry button]
ShowError -->|user taps Retry| IncrRetry[increment retryCount]
IncrRetry --> Fetch
Flows
Flow: transcriptFetch
- Core files:
main/app/components/memory/TranscriptDisplay.tsx, main/app/lib/api/memory/transcript.ts - Test files: none currently
Types
TranscriptDisplayProps {
memoryId: string (required)
}
GetMemoryTranscriptParams {
memory_id: string
}
GetMemoryTranscriptResponse {
memory_id: string
transcript: string
processing_status: "complete" | "pending" | "failed"
presigned_url?: string
timestamp: string
}
Paths
| path | input | output | path-type | notes |
transcriptFetch.ready | memoryId, API returns transcript string | ScrollView renders transcript text (color #E5E7EB, 14 px, lineHeight 20) | happy path | |
transcriptFetch.noTranscript | memoryId, API returns empty/null transcript | Placeholder text "No transcript available" (color #9CA3AF, 13 px, centred) | happy path | |
transcriptFetch.error | API throws or returns error | Warning icon + red error message + Retry Pressable | error | retryCount incremented on tap; new fetch triggered |
transcriptFetch.loading | fetch in flight | ActivityIndicator (white, small, testID transcript-loading) | happy path | |
Pseudocode
mount / memoryId change / retryCount change:
cancelled = false
setLoading(true)
try:
data = await getMemoryTranscript({ memory_id: memoryId })
if !cancelled:
setTranscript(data.transcript)
setError(null)
catch err:
if !cancelled:
setError(err.message ?? "Failed to load transcript")
setTranscript(null)
finally:
if !cancelled: setLoading(false)
return () => { cancelled = true }
handleRetry():
setError(null)
setRetryCount(c => c + 1) // triggers re-run of above effect
Flow: transcriptAPI
- Core files:
main/app/lib/api/memory/transcript.ts - Test files: none currently
Types
GetMemoryTranscriptParams {
memory_id: string
}
GetMemoryTranscriptResponse (Zod-validated) {
memory_id: string
transcript: string
processing_status: "complete" | "pending" | "failed"
presigned_url?: string (optional)
timestamp: string
}
Paths
| path | input | output | path-type | notes |
transcriptAPI.success | valid memory_id | GetMemoryTranscriptResponse | happy path | response validated with Zod schema |
transcriptAPI.error | network failure, HTTP 4xx/5xx, or parse error | throws Error | error | caller (TranscriptDisplay) catches and surfaces retry UI |
Pseudocode
getMemoryTranscript({ memory_id }):
api = getApi()
response = await api.get(`/memories/${memory_id}/transcript`, { timeout: 120_000 })
return GetMemoryTranscriptResponseSchema.parse(response.data.data)
Notes: - Timeout is 120 s to match the Lambda's own timeout in template.yaml. - Zod schema enforces shape at runtime; a malformed response throws a ZodError which propagates as a generic fetch error to the component.
Logs
| Source | Location |
| React Native | Metro / device console |
Deployment
- Mechanism:
local only - Deploy command:
cd main/app && npx expo start
- Notes: Expo managed workflow.
TranscriptDisplay is a pure React Native component with no native module dependencies beyond @expo/vector-icons.