fix: music downloading not playing + queue drag and drop
Some checks failed
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🌐 Translation Sync / sync-translations (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
🕒 Handle Stale Issues / 🗑️ Cleanup Stale Issues (push) Has been cancelled

This commit is contained in:
Fredrik Burmester
2026-01-04 16:28:35 +01:00
parent d22827bc9b
commit a2058a8009
17 changed files with 375 additions and 92 deletions

View File

@@ -99,6 +99,7 @@ export const MusicPlaybackEngine: React.FC = () => {
currentIndex,
);
await TrackPlayer.skip(currentIndex);
await TrackPlayer.play();
}
} catch (error) {
console.warn(

View File

@@ -27,6 +27,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Text } from "@/components/common/Text";
import { useFavorite } from "@/hooks/useFavorite";
import {
audioStorageEvents,
downloadTrack,
isCached,
isPermanentDownloading,
@@ -62,6 +63,22 @@ export const TrackOptionsSheet: React.FC<Props> = ({
const insets = useSafeAreaInsets();
const { t } = useTranslation();
const [isDownloadingTrack, setIsDownloadingTrack] = useState(false);
// Counter to trigger re-evaluation of download status when storage changes
const [storageUpdateCounter, setStorageUpdateCounter] = useState(0);
// Listen for storage events to update download status
useEffect(() => {
const handleComplete = (event: { itemId: string }) => {
if (event.itemId === track?.Id) {
setStorageUpdateCounter((c) => c + 1);
}
};
audioStorageEvents.on("complete", handleComplete);
return () => {
audioStorageEvents.off("complete", handleComplete);
};
}, [track?.Id]);
// Use a placeholder item for useFavorite when track is null
const { isFavorite, toggleFavorite } = useFavorite(
@@ -70,15 +87,18 @@ export const TrackOptionsSheet: React.FC<Props> = ({
const snapPoints = useMemo(() => ["65%"], []);
// Check download status
// Check download status (storageUpdateCounter triggers re-evaluation when download completes)
const isAlreadyDownloaded = useMemo(
() => isPermanentlyDownloaded(track?.Id),
[track?.Id],
[track?.Id, storageUpdateCounter],
);
const isOnlyCached = useMemo(
() => isCached(track?.Id),
[track?.Id, storageUpdateCounter],
);
const isOnlyCached = useMemo(() => isCached(track?.Id), [track?.Id]);
const isCurrentlyDownloading = useMemo(
() => isPermanentDownloading(track?.Id),
[track?.Id],
[track?.Id, storageUpdateCounter],
);
const imageUrl = useMemo(() => {
@@ -150,7 +170,10 @@ export const TrackOptionsSheet: React.FC<Props> = ({
try {
const result = await getAudioStreamUrl(api, user.Id, track.Id);
if (result?.url && !result.isTranscoding) {
await downloadTrack(track.Id, result.url, { permanent: true });
await downloadTrack(track.Id, result.url, {
permanent: true,
container: result.mediaSource?.Container || undefined,
});
}
} catch {
// Silent fail