custom linear haptics

This commit is contained in:
Boof2015
2026-07-13 02:20:57 -04:00
parent a34d9cba89
commit 261d095090
42 changed files with 1569 additions and 89 deletions
+6 -1
View File
@@ -5,6 +5,7 @@ import { spacing } from '@/theme';
import { ACCENTS, ACCENT_IDS, type AccentId } from '@/theme/accents';
import { createThemedStyles, useColors } from '@/theme/themed';
import { useRipple } from '@/theme/ripple';
import { playHaptic } from '@/lib/haptics';
const SWATCH_SIZE = 36;
@@ -26,7 +27,11 @@ export function AccentSwatchRow({ value, onChange }: AccentSwatchRowProps) {
return (
<Pressable android_ripple={ripple.bounded}
key={id}
onPress={() => onChange(id)}
onPress={() => {
if (selected) return;
playHaptic('selection');
onChange(id);
}}
accessibilityRole="radio"
accessibilityState={{ selected }}
accessibilityLabel={`${ACCENTS[id].label} accent`}
+8 -1
View File
@@ -4,6 +4,7 @@ import { radius, spacing } from '@/theme';
import { createThemedStyles, useColors } from '@/theme/themed';
import { useRipple } from '@/theme/ripple';
import type { NowPlayingScopeStyle } from '@/stores/settingsStore';
import { playHaptic } from '@/lib/haptics';
interface ScopeStyleCardsProps {
/** null renders neither card selected (onboarding: no preselection bias). */
@@ -59,11 +60,17 @@ function StyleCard({
const colors = useColors();
const ripple = useRipple();
const handlePress = () => {
if (selected) return;
playHaptic('selection');
onPress();
};
return (
<Pressable
android_ripple={ripple.bounded}
style={[styles.card, selected && styles.cardSelected]}
onPress={onPress}
onPress={handlePress}
accessibilityRole="radio"
accessibilityState={{ selected }}
accessibilityLabel={`${title}. ${description}`}
+16 -3
View File
@@ -27,6 +27,7 @@ import { useSettingsStore } from '@/stores/settingsStore';
import { useThemeStore } from '@/stores/themeStore';
import type { LastFmStatus } from '@/types/lastFm';
import { Text } from '@/components/Text';
import { playHaptic } from '@/lib/haptics';
export function lastFmScrobbleSubtitle(status: LastFmStatus | null): string {
const connected = status?.profiles.filter((p) => p.connected).length ?? 0;
@@ -110,7 +111,11 @@ export function AppearanceSettingsPanel() {
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY}
key={option.id}
style={[styles.option, selected && styles.optionSelected]}
onPress={() => void setBaseTheme(option.id)}
onPress={() => {
if (selected) return;
playHaptic('selection');
void setBaseTheme(option.id);
}}
accessibilityRole="radio"
accessibilityState={{ selected }}
>
@@ -331,7 +336,11 @@ export function LibrarySettingsPanel() {
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY}
key={option.mode}
style={[styles.option, selected && styles.optionSelected]}
onPress={() => void setArtistGroupingMode(option.mode)}
onPress={() => {
if (selected) return;
playHaptic('selection');
void setArtistGroupingMode(option.mode);
}}
accessibilityRole="radio"
accessibilityState={{ selected }}
>
@@ -418,7 +427,11 @@ export function AudioSettingsPanel() {
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY}
key={m.mode}
style={[styles.modePill, selected && styles.modePillSelected]}
onPress={() => void setReplayGainMode(m.mode)}
onPress={() => {
if (selected) return;
playHaptic('selection');
void setReplayGainMode(m.mode);
}}
>
<Text variant="label" color={selected ? colors.accentTextStrong : colors.textSecondary}>
{m.label}
@@ -3,7 +3,6 @@ import {
Pressable,
ScrollView,
StyleSheet,
Switch,
View,
type StyleProp,
type ViewStyle,
@@ -15,6 +14,7 @@ import { Text } from '@/components/Text';
import { radius, spacing } from '@/theme';
import { createThemedStyles, useColors } from '@/theme/themed';
import { SCROLL_PRESS_DELAY, useRipple } from '@/theme/ripple';
import { HapticSwitch } from '@/components/HapticSwitch';
export type SettingsIconName = keyof typeof Ionicons.glyphMap;
@@ -148,7 +148,7 @@ export function SettingsToggleRow({
{description}
</Text>
</View>
<Switch
<HapticSwitch
value={value}
onValueChange={onValueChange}
trackColor={{ false: colors.glassBorder, true: colors.accent }}