fix internal routing, and remove softlocking

This commit is contained in:
Boof2015
2026-07-25 11:12:02 -04:00
parent 098992639d
commit 0f34ca2e8d
33 changed files with 904 additions and 157 deletions
+10
View File
@@ -1,6 +1,16 @@
import { Stack } from 'expo-router';
import { useColors } from '@/theme/themed';
/**
* Anchor the library stack at its list. Without this, navigating straight to a
* detail route (from Home, quick search, or the now-playing overlay) builds a
* stack of just `[album]` with nothing beneath it — so popping one level had
* nowhere to go and back escaped the tab entirely.
*/
export const unstable_settings = {
initialRouteName: 'index',
};
/**
* Nested stack inside the Library tab so album/artist detail screens keep the
* tab bar + mini-player visible.
+3 -2
View File
@@ -40,7 +40,7 @@ export default function AlbumScreen() {
const { key } = useLocalSearchParams<{ key: string }>();
const { items: tracks, summary: album, totalCount, loadMore } = useNativeAlbumDetail(key);
const currentPath = usePlayerStore((s) => s.currentTrack?.path);
const handleBack = useLibraryDetailBack();
const { goBack, backLabel } = useLibraryDetailBack();
const insets = useSafeAreaInsets();
const { scrollY, heroFaded, collapsed, onScroll, scrollEventThrottle, expandedHeight, onHeroBlockLayout } =
useDetailCollapse();
@@ -154,7 +154,8 @@ export default function AlbumScreen() {
</>
}
disabled={tracks.length === 0}
onBack={handleBack}
onBack={goBack}
backLabel={backLabel}
onPlay={() => playFrom(0)}
onShuffle={() => void playLibraryQuery({ kind: 'album', albumKey: key }, {
shuffle: true,
+3 -2
View File
@@ -71,7 +71,7 @@ export default function ArtistScreen() {
name: string;
credit?: string;
}>();
const handleBack = useLibraryDetailBack();
const { goBack, backLabel } = useLibraryDetailBack();
const insets = useSafeAreaInsets();
const { scrollY, heroFaded, collapsed, onScroll, scrollEventThrottle, expandedHeight, onHeroBlockLayout } =
useDetailCollapse();
@@ -246,7 +246,8 @@ export default function ArtistScreen() {
</View>
}
disabled={disabled}
onBack={handleBack}
onBack={goBack}
backLabel={backLabel}
onPlay={playArtist}
onShuffle={shuffleArtist}
scrollY={scrollY}
+16 -10
View File
@@ -1,5 +1,5 @@
import {
useEffect,
useCallback,
useMemo,
useState
} from 'react';
@@ -11,7 +11,7 @@ import {
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { FlashList } from '@shopify/flash-list';
import { useRouter } from 'expo-router';
import { useFocusEffect, useRouter } from 'expo-router';
import { Screen } from '@/components/Screen';
import { Text } from '@/components/Text';
import { ViewModeSwitcher } from '@/components/library/ViewModeSwitcher';
@@ -165,14 +165,20 @@ export default function LibraryScreen() {
setPlaylistPickerOpen(false);
};
useEffect(() => {
if (!selectMode) return;
const sub = BackHandler.addEventListener('hardwareBackPress', () => {
exitSelection();
return true;
});
return () => sub.remove();
}, [selectMode]);
// Focus-gated, not a plain effect: the tabs layout keeps this screen mounted
// while blurred (`detachInactiveScreens={false}` + `freezeOnBlur: false`), so
// an ungated handler swallowed one back press anywhere in the app — any other
// tab, any settings screen — whenever selection happened to be active.
useFocusEffect(
useCallback(() => {
if (!selectMode) return undefined;
const sub = BackHandler.addEventListener('hardwareBackPress', () => {
exitSelection();
return true;
});
return () => sub.remove();
}, [selectMode])
);
const selectedDbTracks = () => sortedTracks.filter((track) => selectedIds.has(track.id));
+4 -3
View File
@@ -89,7 +89,7 @@ export default function PlaylistScreen() {
const colors = useColors();
const router = useRouter();
const { id } = useLocalSearchParams<{ id: string }>();
const handleBack = useLibraryDetailBack();
const { goBack, backLabel } = useLibraryDetailBack();
const isFavorites = id === 'favorites';
const playlistId = isFavorites ? null : Number(id);
@@ -219,7 +219,7 @@ export default function PlaylistScreen() {
void (async () => {
try {
await deletePlaylist(target.id);
handleBack();
goBack();
} catch (err) {
Alert.alert('Delete failed', errorMessage(err));
}
@@ -340,7 +340,8 @@ export default function PlaylistScreen() {
) : null
}
disabled={playable.length === 0}
onBack={handleBack}
onBack={goBack}
backLabel={backLabel}
onMore={() => setOptionsOpen(true)}
onPlay={() => startPlayback(0)}
onShuffle={startShuffle}