import React, { useState, useRef } from 'react'; import { StyleSheet, Text, View, TextInput, Button, ScrollView, Alert } from 'react-native'; import { Audio } from 'expo-av'; import * as FileSystem from 'expo-file-system'; export default function App() { const [apiBase, setApiBase] = useState('http://localhost:3000'); const [recording, setRecording] = useState(null); const [transcript, setTranscript] = useState(''); const [variantsRaw, setVariantsRaw] = useState(''); const [tone, setTone] = useState('professional'); const startRecording = async () => { try { await Audio.requestPermissionsAsync(); await Audio.setAudioModeAsync({ allowsRecordingIOS: true, playsInSilentModeIOS: true }); const { recording } = await Audio.Recording.createAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY); setRecording(recording); } catch (err) { console.error('startRecording', err); Alert.alert('Recording error'); } }; const stopRecording = async () => { try { await recording.stopAndUnloadAsync(); const uri = recording.getURI(); setRecording(null); Alert.alert('Recorded', `Saved at ${uri}`); // Upload and transcribe sample flow: request signed URL const filename = uri.split('/').pop(); const stat = await FileSystem.getInfoAsync(uri); const payload = { filename, contentType: 'audio/webm', length: stat.size }; const signed = await fetch(apiBase + '/api/signed-upload', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify(payload) }); const j = await signed.json(); // Upload file with PUT const fileData = await FileSystem.readAsStringAsync(uri, { encoding: FileSystem.EncodingType.Base64 }); const put = await fetch(j.uploadUrl, { method: 'PUT', headers: {'Content-Type':'audio/webm'}, body: Buffer.from(fileData, 'base64') }); if (!put.ok) throw new Error('upload failed'); // Start transcribe const tResp = await fetch(apiBase + '/api/transcribe/start', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ objectKey: j.objectKey, entryId: `expo-${Date.now()}`, anonymize: false, language: 'en' }) }); const tJson = await tResp.json(); Alert.alert('Transcription started', JSON.stringify(tJson)); } catch (err) { console.error('stopRecording', err); Alert.alert('Error', String(err)); } }; const generate = async () => { try { const resp = await fetch(apiBase + '/api/generate-post', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ sanitizedText: transcript, tone, maxChars: 400, variants: 2 }) }); const j = await resp.json(); setVariantsRaw(JSON.stringify(j, null, 2)); Alert.alert('Generated'); } catch (err) { console.error(err); Alert.alert('Generate failed'); } }; return ( Journaling AI Demo (Expo) API Base URL Transcript