mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-19 12:14:47 +02:00
sharable eq
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
View
|
||||
} from 'react-native';
|
||||
import { BottomSheetTextInput } from '@gorhom/bottom-sheet';
|
||||
import { Text } from '@/components/Text';
|
||||
import {
|
||||
fonts,
|
||||
radius,
|
||||
spacing,
|
||||
} from '@/theme';
|
||||
import { createThemedStyles, useColors } from '@/theme/themed';
|
||||
import { EqSheet } from './EqSheet';
|
||||
|
||||
interface EQPresetNameSheetProps {
|
||||
defaultName: string;
|
||||
actionLabel: string;
|
||||
onSubmit: (name: string) => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function EQPresetNameSheet({
|
||||
defaultName,
|
||||
actionLabel,
|
||||
onSubmit,
|
||||
onClose,
|
||||
}: EQPresetNameSheetProps) {
|
||||
const styles = useStyles();
|
||||
const colors = useColors();
|
||||
const [name, setName] = useState(defaultName);
|
||||
const trimmed = name.trim();
|
||||
|
||||
const submit = () => {
|
||||
if (!trimmed) return;
|
||||
onClose();
|
||||
onSubmit(trimmed);
|
||||
};
|
||||
|
||||
return (
|
||||
<EqSheet onClose={onClose}>
|
||||
<Text variant="heading" style={styles.title}>
|
||||
Name preset
|
||||
</Text>
|
||||
<BottomSheetTextInput
|
||||
value={name}
|
||||
onChangeText={setName}
|
||||
placeholder="Preset name"
|
||||
placeholderTextColor={colors.textTertiary}
|
||||
style={styles.input}
|
||||
autoFocus
|
||||
selectTextOnFocus
|
||||
maxLength={40}
|
||||
returnKeyType="done"
|
||||
onSubmitEditing={submit}
|
||||
/>
|
||||
<View style={styles.actions}>
|
||||
<Pressable style={[styles.btn, styles.cancel]} onPress={onClose}>
|
||||
<Text variant="label" color={colors.textSecondary}>
|
||||
Cancel
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Pressable style={[styles.btn, styles.primary, !trimmed && styles.disabled]} disabled={!trimmed} onPress={submit}>
|
||||
<Text variant="label" color={colors.accentTextStrong}>
|
||||
{actionLabel}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</EqSheet>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createThemedStyles((colors) => ({
|
||||
title: {
|
||||
marginTop: spacing.xs,
|
||||
marginBottom: spacing.md,
|
||||
},
|
||||
input: {
|
||||
color: colors.textPrimary,
|
||||
fontFamily: fonts.sans.regular,
|
||||
fontSize: 16,
|
||||
paddingHorizontal: spacing.md,
|
||||
paddingVertical: spacing.md,
|
||||
borderRadius: radius.md,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.glassBorder,
|
||||
backgroundColor: colors.glassBg,
|
||||
},
|
||||
actions: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
gap: spacing.sm,
|
||||
marginTop: spacing.lg,
|
||||
},
|
||||
btn: {
|
||||
paddingHorizontal: spacing.xl,
|
||||
paddingVertical: spacing.md,
|
||||
borderRadius: radius.pill,
|
||||
},
|
||||
cancel: {
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.glassBorder,
|
||||
},
|
||||
primary: {
|
||||
backgroundColor: colors.accentGlow,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.accent,
|
||||
},
|
||||
disabled: {
|
||||
opacity: 0.4,
|
||||
},
|
||||
}));
|
||||
|
||||
export default EQPresetNameSheet;
|
||||
@@ -0,0 +1,133 @@
|
||||
import {
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
View
|
||||
} from 'react-native';
|
||||
import { Text } from '@/components/Text';
|
||||
import {
|
||||
radius,
|
||||
spacing,
|
||||
} from '@/theme';
|
||||
import { createThemedStyles, useColors } from '@/theme/themed';
|
||||
import type { EQPreset } from '@/types/audio';
|
||||
import { EqSheet } from './EqSheet';
|
||||
import { formatGain } from './format';
|
||||
|
||||
interface EQPresetPreviewSheetProps {
|
||||
preset: EQPreset;
|
||||
title?: string;
|
||||
confirmLabel?: string;
|
||||
onConfirm: () => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function EQPresetPreviewSheet({
|
||||
preset,
|
||||
title = 'Import preset',
|
||||
confirmLabel = 'Import and Apply',
|
||||
onConfirm,
|
||||
onClose,
|
||||
}: EQPresetPreviewSheetProps) {
|
||||
const styles = useStyles();
|
||||
const colors = useColors();
|
||||
const enabledBands = preset.bands.filter((band) => band.enabled).length;
|
||||
const modeLabel = preset.mode === 'graphic' ? 'Graphic' : 'Parametric';
|
||||
|
||||
return (
|
||||
<EqSheet onClose={onClose}>
|
||||
<Text variant="heading" style={styles.title}>
|
||||
{title}
|
||||
</Text>
|
||||
<View style={styles.preview}>
|
||||
<Text variant="body" numberOfLines={1} color={colors.textPrimary}>
|
||||
{preset.name}
|
||||
</Text>
|
||||
<View style={styles.metaRow}>
|
||||
<Text variant="caption" color={colors.textTertiary}>
|
||||
Mode
|
||||
</Text>
|
||||
<Text variant="label" color={colors.textSecondary}>
|
||||
{modeLabel}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.metaRow}>
|
||||
<Text variant="caption" color={colors.textTertiary}>
|
||||
Preamp
|
||||
</Text>
|
||||
<Text variant="label" color={colors.textSecondary}>
|
||||
{formatGain(preset.preamp)} dB
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.metaRow}>
|
||||
<Text variant="caption" color={colors.textTertiary}>
|
||||
Bands
|
||||
</Text>
|
||||
<Text variant="label" color={colors.textSecondary}>
|
||||
{enabledBands}/{preset.bands.length}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.actions}>
|
||||
<Pressable style={[styles.btn, styles.cancel]} onPress={onClose}>
|
||||
<Text variant="label" color={colors.textSecondary}>
|
||||
Cancel
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Pressable
|
||||
style={[styles.btn, styles.primary]}
|
||||
onPress={() => {
|
||||
onConfirm();
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<Text variant="label" color={colors.accentTextStrong}>
|
||||
{confirmLabel}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</EqSheet>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createThemedStyles((colors) => ({
|
||||
title: {
|
||||
marginTop: spacing.xs,
|
||||
marginBottom: spacing.md,
|
||||
},
|
||||
preview: {
|
||||
borderRadius: radius.md,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.glassBorder,
|
||||
backgroundColor: colors.glassBg,
|
||||
padding: spacing.md,
|
||||
gap: spacing.sm,
|
||||
},
|
||||
metaRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
gap: spacing.md,
|
||||
},
|
||||
actions: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
gap: spacing.sm,
|
||||
marginTop: spacing.lg,
|
||||
},
|
||||
btn: {
|
||||
paddingHorizontal: spacing.lg,
|
||||
paddingVertical: spacing.md,
|
||||
borderRadius: radius.pill,
|
||||
},
|
||||
cancel: {
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.glassBorder,
|
||||
},
|
||||
primary: {
|
||||
backgroundColor: colors.accentGlow,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.accent,
|
||||
},
|
||||
}));
|
||||
|
||||
export default EQPresetPreviewSheet;
|
||||
@@ -0,0 +1,75 @@
|
||||
import {
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
View
|
||||
} from 'react-native';
|
||||
import QRCode from 'react-native-qrcode-svg';
|
||||
import { Text } from '@/components/Text';
|
||||
import {
|
||||
radius,
|
||||
spacing,
|
||||
} from '@/theme';
|
||||
import { createThemedStyles, useColors } from '@/theme/themed';
|
||||
import { EqSheet } from './EqSheet';
|
||||
|
||||
interface EQPresetQrSheetProps {
|
||||
presetName: string;
|
||||
value: string;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function EQPresetQrSheet({ presetName, value, onClose }: EQPresetQrSheetProps) {
|
||||
const styles = useStyles();
|
||||
const colors = useColors();
|
||||
|
||||
return (
|
||||
<EqSheet onClose={onClose}>
|
||||
<Text variant="heading" style={styles.title}>
|
||||
Preset QR
|
||||
</Text>
|
||||
<View style={styles.qrWrap}>
|
||||
<QRCode value={value} size={220} color="#000000" backgroundColor="#ffffff" quietZone={12} ecl="M" />
|
||||
</View>
|
||||
<Text variant="label" numberOfLines={1} color={colors.textSecondary} style={styles.name}>
|
||||
{presetName}
|
||||
</Text>
|
||||
<Pressable style={styles.done} onPress={onClose}>
|
||||
<Text variant="label" color={colors.accentTextStrong}>
|
||||
Done
|
||||
</Text>
|
||||
</Pressable>
|
||||
</EqSheet>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createThemedStyles((colors) => ({
|
||||
title: {
|
||||
marginTop: spacing.xs,
|
||||
marginBottom: spacing.md,
|
||||
},
|
||||
qrWrap: {
|
||||
alignSelf: 'center',
|
||||
padding: spacing.md,
|
||||
borderRadius: radius.md,
|
||||
backgroundColor: '#ffffff',
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.glassBorder,
|
||||
},
|
||||
name: {
|
||||
alignSelf: 'center',
|
||||
maxWidth: 260,
|
||||
marginTop: spacing.md,
|
||||
},
|
||||
done: {
|
||||
alignSelf: 'flex-end',
|
||||
marginTop: spacing.lg,
|
||||
paddingHorizontal: spacing.xl,
|
||||
paddingVertical: spacing.md,
|
||||
borderRadius: radius.pill,
|
||||
backgroundColor: colors.accentGlow,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.accent,
|
||||
},
|
||||
}));
|
||||
|
||||
export default EQPresetQrSheet;
|
||||
Reference in New Issue
Block a user