mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-21 13:09:46 +02:00
optimize further
This commit is contained in:
@@ -26,6 +26,7 @@ import {
|
||||
spacing,
|
||||
} from '@/theme';
|
||||
import { createThemedStyles, useColors } from '@/theme/themed';
|
||||
import { SCROLL_PRESS_DELAY, useRipple } from '@/theme/ripple';
|
||||
import type { Palette } from '@/theme/palettes';
|
||||
import { useLibraryStore } from '@/stores/libraryStore';
|
||||
import { usePlayerStore } from '@/stores/playerStore';
|
||||
@@ -291,6 +292,7 @@ function SectionHeader({
|
||||
onPress?: () => void;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
const ripple = useRipple();
|
||||
const colors = useColors();
|
||||
return (
|
||||
<View style={styles.sectionHeader}>
|
||||
@@ -303,7 +305,7 @@ function SectionHeader({
|
||||
</Text>
|
||||
</View>
|
||||
{onPress ? (
|
||||
<Pressable style={styles.seeAllButton} onPress={onPress} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY} style={styles.seeAllButton} onPress={onPress} accessibilityRole="button">
|
||||
<Text variant="label" color={colors.accentText}>
|
||||
See all
|
||||
</Text>
|
||||
@@ -322,6 +324,7 @@ function AlbumRail({
|
||||
onAlbumPress: (album: ArtistAlbum) => void;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
const ripple = useRipple();
|
||||
return (
|
||||
<ScrollView
|
||||
horizontal
|
||||
@@ -329,7 +332,7 @@ function AlbumRail({
|
||||
contentContainerStyle={styles.albumRail}
|
||||
>
|
||||
{albums.map((album) => (
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY}
|
||||
key={album.identity_key}
|
||||
style={styles.albumCard}
|
||||
onPress={() => onAlbumPress(album)}
|
||||
|
||||
@@ -12,12 +12,14 @@ import { Text } from '@/components/Text';
|
||||
import { AlbumGridItem } from '@/components/library/AlbumGridItem';
|
||||
import { spacing } from '@/theme';
|
||||
import { useColors } from '@/theme/themed';
|
||||
import { SCROLL_PRESS_DELAY, useRipple } from '@/theme/ripple';
|
||||
import { useLibraryStore } from '@/stores/libraryStore';
|
||||
import { useSettingsStore } from '@/stores/settingsStore';
|
||||
import { buildArtistDetail } from '@/library/artistDetail';
|
||||
|
||||
export default function ArtistAlbumsScreen() {
|
||||
const colors = useColors();
|
||||
const ripple = useRipple();
|
||||
const router = useRouter();
|
||||
const { name = 'Artist' } = useLocalSearchParams<{ name: string }>();
|
||||
const allTracks = useLibraryStore((s) => s.tracks);
|
||||
@@ -30,7 +32,7 @@ export default function ArtistAlbumsScreen() {
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<Pressable style={styles.back} onPress={() => router.back()} hitSlop={8}>
|
||||
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY} style={styles.back} onPress={() => router.back()} hitSlop={8}>
|
||||
<Ionicons name="chevron-back" size={22} color={colors.textSecondary} />
|
||||
<Text variant="body" color={colors.textSecondary} numberOfLines={1}>
|
||||
{name}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { TrackRow } from '@/components/library/TrackRow';
|
||||
import { TrackActionsSheet } from '@/components/library/TrackActionsSheet';
|
||||
import { spacing } from '@/theme';
|
||||
import { useColors } from '@/theme/themed';
|
||||
import { SCROLL_PRESS_DELAY, useRipple } from '@/theme/ripple';
|
||||
import { useLibraryStore } from '@/stores/libraryStore';
|
||||
import { usePlayerStore } from '@/stores/playerStore';
|
||||
import { useSettingsStore } from '@/stores/settingsStore';
|
||||
@@ -23,6 +24,7 @@ import type { DbTrack } from '@/types/library';
|
||||
|
||||
export default function ArtistAppearancesScreen() {
|
||||
const colors = useColors();
|
||||
const ripple = useRipple();
|
||||
const router = useRouter();
|
||||
const { name = 'Artist' } = useLocalSearchParams<{ name: string }>();
|
||||
const allTracks = useLibraryStore((s) => s.tracks);
|
||||
@@ -43,7 +45,7 @@ export default function ArtistAppearancesScreen() {
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<Pressable style={styles.back} onPress={() => router.back()} hitSlop={8}>
|
||||
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY} style={styles.back} onPress={() => router.back()} hitSlop={8}>
|
||||
<Ionicons name="chevron-back" size={22} color={colors.textSecondary} />
|
||||
<Text variant="body" color={colors.textSecondary} numberOfLines={1}>
|
||||
{name}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { TrackRow } from '@/components/library/TrackRow';
|
||||
import { TrackActionsSheet } from '@/components/library/TrackActionsSheet';
|
||||
import { spacing } from '@/theme';
|
||||
import { useColors } from '@/theme/themed';
|
||||
import { SCROLL_PRESS_DELAY, useRipple } from '@/theme/ripple';
|
||||
import { useLibraryStore } from '@/stores/libraryStore';
|
||||
import { usePlayerStore } from '@/stores/playerStore';
|
||||
import { useSettingsStore } from '@/stores/settingsStore';
|
||||
@@ -23,6 +24,7 @@ import type { DbTrack } from '@/types/library';
|
||||
|
||||
export default function ArtistSongsScreen() {
|
||||
const colors = useColors();
|
||||
const ripple = useRipple();
|
||||
const router = useRouter();
|
||||
const { name = 'Artist' } = useLocalSearchParams<{ name: string }>();
|
||||
const allTracks = useLibraryStore((s) => s.tracks);
|
||||
@@ -43,7 +45,7 @@ export default function ArtistSongsScreen() {
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<Pressable style={styles.back} onPress={() => router.back()} hitSlop={8}>
|
||||
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY} style={styles.back} onPress={() => router.back()} hitSlop={8}>
|
||||
<Ionicons name="chevron-back" size={22} color={colors.textSecondary} />
|
||||
<Text variant="body" color={colors.textSecondary} numberOfLines={1}>
|
||||
{name}
|
||||
|
||||
@@ -39,6 +39,7 @@ import {
|
||||
} from '@/components/search/PullSearchGesture';
|
||||
import { spacing } from '@/theme';
|
||||
import { useColors } from '@/theme/themed';
|
||||
import { useRipple } from '@/theme/ripple';
|
||||
import { useLibraryStore } from '@/stores/libraryStore';
|
||||
import { usePlayerStore } from '@/stores/playerStore';
|
||||
import { useSearchStore } from '@/stores/searchStore';
|
||||
@@ -77,6 +78,7 @@ const ARTIST_SORT_OPTIONS: ArtistSort[] = ['name', 'track_count'];
|
||||
|
||||
export default function LibraryScreen() {
|
||||
const colors = useColors();
|
||||
const ripple = useRipple();
|
||||
const router = useRouter();
|
||||
const viewMode = useLibraryStore((s) => s.viewMode);
|
||||
const setViewMode = useLibraryStore((s) => s.setViewMode);
|
||||
@@ -244,7 +246,7 @@ export default function LibraryScreen() {
|
||||
Library
|
||||
</Text>
|
||||
{!isEmpty ? (
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded}
|
||||
hitSlop={8}
|
||||
onPress={() => openQuickSearch()}
|
||||
accessibilityRole="button"
|
||||
@@ -281,14 +283,14 @@ export default function LibraryScreen() {
|
||||
<Text variant="label">
|
||||
{selectedIds.size} selected
|
||||
</Text>
|
||||
<Pressable onPress={exitSelection} hitSlop={8} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} onPress={exitSelection} hitSlop={8} accessibilityRole="button">
|
||||
<Text variant="label" color={colors.accentText}>
|
||||
Cancel
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
) : sortable ? (
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded}
|
||||
style={styles.sortTrigger}
|
||||
onPress={() => setSortSheetOpen(true)}
|
||||
accessibilityRole="button"
|
||||
|
||||
@@ -27,6 +27,7 @@ import { TextPromptModal } from '@/components/sheets/TextPromptModal';
|
||||
import { CollapsingHeader, useDetailCollapse } from '@/components/library/CollapsingDetail';
|
||||
import { spacing } from '@/theme';
|
||||
import { createThemedStyles, useColors } from '@/theme/themed';
|
||||
import { SCROLL_PRESS_DELAY, useRipple } from '@/theme/ripple';
|
||||
import { usePlaylistStore } from '@/stores/playlistStore';
|
||||
import { usePlayerStore } from '@/stores/playerStore';
|
||||
import { playTracks, shuffleTracks } from '@/audio/playbackController';
|
||||
@@ -54,9 +55,10 @@ function basename(path: string): string {
|
||||
|
||||
function MissingRow({ entry, onLongPress }: { entry: PlaylistTrackEntry; onLongPress: () => void }) {
|
||||
const styles = useStyles();
|
||||
const ripple = useRipple();
|
||||
const colors = useColors();
|
||||
return (
|
||||
<Pressable style={styles.missingRow} onLongPress={onLongPress} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY} style={styles.missingRow} onLongPress={onLongPress} accessibilityRole="button">
|
||||
<View style={styles.missingMeta}>
|
||||
<Text variant="body" numberOfLines={1} color={colors.textTertiary}>
|
||||
{entry.fallback_title ?? basename(entry.track_path)}
|
||||
@@ -74,6 +76,7 @@ type Prompt = { kind: 'rename'; playlist: Playlist } | null;
|
||||
|
||||
export default function PlaylistScreen() {
|
||||
const styles = useStyles();
|
||||
const ripple = useRipple();
|
||||
const colors = useColors();
|
||||
const router = useRouter();
|
||||
const { id } = useLocalSearchParams<{ id: string }>();
|
||||
@@ -283,7 +286,7 @@ export default function PlaylistScreen() {
|
||||
heroMeta={<Text variant="label">{meta}</Text>}
|
||||
heroExtra={
|
||||
isDynamic && playlistId != null ? (
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded} unstable_pressDelay={SCROLL_PRESS_DELAY}
|
||||
style={styles.editRules}
|
||||
onPress={() =>
|
||||
router.push({
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
} from '@/components/sheets/AppSheet';
|
||||
import { fonts, fontSize, radius, spacing } from '@/theme';
|
||||
import { createThemedStyles, useColors } from '@/theme/themed';
|
||||
import { useRipple } from '@/theme/ripple';
|
||||
import { usePlaylistStore } from '@/stores/playlistStore';
|
||||
import {
|
||||
DYNAMIC_PLAYLIST_PRESETS,
|
||||
@@ -327,15 +328,16 @@ function DraftActions({
|
||||
onApply: () => void;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
const ripple = useRipple();
|
||||
const colors = useColors();
|
||||
return (
|
||||
<View style={styles.sheetActions}>
|
||||
<Pressable style={[styles.sheetButton, styles.cancelButton]} onPress={onCancel} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} style={[styles.sheetButton, styles.cancelButton]} onPress={onCancel} accessibilityRole="button">
|
||||
<Text variant="label" color={colors.textSecondary}>
|
||||
Cancel
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded}
|
||||
style={[styles.sheetButton, styles.applyButton, disabled && styles.applyDisabled]}
|
||||
disabled={disabled}
|
||||
onPress={onApply}
|
||||
@@ -529,6 +531,7 @@ function ConditionEditorSheet({
|
||||
onApply: () => void;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
const ripple = useRipple();
|
||||
const colors = useColors();
|
||||
const draft = target.draft;
|
||||
const error = validateCondition(draft);
|
||||
@@ -536,7 +539,7 @@ function ConditionEditorSheet({
|
||||
return (
|
||||
<AppSheet onClose={onCancel}>
|
||||
<AppSheetTitle title={target.mode === 'new' ? 'Add filter' : 'Edit filter'} />
|
||||
<Pressable style={styles.sheetSelectRow} onPress={onChangeField} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} style={styles.sheetSelectRow} onPress={onChangeField} accessibilityRole="button">
|
||||
<View style={styles.sheetSelectText}>
|
||||
<Text variant="caption" color={colors.textTertiary}>
|
||||
FIELD
|
||||
@@ -568,7 +571,7 @@ function ConditionEditorSheet({
|
||||
|
||||
<View style={styles.conditionSheetFooter}>
|
||||
{target.mode === 'edit' ? (
|
||||
<Pressable style={styles.removeButton} onPress={onRemove} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} style={styles.removeButton} onPress={onRemove} accessibilityRole="button">
|
||||
<Ionicons name="trash-outline" size={17} color={colors.warning} />
|
||||
<Text variant="label" color={colors.warning}>
|
||||
Remove
|
||||
@@ -713,11 +716,12 @@ function FilterCard({
|
||||
onRemove: () => void;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
const ripple = useRipple();
|
||||
const colors = useColors();
|
||||
const option = fieldOptionForKey(getConditionFieldKey(condition));
|
||||
|
||||
return (
|
||||
<Pressable style={styles.ruleCard} onPress={onPress} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} style={styles.ruleCard} onPress={onPress} accessibilityRole="button">
|
||||
<View style={styles.cardIcon}>
|
||||
<Ionicons name={option?.icon ?? 'options-outline'} size={18} color={colors.accent} />
|
||||
</View>
|
||||
@@ -729,7 +733,7 @@ function FilterCard({
|
||||
{fieldGroupLabel(condition)}
|
||||
</Text>
|
||||
</View>
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded}
|
||||
style={styles.cardRemove}
|
||||
onPress={onRemove}
|
||||
hitSlop={8}
|
||||
@@ -744,6 +748,7 @@ function FilterCard({
|
||||
|
||||
export default function DynamicPlaylistEditorScreen() {
|
||||
const styles = useStyles();
|
||||
const ripple = useRipple();
|
||||
const colors = useColors();
|
||||
const router = useRouter();
|
||||
const { id } = useLocalSearchParams<{ id?: string }>();
|
||||
@@ -1036,7 +1041,7 @@ export default function DynamicPlaylistEditorScreen() {
|
||||
>
|
||||
<Screen padded={false}>
|
||||
<View style={styles.header}>
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded}
|
||||
onPress={() => router.back()}
|
||||
hitSlop={8}
|
||||
style={styles.headerButton}
|
||||
@@ -1080,7 +1085,7 @@ export default function DynamicPlaylistEditorScreen() {
|
||||
contentContainerStyle={styles.presetRow}
|
||||
>
|
||||
{DYNAMIC_PLAYLIST_PRESETS.map((preset) => (
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded}
|
||||
key={preset.id}
|
||||
style={styles.presetChip}
|
||||
onPress={() => applyPreset(preset.rules)}
|
||||
@@ -1100,7 +1105,7 @@ export default function DynamicPlaylistEditorScreen() {
|
||||
<Text variant="caption" style={styles.sectionLabel}>
|
||||
FILTERS
|
||||
</Text>
|
||||
<Pressable style={styles.inlineAction} onPress={() => openFieldPicker('new')} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} style={styles.inlineAction} onPress={() => openFieldPicker('new')} accessibilityRole="button">
|
||||
<Ionicons name="add" size={16} color={colors.accent} />
|
||||
<Text variant="label" color={colors.accent}>
|
||||
Add filter
|
||||
@@ -1133,7 +1138,7 @@ export default function DynamicPlaylistEditorScreen() {
|
||||
<Text variant="caption" style={styles.sectionLabel}>
|
||||
ORDER
|
||||
</Text>
|
||||
<Pressable style={styles.sortCard} onPress={openSortSheet} accessibilityRole="button">
|
||||
<Pressable android_ripple={ripple.bounded} style={styles.sortCard} onPress={openSortSheet} accessibilityRole="button">
|
||||
<View style={styles.cardIcon}>
|
||||
<Ionicons name="swap-vertical" size={18} color={colors.accent} />
|
||||
</View>
|
||||
@@ -1161,7 +1166,7 @@ export default function DynamicPlaylistEditorScreen() {
|
||||
{status.label}
|
||||
</Text>
|
||||
</View>
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded}
|
||||
style={[styles.previewButton, normalizedRulesError !== null && styles.disabled]}
|
||||
disabled={normalizedRulesError !== null}
|
||||
onPress={() => setSheet({ kind: 'preview' })}
|
||||
@@ -1172,7 +1177,7 @@ export default function DynamicPlaylistEditorScreen() {
|
||||
Preview
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Pressable
|
||||
<Pressable android_ripple={ripple.bounded}
|
||||
style={[styles.saveButton, saveDisabled && styles.disabled]}
|
||||
disabled={saveDisabled}
|
||||
onPress={save}
|
||||
|
||||
Reference in New Issue
Block a user