feat(coach): Instagram-style voice recording bar

Beim Aufnehmen ersetzt jetzt eine volle Pill-Bar die Eingabe:
  - Links: Trash-Icon (neutral, dezent)
  - Mitte: Live-Dot (brandOrange) + animierte Waveform-Bars + Timer
  - Rechts: Senden-Button (brandOrange, Pfeil-Icon)

Keine roten Farben mehr, kein separater Mic-Button beim Aufnehmen.
Mic-Button verschwindet komplett während Recording (erst wieder
sichtbar wenn aufgehört). Konsistent mit Rebreak-Farbschema.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chahinebrini 2026-06-01 10:47:08 +02:00
parent bd8d5a3072
commit 7db32ca606

View File

@ -652,15 +652,36 @@ export default function CoachScreen() {
{/* Input bar */} {/* Input bar */}
<View style={[styles.inputBar, { paddingBottom: keyboardHeight > 0 ? 8 : Math.max(12, insets.bottom), backgroundColor: colors.bg, borderTopColor: colors.border }]}> <View style={[styles.inputBar, { paddingBottom: keyboardHeight > 0 ? 8 : Math.max(12, insets.bottom), backgroundColor: colors.bg, borderTopColor: colors.border }]}>
{isRecording ? ( {isRecording ? (
<View style={styles.recordingContainer}> /* ── Instagram-style Recording Bar ─────────────────────── */
<TouchableOpacity style={styles.cancelBtn} onPress={cancelRecording} activeOpacity={0.7}> <View style={[styles.recordingBar, { backgroundColor: colors.surfaceElevated, borderColor: colors.border }]}>
<Ionicons name="trash" size={16} color="#f87171" /> {/* Trash - links */}
<TouchableOpacity
style={[styles.recSideBtn, { backgroundColor: colors.bg }]}
onPress={cancelRecording}
activeOpacity={0.7}
>
<Ionicons name="trash-outline" size={17} color={colors.textMuted} />
</TouchableOpacity> </TouchableOpacity>
<View style={styles.pulseDot} />
<Text style={styles.recordingTimer}>{formatDuration(recordingDuration)}</Text> {/* Waveform + Timer - mitte */}
<View style={{ flex: 1 }}> <View style={styles.recCenter}>
<VoiceBars count={18} baseColor="#f87171" /> <View style={[styles.recLiveDot, { backgroundColor: colors.brandOrange }]} />
<View style={{ flex: 1 }}>
<VoiceBars count={22} baseColor={colors.text} />
</View>
<Text style={[styles.recTimer, { color: colors.textMuted }]}>
{formatDuration(recordingDuration)}
</Text>
</View> </View>
{/* Send - rechts */}
<TouchableOpacity
style={[styles.recSideBtn, { backgroundColor: colors.brandOrange }]}
onPress={onMicUp}
activeOpacity={0.8}
>
<Ionicons name="arrow-up" size={18} color="#fff" />
</TouchableOpacity>
</View> </View>
) : isTranscribing ? ( ) : isTranscribing ? (
<View style={styles.transcribingRow}> <View style={styles.transcribingRow}>
@ -681,19 +702,15 @@ export default function CoachScreen() {
/> />
)} )}
{!isTranscribing && ( {!isRecording && !isTranscribing && (
<TouchableOpacity <TouchableOpacity
style={[styles.micBtn, { backgroundColor: colors.surfaceElevated }, isRecording && styles.micBtnActive, thinking && styles.micBtnDisabled]} style={[styles.micBtn, { backgroundColor: colors.surfaceElevated }, thinking && styles.micBtnDisabled]}
onPressIn={onMicDown} onPressIn={onMicDown}
onPressOut={onMicUp} onPressOut={onMicUp}
disabled={thinking} disabled={thinking}
activeOpacity={0.7} activeOpacity={0.7}
> >
<Ionicons <Ionicons name="mic" size={18} color={colors.textMuted} />
name={isRecording ? 'square' : 'mic'}
size={18}
color={isRecording ? '#fff' : colors.textMuted}
/>
</TouchableOpacity> </TouchableOpacity>
)} )}
@ -960,37 +977,39 @@ const styles = StyleSheet.create({
sendBtnDisabled: { sendBtnDisabled: {
opacity: 0.4, opacity: 0.4,
}, },
recordingContainer: { recordingBar: {
flex: 1, flex: 1,
height: 38, height: 44,
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
gap: 8, gap: 8,
backgroundColor: 'rgba(220,38,38,0.08)', borderWidth: StyleSheet.hairlineWidth,
borderWidth: 1,
borderColor: 'rgba(220,38,38,0.2)',
borderRadius: 22, borderRadius: 22,
paddingHorizontal: 12, paddingHorizontal: 6,
}, },
cancelBtn: { recSideBtn: {
width: 32, width: 32,
height: 32, height: 32,
borderRadius: 16, borderRadius: 16,
backgroundColor: 'rgba(220,38,38,0.15)',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
}, },
pulseDot: { recCenter: {
width: 8, flex: 1,
height: 8, flexDirection: 'row',
borderRadius: 4, alignItems: 'center',
backgroundColor: '#dc2626', gap: 6,
}, },
recordingTimer: { recLiveDot: {
fontSize: 13, width: 7,
height: 7,
borderRadius: 3.5,
},
recTimer: {
fontSize: 12,
fontFamily: 'Nunito_600SemiBold', fontFamily: 'Nunito_600SemiBold',
color: '#f87171',
fontVariant: ['tabular-nums'], fontVariant: ['tabular-nums'],
minWidth: 32,
}, },
transcribingRow: { transcribingRow: {
flex: 1, flex: 1,