feat: design for queue, add songs, search and more

This commit is contained in:
2026-09-01 15:33:21 +02:00
parent 3a0f8210dd
commit faa271edd6
19 changed files with 251 additions and 34 deletions
+8 -2
View File
@@ -1,6 +1,7 @@
import {
addSongList,
clearQueue,
removeSong,
shuffleList
} from './playlists/add';
import {
@@ -27,12 +28,12 @@ import {
} from './playlists';
const next = () => {
playIndex( queueIdx.value + 1 );
playIndex( ( queueIdx.value + 1 ) % queue.value.length );
};
const prev = () => {
// TODO: Back to beginning if more than some seconds have passed?
playIndex( queueIdx.value - 1 );
playIndex( ( queueIdx.value - 1 + queue.value.length ) % queue.value.length );
};
const play = () => {
@@ -117,6 +118,10 @@ const getSources = (): string[] => {
return Object.keys( sources );
};
/**
* Add songs to the playlist from given source
* @param source - The ID of the source to add from
*/
const addSongFromSource = async ( source: string ) => {
sources[source]!.addSongsFromThisSource( addSongList );
};
@@ -135,6 +140,7 @@ export default {
next,
prev,
clearQueue,
removeSong,
queue,
queueIdx,
duration,
-1
View File
@@ -35,7 +35,6 @@ export const removeSong = ( idx: number ) => {
const removed = queue.value.splice( idx, 1 )[0];
// TODO: Check that this works
for ( let i = 0; i < rawQueue.value.length; i++ ) {
if ( rawQueue.value[ i ] === removed ) {
rawQueue.value.splice( i, 1 );
+5
View File
@@ -90,6 +90,11 @@ export interface PlayerSourcePlugin {
*/
'getDuration': () => number;
/**
* Check if source is available for playback
*/
'available': () => boolean;
/**
* Called when user adds another song to the playlist via this source.
* You may use the provided interface elements (search bar and popups) to e.g. ask if user wants to use a playlist, album, etc
+1
View File
@@ -12,6 +12,7 @@ export const useLocalPlayer: PlayerSourcePluginInitializer = async (): Promise<P
};
return {
'available': () => true,
'id': 'local',
'name': 'Local Disk',
'play': player.play,
@@ -43,6 +43,7 @@ export const useMusicKit: PlayerSourcePluginInitializer = ( storefront: string =
};
return {
'available': controls.getLoggedIn,
'play': controls.play,
'pause': controls.pause,
'stop': controls.stop,
@@ -34,6 +34,10 @@ export const musicKitPlayback = ( musickitInstance: MusicKitInstance ) => {
return musickitInstance.currentPlaybackDuration;
};
const getLoggedIn = (): boolean => {
return musickitInstance.isAuthorized;
};
return {
play,
pause,
@@ -41,6 +45,7 @@ export const musicKitPlayback = ( musickitInstance: MusicKitInstance ) => {
playSong,
stop,
getPlaybackPos,
getDuration
getDuration,
getLoggedIn
};
};
@@ -7,12 +7,16 @@ import type {
import {
openImportTypePicker
} from '@/composables/importTypePicker';
import {
searchPlaylists
} from './playlists';
import {
searchSongs
} from './songs';
export const addFromAppleMusic = async ( instance: MusicKitInstance, cb: ( songs: Song[] ) => void ): Promise<void> => {
const songs = await searchSongs( instance, cb );
const playlists = await searchPlaylists( instance, cb );
openImportTypePicker( [
{
@@ -24,8 +28,8 @@ export const addFromAppleMusic = async ( instance: MusicKitInstance, cb: ( songs
{
'name': 'Playlists',
'type': 'cloud',
'addSelected': songs.addSelected,
'search': songs.search
'addSelected': playlists.addSelected,
'search': playlists.search
}
] );
};
@@ -1,17 +1,24 @@
import type {
Song
} from '@/ts/dtype/playlist';
import type {
MusicKitInstance
} from 'musickitjs-v3-types/MusicKitInstance';
import type {
Song
} from '@/ts/dtype/playlist';
export const searchPlaylists = async ( instance: MusicKitInstance ) => {
export const searchPlaylists = async ( instance: MusicKitInstance, cb: ( songs: Song[] ) => void ) => {
// TODO: Get all playlists
const search = async () => {};
const addSelected = async ( idx: number ): Promise<Song[]> => {
// TODO: Load the playlist content and return songs
const search = async ( term: string ): Promise<Song[]> => {
return [];
};
const addSelected = async ( idx: number ) => {
// TODO: Implement
cb( [] );
};
return {
search,
addSelected
};
};