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:
parent
bd8d5a3072
commit
7db32ca606
@ -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,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user