diff --git a/dmp-core/src/music_controller/controller.rs b/dmp-core/src/music_controller/controller.rs index 8c94836..a7d9648 100644 --- a/dmp-core/src/music_controller/controller.rs +++ b/dmp-core/src/music_controller/controller.rs @@ -109,14 +109,12 @@ pub enum LibraryCommand { AllSongs, GetLibrary, ExternalPlaylist(Uuid), - PlaylistSong{ - list_uuid: Uuid, - item_uuid: Uuid - }, + PlaylistSong { list_uuid: Uuid, item_uuid: Uuid }, Playlist(Uuid), ImportM3UPlayList(PathBuf), Save, Playlists, + PlaylistAddSong { playlist: Uuid, song: Uuid }, } #[derive(Debug, Clone)] diff --git a/dmp-core/src/music_controller/controller_handle.rs b/dmp-core/src/music_controller/controller_handle.rs index 146fec4..cb8fb0c 100644 --- a/dmp-core/src/music_controller/controller_handle.rs +++ b/dmp-core/src/music_controller/controller_handle.rs @@ -74,6 +74,15 @@ impl ControllerHandle { Ok((uuid, name)) } + pub async fn playlist_add_song(&self, playlist: Uuid, song: Uuid) { + let (command, tx) = + LibraryCommandInput::command(LibraryCommand::PlaylistAddSong { playlist, song }); + self.lib_mail_rx.send(command).await.unwrap(); + let LibraryResponse::Ok = tx.recv().await.unwrap() else { + unreachable!() + }; + } + // The Queue Section pub async fn queue_append( &self, diff --git a/dmp-core/src/music_controller/library_command.rs b/dmp-core/src/music_controller/library_command.rs index 463693b..01b3cfe 100644 --- a/dmp-core/src/music_controller/library_command.rs +++ b/dmp-core/src/music_controller/library_command.rs @@ -89,15 +89,27 @@ impl Controller { .await .unwrap(); } - LibraryCommand::PlaylistSong { list_uuid, item_uuid } => { - let playlist= library.playlists.query_uuid(&list_uuid).unwrap(); - let Some((uuid, index)) = playlist.query_uuid(&item_uuid) else { todo!() }; - let Some((song, _)) = library.query_uuid(uuid) else { todo!() }; + LibraryCommand::PlaylistSong { + list_uuid, + item_uuid, + } => { + let playlist = library.playlists.query_uuid(&list_uuid).unwrap(); + let Some((uuid, index)) = playlist.query_uuid(&item_uuid) else { + todo!() + }; + let Some((song, _)) = library.query_uuid(uuid) else { + todo!() + }; res_rx .send(LibraryResponse::PlaylistSong(song.clone(), index)) .await .unwrap(); } + LibraryCommand::PlaylistAddSong { playlist, song } => { + let playlist = library.query_playlist_uuid_mut(&playlist).unwrap(); + playlist.add_track(song); + res_rx.send(LibraryResponse::Ok).await.unwrap(); + } _ => { todo!() } diff --git a/dmp-core/src/music_storage/library.rs b/dmp-core/src/music_storage/library.rs index 55707c7..e316cc5 100644 --- a/dmp-core/src/music_storage/library.rs +++ b/dmp-core/src/music_storage/library.rs @@ -1232,6 +1232,10 @@ impl MusicLibrary { self.playlists.query_uuid(uuid) } + pub fn query_playlist_uuid_mut(&mut self, uuid: &Uuid) -> Option<&mut Playlist> { + self.playlists.query_uuid_mut(uuid) + } + pub fn push_playlist(&mut self, playlist: PlaylistFolderItem) { self.playlists.items.push(playlist); } diff --git a/dmp-core/src/music_storage/playlist.rs b/dmp-core/src/music_storage/playlist.rs index 3aab7c5..1d510ff 100644 --- a/dmp-core/src/music_storage/playlist.rs +++ b/dmp-core/src/music_storage/playlist.rs @@ -55,6 +55,20 @@ impl PlaylistFolder { None } + pub fn query_uuid_mut(&mut self, uuid: &Uuid) -> Option<&mut Playlist> { + for item in &mut self.items { + match item { + PlaylistFolderItem::Folder(folder) => return folder.query_uuid_mut(uuid), + PlaylistFolderItem::List(playlist) => { + if &playlist.uuid == uuid { + return Some(playlist); + } + } + } + } + None + } + pub fn lists_recursive(&self) -> Vec<&Playlist> { let mut vec = vec![]; for item in &self.items { diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 2e60e65..ccf9e63 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -24,8 +24,8 @@ use uuid::Uuid; use wrappers::{_Song, stop}; use crate::wrappers::{ - get_library, get_playlist, get_playlists, get_queue, get_song, import_playlist, next, pause, - play, prev, remove_from_queue, seek, set_volume, + add_song_to_playlist, get_library, get_playlist, get_playlists, get_queue, get_song, + import_playlist, next, pause, play, prev, remove_from_queue, seek, set_volume, }; use commands::{add_song_to_queue, display_album_art, last_fm_init_auth, play_now}; @@ -69,6 +69,7 @@ pub fn run() { save_config, close_window, start_controller, + add_song_to_playlist, // test_menu, ]) .manage(tempfile::TempDir::new().unwrap()) diff --git a/src-tauri/src/wrappers.rs b/src-tauri/src/wrappers.rs index e03f579..7c11116 100644 --- a/src-tauri/src/wrappers.rs +++ b/src-tauri/src/wrappers.rs @@ -1,4 +1,4 @@ -use std::{collections::BTreeMap, path::PathBuf}; +use std::{collections::BTreeMap, path::PathBuf, thread::spawn}; use chrono::{serde::ts_milliseconds_option, DateTime, Utc}; use crossbeam::channel::Sender; @@ -11,6 +11,7 @@ use dmp_core::{ }; use itertools::Itertools; use serde::Serialize; + use tauri::{AppHandle, Emitter, State, Wry}; use uuid::Uuid; @@ -217,14 +218,18 @@ pub async fn get_playlists( ctrl_handle: State<'_, ControllerHandle>, ) -> Result<(), String> { let lists = ctrl_handle.playlist_get_all().await; - app.emit( - "playlists_gotten", - lists - .into_iter() - .map(|(uuid, name)| PlaylistPayload { uuid, name }) - .collect_vec(), - ) - .unwrap(); + spawn(move || { + futures::executor::block_on(async { + app.emit( + "playlists_gotten", + lists + .into_iter() + .map(|(uuid, name)| PlaylistPayload { uuid, name }) + .collect_vec(), + ) + .unwrap(); + }) + }); Ok(()) } @@ -272,3 +277,12 @@ pub async fn get_song( pub async fn seek(ctrl_handle: State<'_, ControllerHandle>, time: i64) -> Result<(), String> { ctrl_handle.seek(time).await.map_err(|e| e.to_string()) } + +#[tauri::command] +pub async fn add_song_to_playlist( + ctrl_handle: State<'_, ControllerHandle>, + song: Uuid, + playlist: Uuid, +) -> Result<(), String> { + Ok(ctrl_handle.playlist_add_song(playlist, song).await) +} diff --git a/src/App.tsx b/src/App.tsx index 7bb3fe7..1eb2166 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { createRef, ReactEventHandler, useEffect, useRef, useState } from "react"; +import React, { createRef, MutableRefObject, ReactEventHandler, useEffect, useRef, useState } from "react"; import { convertFileSrc, invoke } from "@tauri-apps/api/core"; import "./App.css"; import { Config, playbackInfo } from "./types"; @@ -7,7 +7,7 @@ import { Config, playbackInfo } from "./types"; // import { fetch } from "@tauri-apps/plugin-http"; import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"; import { getCurrentWindow, LogicalPosition } from "@tauri-apps/api/window"; -import { Menu } from "@tauri-apps/api/menu"; +import { Menu, Submenu, SubmenuOptions } from "@tauri-apps/api/menu"; import { listen } from "@tauri-apps/api/event"; const appWindow = getCurrentWebviewWindow(); @@ -18,6 +18,7 @@ function App() { const [playing, setPlaying] = useState(false); const [playlists, setPlaylists] = useState([]); const [viewName, setViewName] = useState("Library"); + const playlistsInfo= useRef([]); const [nowPlaying, setNowPlaying] = useState(
- - + +
{ nowPlaying } @@ -100,22 +101,32 @@ function App() { export default App; +interface PlaylistInfo { + uuid: string, + name: string, +} + + interface PlaylistHeadProps { playlists: JSX.Element[] setPlaylists: React.Dispatch>, setViewName: React.Dispatch>, setLibrary: React.Dispatch>, + playlistsInfo: MutableRefObject, } -function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary }: PlaylistHeadProps) { +function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary, playlistsInfo }: PlaylistHeadProps) { useEffect(() => { const unlisten = appWindow.listen("playlists_gotten", (_res) => { // console.log(event); - let res = _res.payload; + let res = _res.payload as PlaylistInfo[]; + playlistsInfo.current = [...res]; + console.log(playlistsInfo, res); setPlaylists([ ...res.map( (item) => { + return (