import { useState } from 'react';
import { usePathname } from 'expo-router';
import { useReturnToTabs } from '@/navigation/returnToTabs';
import {
AppSheet,
AppSheetItem,
AppSheetSection,
AppSheetTitle,
type AppSheetItemProps,
} from '@/components/sheets/AppSheet';
import { PlaylistPickerSheet } from '@/components/sheets/PlaylistPickerSheet';
import { enqueueEnd, enqueueTop } from '@/audio/playbackController';
import { dbTrackToTrack } from '@/library/trackAdapter';
import { resolveNavigationArtist } from '@/library/artistGrouping';
import { usePlaylistStore } from '@/stores/playlistStore';
import { useSettingsStore } from '@/stores/settingsStore';
import type { DbTrack } from '@/types/library';
export interface TrackActionSheetItem extends AppSheetItemProps {
key: string;
}
interface TrackActionsSheetProps {
/** null = hidden. */
track: DbTrack | null;
onClose: () => void;
/** Allows callers with their own menu to jump straight to playlist picking. */
initialStep?: 'menu' | 'pickPlaylist';
/** Screen-specific extras (e.g. playlist detail: remove / move). Handlers should close. */
extraItems?: TrackActionSheetItem[];
}
/** Track menu: queue, playlist, navigation, favorites, and optional screen extras. */
export function TrackActionsSheet(props: TrackActionsSheetProps) {
// Mount fresh per track so the step state resets.
if (!props.track) return null;
return ;
}
function TrackActionsSheetInner({
track,
onClose,
initialStep = 'menu',
extraItems = [],
}: TrackActionsSheetProps & { track: DbTrack }) {
// This sheet also renders from `recently-played` and from inside the
// now-playing overlay, i.e. while a root-stack sibling of `(tabs)` is focused,
// where a bare push would mint a second copy of the whole tab tree.
const returnToTabs = useReturnToTabs();
const pathname = usePathname();
const [step, setStep] = useState<'menu' | 'pickPlaylist'>(initialStep);
const groupingMode = useSettingsStore((s) => s.artistGroupingMode);
const isFavorite = usePlaylistStore((s) => s.favoritePaths.has(track.path));
const toggleFavorite = usePlaylistStore((s) => s.toggleFavorite);
const artistName = resolveNavigationArtist(track, groupingMode);
const albumHref = `/library/album/${encodeURIComponent(track.album_identity_key)}`;
const artistHref = `/library/artist/${encodeURIComponent(artistName)}`;
const closeAndRun = (run: () => void) => {
onClose();
run();
};
const menuItems: TrackActionSheetItem[] = [
{
key: 'play-next',
label: 'Play next',
icon: 'play-skip-forward',
onPress: () => closeAndRun(() => void enqueueTop(dbTrackToTrack(track))),
},
{
key: 'add-to-queue',
label: 'Add to queue',
icon: 'list-outline',
onPress: () => closeAndRun(() => void enqueueEnd(dbTrackToTrack(track))),
},
{
key: 'add-to-playlist',
label: 'Add to playlist...',
icon: 'add-circle-outline',
onPress: () => setStep('pickPlaylist'),
},
{
key: 'view-album',
label: 'View album',
icon: 'albums-outline',
onPress: () =>
closeAndRun(() => {
// Already here (this sheet also opens from the album screen itself):
// pushing would stack a duplicate of the current screen.
if (pathname === albumHref) return;
returnToTabs(
{ pathname: '/library/album/[key]', params: { key: track.album_identity_key } },
'push'
);
}),
},
{
key: 'view-artist',
label: 'View artist',
icon: 'person-outline',
onPress: () =>
closeAndRun(() => {
if (pathname === artistHref) return;
returnToTabs(
{ pathname: '/library/artist/[name]', params: { name: artistName } },
'push'
);
}),
},
{
key: 'favorite',
label: isFavorite ? 'Remove from favorites' : 'Add to favorites',
icon: isFavorite ? 'heart-dislike-outline' : 'heart-outline',
selected: isFavorite,
onPress: () => closeAndRun(() => void toggleFavorite(track)),
},
];
if (step === 'pickPlaylist') {
return (
setStep('menu') : undefined}
/>
);
}
return (
{menuItems.map(({ key, ...item }) => (
))}
{extraItems.length > 0 ? (
<>
{extraItems.map(({ key, ...item }) => (
))}
>
) : null}
);
}