mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-21 13:09:46 +02:00
fix internal routing, and remove softlocking
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user