mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-19 12:14:47 +02:00
rewrite entire queue system to native
This commit is contained in:
@@ -5,7 +5,7 @@ import { QueueTray } from '@/components/queue/QueueTray';
|
||||
import { RemoteQueueSheet } from '@/components/queue/RemoteQueueSheet';
|
||||
import { seekTo } from '@/audio/playbackController';
|
||||
import { spacing } from '@/theme';
|
||||
import { createThemedStyles } from '@/theme/themed';
|
||||
import { createThemedStyles, useColors } from '@/theme/themed';
|
||||
import {
|
||||
getNowPlayingTrackTransitionKey,
|
||||
NowPlayingTrackFadeThrough,
|
||||
@@ -14,6 +14,10 @@ import { usePlayerStore } from '@/stores/playerStore';
|
||||
import { useSettingsStore } from '@/stores/settingsStore';
|
||||
import type { NowPlayingCompanion } from './nowPlayingPreferences';
|
||||
import type { Track } from '@/types/audio';
|
||||
import {
|
||||
AstraQueueView,
|
||||
toNativeQueuePalette,
|
||||
} from '../../../modules/astra-library-scanner';
|
||||
|
||||
const COMPANION_SEGMENTS = [
|
||||
{ key: 'queue', label: 'Queue' },
|
||||
@@ -35,7 +39,9 @@ export function NowPlayingCompanionPane({
|
||||
track,
|
||||
}: NowPlayingCompanionPaneProps) {
|
||||
const styles = useStyles();
|
||||
const colors = useColors();
|
||||
const companion = useSettingsStore((s) => s.nowPlayingCompanion);
|
||||
const nativeQueueEnabled = useSettingsStore((s) => s.nativeQueueEnabled);
|
||||
const setCompanion = useSettingsStore((s) => s.setNowPlayingCompanion);
|
||||
const currentTime = usePlayerStore((s) => (active && !desktopTarget ? s.currentTime : 0));
|
||||
const duration = usePlayerStore((s) => (desktopTarget ? 0 : s.duration));
|
||||
@@ -68,7 +74,15 @@ export function NowPlayingCompanionPane({
|
||||
</View>
|
||||
<View style={styles.content}>
|
||||
{companion === 'queue' ? (
|
||||
<QueueTray embedded onClose={noop} />
|
||||
nativeQueueEnabled ? (
|
||||
<AstraQueueView
|
||||
active={active}
|
||||
palette={toNativeQueuePalette(colors)}
|
||||
style={styles.nativeQueue}
|
||||
/>
|
||||
) : (
|
||||
<QueueTray embedded onClose={noop} />
|
||||
)
|
||||
) : track ? (
|
||||
<NowPlayingTrackFadeThrough
|
||||
transitionKey={transitionTrackKey}
|
||||
@@ -113,4 +127,8 @@ const useStyles = createThemedStyles((colors) => ({
|
||||
minHeight: 0,
|
||||
position: 'relative',
|
||||
},
|
||||
nativeQueue: {
|
||||
flex: 1,
|
||||
minHeight: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -108,12 +108,18 @@ import { useThemeStore } from '@/stores/themeStore';
|
||||
import type { DbTrack } from '@/types/library';
|
||||
import {
|
||||
cycleRepeat,
|
||||
jumpToQueueIndex,
|
||||
seekTo,
|
||||
skipToNext,
|
||||
skipToPrevious,
|
||||
synchronizeVirtualQueueRevision,
|
||||
togglePlay,
|
||||
toggleShuffle
|
||||
} from '@/audio/playbackController';
|
||||
import {
|
||||
AstraQueue,
|
||||
toNativeQueuePalette,
|
||||
} from '../../../modules/astra-library-scanner';
|
||||
import {
|
||||
desktopConnectionLabel,
|
||||
getDesktopPlaybackPresentation,
|
||||
@@ -174,6 +180,7 @@ export function NowPlayingOverlay() {
|
||||
const nowPlayingAccentSource = useThemeStore((s) => s.nowPlayingAccentSource);
|
||||
const coverArtAccentMethod = useThemeStore((s) => s.coverArtAccentMethod);
|
||||
const scopeMode = useSettingsStore((s) => s.scopeMode);
|
||||
const nativeQueueEnabled = useSettingsStore((s) => s.nativeQueueEnabled);
|
||||
const scopeStageVisible = useSettingsStore((s) => s.scopeStageVisible);
|
||||
const setScopeStageVisible = useSettingsStore((s) => s.setScopeStageVisible);
|
||||
const scopeStyle = useSettingsStore((s) => s.nowPlayingScopeStyle);
|
||||
@@ -378,6 +385,12 @@ export function NowPlayingOverlay() {
|
||||
}
|
||||
suspendPanForChildTransition();
|
||||
setQueueOpen(true);
|
||||
if (nativeQueueEnabled && !isDesktopTarget) {
|
||||
void AstraQueue.present({ palette: toNativeQueuePalette(colors) }).catch((error) => {
|
||||
console.warn('[queue] native presentation failed', error);
|
||||
setQueueOpen(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const swapScopeMode = () =>
|
||||
@@ -742,10 +755,49 @@ export function NowPlayingOverlay() {
|
||||
// Stable identity: QueueTray is memo'd, so a fresh arrow here would defeat it.
|
||||
const closeQueue = useCallback(() => {
|
||||
suspendPanForChildTransition();
|
||||
if (nativeQueueEnabled && !isDesktopTarget) AstraQueue.dismiss();
|
||||
setQueueOpen(false);
|
||||
// Shared values and the state setter remain stable for this overlay mount.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [isDesktopTarget, nativeQueueEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!nativeQueueEnabled) return undefined;
|
||||
const dismissed = AstraQueue.addListener('onDismissed', () => {
|
||||
setQueueOpen(false);
|
||||
});
|
||||
const playbackRequest = AstraQueue.addListener('onPlaybackRequest', (request) => {
|
||||
void (async () => {
|
||||
try {
|
||||
const position = await AstraQueue.resolveEntryPosition(
|
||||
request.entryId,
|
||||
request.queueRevision,
|
||||
);
|
||||
if (position == null) {
|
||||
throw new Error('The queue changed. Try that song again.');
|
||||
}
|
||||
await jumpToQueueIndex(position, { virtualPosition: true });
|
||||
AstraQueue.resolvePlaybackRequest(request.requestId, true);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Could not play that song';
|
||||
AstraQueue.resolvePlaybackRequest(request.requestId, false, message);
|
||||
}
|
||||
})();
|
||||
});
|
||||
const revision = AstraQueue.addListener('onQueueRevision', (event) => {
|
||||
void synchronizeVirtualQueueRevision(
|
||||
event.queueRevision,
|
||||
event.activePosition,
|
||||
).catch((error) => {
|
||||
console.warn('[queue] transport revision sync failed', error);
|
||||
});
|
||||
});
|
||||
return () => {
|
||||
dismissed.remove();
|
||||
playbackRequest.remove();
|
||||
revision.remove();
|
||||
};
|
||||
}, [nativeQueueEnabled]);
|
||||
|
||||
// Hardware back, innermost layer first: menu → queue tray → player. Registered
|
||||
// only while open, so it sits above the focused screen's own handlers (LIFO)
|
||||
@@ -1692,9 +1744,9 @@ export function NowPlayingOverlay() {
|
||||
{queueOpen && !hasTabletCompanion && (
|
||||
isDesktopTarget ? (
|
||||
<RemoteQueueSheet onClose={closeQueue} />
|
||||
) : (
|
||||
) : !nativeQueueEnabled ? (
|
||||
<QueueTray onClose={closeQueue} />
|
||||
)
|
||||
) : null
|
||||
)}
|
||||
<PlaybackTargetPicker
|
||||
visible={targetPickerOpen}
|
||||
|
||||
Reference in New Issue
Block a user