mirror of
https://github.com/janishutz/MusicPlayer.git
synced 2026-09-10 14:25:24 +02:00
feat: song editor
This commit is contained in:
Vendored
-2
@@ -1,5 +1,3 @@
|
||||
// NOTE: For re-associating files with details here, can use dropdown in UI
|
||||
|
||||
export interface Playlist {
|
||||
'name': string;
|
||||
'songs': PlaylistSongs;
|
||||
|
||||
@@ -20,13 +20,12 @@ export const isConnected = ref( false );
|
||||
|
||||
export const useAntiTamper = ref( false );
|
||||
|
||||
// TODO: Anit-Tamper
|
||||
// const antiTamperClients = [];
|
||||
|
||||
let connection: null | EventSource = null;
|
||||
let retries = 0;
|
||||
|
||||
// TODO: Persist room name in local storage
|
||||
|
||||
const createRoom = async ( name: string, antiTamper: boolean ): Promise<boolean> => {
|
||||
if ( !( /^[a-zA-Z0-9-]{3,20}$/ ).test( name ) ) return false;
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ const next = () => {
|
||||
};
|
||||
|
||||
const prev = () => {
|
||||
// TODO: Back to beginning if more than some seconds have passed?
|
||||
if ( playbackPercentage.value * duration.value > 7 )
|
||||
return seekTo( 0 );
|
||||
|
||||
playIndex( ( queueIdx.value - 1 + queue.value.length ) % queue.value.length );
|
||||
};
|
||||
|
||||
@@ -136,10 +138,12 @@ const addToSongList = ( songs: Song[] ) => {
|
||||
/**
|
||||
* Add songs to the playlist from given source
|
||||
* @param source - The ID of the source to add from
|
||||
* @param cb - A custom callback to be executed instead of the default, which adds to queue
|
||||
* @param skipLogin - Whether to skip login checks
|
||||
*/
|
||||
const addSongFromSource = async ( source: string ): Promise<boolean> => {
|
||||
if ( sources[source]!.authorized.value ) {
|
||||
sources[source]!.addSongsFromThisSource( addToSongList );
|
||||
const addSongFromSource = async ( source: string, cb?: ( songs: Song[] ) => void, skipLogin?: boolean ): Promise<boolean> => {
|
||||
if ( sources[source]!.authorized.value || skipLogin ) {
|
||||
sources[source]!.addSongsFromThisSource( cb ? cb : addToSongList, skipLogin ? 0 : undefined, skipLogin );
|
||||
} else {
|
||||
sources[source]!.login!();
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ export const load = ( playlist: PlaylistSongs ) => {
|
||||
};
|
||||
|
||||
if ( needToLoadLocalSongs ) {
|
||||
// FIXME: Combine mime types
|
||||
const mime = Object.values( sources )
|
||||
.map( src => {
|
||||
return src.loading.requiresLocalFiles === true ? src.loading.mime : '';
|
||||
|
||||
+4
-1
@@ -116,8 +116,11 @@ export interface PlayerSourcePlugin {
|
||||
/**
|
||||
* 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
|
||||
* @param cb - Added songs are the arguments
|
||||
* @param kindIdx - The index in the list of import types that should be used without showing popup. If unset, will show the picker
|
||||
* @param autoClose - Whether or not to automatically close the interface after a single pick
|
||||
*/
|
||||
'addSongsFromThisSource': ( cb: ( songs: Song[] ) => void ) => void;
|
||||
'addSongsFromThisSource': ( cb: ( songs: Song[] ) => void, kindIdx?: number, autoClose?: boolean ) => void;
|
||||
|
||||
/**
|
||||
* Fully unload a song. This is called on clear of a playlist
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import {
|
||||
type CloudImport,
|
||||
openImportTypePicker
|
||||
} from '@/composables/importTypePicker';
|
||||
import type {
|
||||
Song
|
||||
} from '@/ts/dtype/playlist';
|
||||
import {
|
||||
openImportTypePicker
|
||||
} from '@/composables/importTypePicker';
|
||||
openSearchInterface
|
||||
} from '@/composables/searchManager';
|
||||
import {
|
||||
searchPlaylists
|
||||
} from './playlists';
|
||||
@@ -11,23 +15,29 @@ import {
|
||||
searchSongs
|
||||
} from './songs';
|
||||
|
||||
export const addFromAppleMusic = async ( cb: ( songs: Song[] ) => void ): Promise<void> => {
|
||||
export const addFromAppleMusic = async ( cb: ( songs: Song[] ) => void, kindIdx?: number, autoClose?: boolean ): Promise<void> => {
|
||||
const songs = await searchSongs( cb );
|
||||
const playlists = await searchPlaylists( cb );
|
||||
|
||||
openImportTypePicker( [
|
||||
const kinds: CloudImport[] = [
|
||||
{
|
||||
'name': 'Songs',
|
||||
'type': 'cloud',
|
||||
'addSelected': songs.addSelected,
|
||||
'search': songs.search,
|
||||
'minChars': 3
|
||||
'minChars': 3,
|
||||
'autoClose': autoClose ?? false
|
||||
},
|
||||
{
|
||||
'name': 'Playlists',
|
||||
'type': 'cloud',
|
||||
'addSelected': playlists.addSelected,
|
||||
'search': playlists.search
|
||||
'search': playlists.search,
|
||||
'autoClose': autoClose ?? false
|
||||
}
|
||||
] );
|
||||
];
|
||||
|
||||
if ( kindIdx === undefined )
|
||||
openImportTypePicker( kinds );
|
||||
else
|
||||
openSearchInterface( kinds[kindIdx]! );
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user