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