mirror of
https://github.com/Dangoware/dango-music-player.git
synced 2025-04-19 10:02:53 -05:00
Added Controller State and Playlist loading on startup
This commit is contained in:
parent
10223b23e2
commit
4f2d5ab64a
8 changed files with 220 additions and 55 deletions
|
@ -1,9 +1,7 @@
|
|||
pub mod other_settings;
|
||||
|
||||
use std::{
|
||||
fs::{self, File, OpenOptions},
|
||||
io::{Error, Read, Write},
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -100,8 +98,8 @@ pub struct Config {
|
|||
pub path: PathBuf,
|
||||
pub backup_folder: Option<PathBuf>,
|
||||
pub libraries: ConfigLibraries,
|
||||
pub volume: f32,
|
||||
pub connections: ConfigConnections,
|
||||
pub state_path: PathBuf,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
@ -160,9 +158,9 @@ impl Config {
|
|||
|
||||
pub fn read_file(path: PathBuf) -> Result<Self, Error> {
|
||||
let mut file: File = File::open(path)?;
|
||||
let mut bun: String = String::new();
|
||||
_ = file.read_to_string(&mut bun);
|
||||
let config: Config = serde_json::from_str::<Config>(&bun)?;
|
||||
let mut buf: String = String::new();
|
||||
_ = file.read_to_string(&mut buf);
|
||||
let config: Config = serde_json::from_str::<Config>(&buf)?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
pub enum Setting {
|
||||
String { name: String, value: String },
|
||||
Int { name: String, value: i32 },
|
||||
Bool { name: String, value: bool },
|
||||
}
|
||||
|
||||
pub struct Form {}
|
|
@ -6,15 +6,19 @@
|
|||
use itertools::Itertools;
|
||||
use kushi::{Queue, QueueItemType};
|
||||
use kushi::{QueueError, QueueItem};
|
||||
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::to_string_pretty;
|
||||
use std::error::Error;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
use std::marker::PhantomData;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::config::ConfigError;
|
||||
use crate::config::{self, ConfigError};
|
||||
use crate::music_player::player::{Player, PlayerError};
|
||||
use crate::music_storage::library::Song;
|
||||
use crate::music_storage::playlist::{ExternalPlaylist, Playlist, PlaylistFolderItem};
|
||||
|
@ -75,7 +79,7 @@ pub enum PlayerCommand {
|
|||
Pause,
|
||||
Play,
|
||||
Enqueue(usize),
|
||||
SetVolume(f64),
|
||||
SetVolume(f32),
|
||||
PlayNow(Uuid, PlayerLocation),
|
||||
}
|
||||
|
||||
|
@ -90,8 +94,11 @@ pub enum LibraryCommand {
|
|||
Song(Uuid),
|
||||
AllSongs,
|
||||
GetLibrary,
|
||||
ExternalPlaylist(Uuid),
|
||||
Playlist(Uuid),
|
||||
ImportM3UPlayList(PathBuf)
|
||||
ImportM3UPlayList(PathBuf),
|
||||
Save,
|
||||
Playlists,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -100,8 +107,10 @@ pub enum LibraryResponse {
|
|||
Song(Song, usize),
|
||||
AllSongs(Vec<Song>),
|
||||
Library(MusicLibrary),
|
||||
Playlist(ExternalPlaylist),
|
||||
ImportM3UPlayList(Uuid, String)
|
||||
ExternalPlaylist(ExternalPlaylist),
|
||||
Playlist(Playlist),
|
||||
ImportM3UPlayList(Uuid, String),
|
||||
Playlists(Vec<(Uuid, String)>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
|
@ -170,6 +179,39 @@ impl ControllerHandle {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct ControllerState {
|
||||
path: PathBuf,
|
||||
volume: f32,
|
||||
now_playing: Uuid,
|
||||
}
|
||||
|
||||
impl ControllerState {
|
||||
fn new(path: PathBuf) -> Self {
|
||||
ControllerState {
|
||||
path,
|
||||
volume: 0.35,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn write_file(&self) -> Result<(), std::io::Error> {
|
||||
OpenOptions::new()
|
||||
.truncate(true)
|
||||
.create(true)
|
||||
.write(true)
|
||||
.open(&self.path)
|
||||
.unwrap()
|
||||
.write_all(&to_string_pretty(self)?.into_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_file(path: impl AsRef<Path>) -> Result<Self, std::io::Error> {
|
||||
let state = serde_json::from_str(&std::fs::read_to_string(path)?)?;
|
||||
Ok(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
||||
pub async fn start(
|
||||
|
@ -184,23 +226,22 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
where
|
||||
P: Player,
|
||||
{
|
||||
//TODO: make a separate event loop for sccessing library that clones borrowed values from inner library loop?
|
||||
let mut queue: Queue<QueueSong, QueueAlbum> = Queue {
|
||||
let queue: Queue<QueueSong, QueueAlbum> = Queue {
|
||||
items: Vec::new(),
|
||||
played: Vec::new(),
|
||||
loop_: false,
|
||||
shuffle: None,
|
||||
};
|
||||
// for testing porpuses
|
||||
// for song in &library.library {
|
||||
// queue.add_item(
|
||||
// QueueSong {
|
||||
// song: song.clone(),
|
||||
// location: PlayerLocation::Test,
|
||||
// },
|
||||
// true,
|
||||
// );
|
||||
// }
|
||||
|
||||
let state = {
|
||||
let path = &config.read().unwrap().state_path;
|
||||
if let Ok(state) = ControllerState::read_file(path) {
|
||||
state
|
||||
} else {
|
||||
ControllerState::new(path.clone())
|
||||
}
|
||||
};
|
||||
|
||||
let queue = queue;
|
||||
|
||||
std::thread::scope(|scope| {
|
||||
|
@ -220,19 +261,27 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
player_mail.1,
|
||||
queue_mail.0,
|
||||
_lib_mail,
|
||||
state,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
scope
|
||||
.spawn(async move {
|
||||
Controller::<P>::player_event_loop(player, player_mail.0)
|
||||
Controller::<P>::player_event_loop(
|
||||
player,
|
||||
player_mail.0
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
scope
|
||||
.spawn(async {
|
||||
Controller::<P>::library_loop(lib_mail.1, &mut library)
|
||||
Controller::<P>::library_loop(
|
||||
lib_mail.1,
|
||||
&mut library,
|
||||
config,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
|
@ -258,8 +307,14 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
player_mail: MailMan<PlayerResponse, PlayerCommand>,
|
||||
queue_mail: MailMan<QueueCommand, QueueResponse>,
|
||||
lib_mail: MailMan<LibraryCommand, LibraryResponse>,
|
||||
mut state: ControllerState,
|
||||
) -> Result<(), ()> {
|
||||
let mut first = true;
|
||||
{
|
||||
let volume = state.volume as f64;
|
||||
player.write().unwrap().set_volume(volume);
|
||||
println!("volume set to {volume}");
|
||||
}
|
||||
while true {
|
||||
let _mail = player_mail.recv().await;
|
||||
if let Ok(mail) = _mail {
|
||||
|
@ -282,9 +337,12 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
player_mail.send(PlayerResponse::Empty).await.unwrap();
|
||||
}
|
||||
PlayerCommand::SetVolume(volume) => {
|
||||
player.write().unwrap().set_volume(volume);
|
||||
player.write().unwrap().set_volume(volume as f64);
|
||||
println!("volume set to {volume}");
|
||||
player_mail.send(PlayerResponse::Empty).await.unwrap();
|
||||
|
||||
state.volume = volume;
|
||||
_ = state.write_file()
|
||||
}
|
||||
PlayerCommand::NextSong => {
|
||||
queue_mail.send(QueueCommand::Next).await.unwrap();
|
||||
|
@ -384,11 +442,26 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
// ...
|
||||
// let's just pretend I figured that out already
|
||||
|
||||
lib_mail.send(LibraryCommand::AllSongs).await.unwrap();
|
||||
let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else {
|
||||
unreachable!()
|
||||
let (songs, index) = match location {
|
||||
PlayerLocation::Library => {
|
||||
lib_mail.send(LibraryCommand::AllSongs).await.unwrap();
|
||||
let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else {
|
||||
unreachable!()
|
||||
};
|
||||
(songs, index)
|
||||
}
|
||||
PlayerLocation::Playlist(uuid) => {
|
||||
lib_mail.send(LibraryCommand::ExternalPlaylist(uuid)).await.unwrap();
|
||||
let LibraryResponse::ExternalPlaylist(list) = lib_mail.recv().await.unwrap() else {
|
||||
unreachable!()
|
||||
};
|
||||
let index = list.get_index(song.uuid).unwrap();
|
||||
(list.tracks, index)
|
||||
}
|
||||
_ => todo!("Got Location other than Library or Playlist")
|
||||
};
|
||||
|
||||
|
||||
for i in index+1..(index+50) {
|
||||
if let Some(song) = songs.get(i) {
|
||||
queue_mail.send(QueueCommand::Append(QueueItem::from_item_type(QueueItemType::Single(QueueSong { song: song.clone(), location })), false)).await.unwrap();
|
||||
|
@ -396,7 +469,7 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
unreachable!()
|
||||
};
|
||||
} else {
|
||||
println!("End of Library");
|
||||
println!("End of Library / Playlist");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -414,6 +487,7 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
async fn library_loop(
|
||||
lib_mail: MailMan<LibraryResponse, LibraryCommand>,
|
||||
library: &'c mut MusicLibrary,
|
||||
config: Arc<RwLock<Config>>,
|
||||
) -> Result<(), ()> {
|
||||
while true {
|
||||
match lib_mail.recv().await.unwrap() {
|
||||
|
@ -424,9 +498,9 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
LibraryCommand::AllSongs => {
|
||||
lib_mail.send(LibraryResponse::AllSongs(library.library.clone())).await.unwrap();
|
||||
},
|
||||
LibraryCommand::Playlist(uuid) => {
|
||||
LibraryCommand::ExternalPlaylist(uuid) => {
|
||||
let playlist = library.query_playlist_uuid(&uuid).unwrap();
|
||||
lib_mail.send(LibraryResponse::Playlist(ExternalPlaylist::from_playlist(playlist, &library))).await.unwrap();
|
||||
lib_mail.send(LibraryResponse::ExternalPlaylist(ExternalPlaylist::from_playlist(playlist, &library))).await.unwrap();
|
||||
}
|
||||
LibraryCommand::ImportM3UPlayList(path) => {
|
||||
let playlist = Playlist::from_m3u(path, library).unwrap();
|
||||
|
@ -436,6 +510,16 @@ impl<'c, P: Player + Send + Sync> Controller<'c, P> {
|
|||
|
||||
lib_mail.send(LibraryResponse::ImportM3UPlayList(uuid, name)).await.unwrap();
|
||||
}
|
||||
LibraryCommand::Save => {
|
||||
library.save({config.read().unwrap().libraries.get_library(&library.uuid).unwrap().path.clone()}).unwrap();
|
||||
lib_mail.send(LibraryResponse::Ok).await.unwrap();
|
||||
}
|
||||
LibraryCommand::Playlists => {
|
||||
let mut lists = vec![];
|
||||
library.playlists.lists_recursive().into_par_iter().map(|list| (list.uuid, list.title.clone())).collect_into_vec(&mut lists);
|
||||
|
||||
lib_mail.send(LibraryResponse::Playlists(lists)).await.unwrap();
|
||||
}
|
||||
_ => { todo!() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,17 @@ impl PlaylistFolder {
|
|||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn lists_recursive(&self) -> Vec<&Playlist> {
|
||||
let mut vec = vec![];
|
||||
for item in &self.items {
|
||||
match item {
|
||||
PlaylistFolderItem::List(ref playlist) => vec.push(playlist),
|
||||
PlaylistFolderItem::Folder(folder) => vec.append(&mut folder.lists_recursive()),
|
||||
}
|
||||
}
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
|
@ -107,13 +118,13 @@ impl Playlist {
|
|||
}
|
||||
pub fn get_index(&self, uuid: Uuid) -> Option<usize> {
|
||||
let mut i = 0;
|
||||
if self.contains(uuid) {
|
||||
if self.tracks.contains(&uuid) {
|
||||
for track in &self.tracks {
|
||||
i += 1;
|
||||
if &uuid == track {
|
||||
dbg!("Index gotted! ", i);
|
||||
return Some(i);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -351,7 +362,9 @@ pub struct ExternalPlaylist {
|
|||
impl ExternalPlaylist {
|
||||
pub(crate) fn from_playlist(playlist: &Playlist, library: &MusicLibrary) -> Self {
|
||||
let tracks: Vec<Song> = playlist.tracks.iter().filter_map(|uuid| {
|
||||
library.query_uuid(uuid).map(|res| res.0.clone())
|
||||
library.query_uuid(uuid).map(|res| {
|
||||
res.0.clone()
|
||||
})
|
||||
}).collect_vec();
|
||||
|
||||
Self {
|
||||
|
@ -363,6 +376,27 @@ impl ExternalPlaylist {
|
|||
play_time: playlist.play_time
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_index(&self, uuid: Uuid) -> Option<usize> {
|
||||
let mut i = 0;
|
||||
if self.contains(uuid) {
|
||||
for track in &self.tracks {
|
||||
if &uuid == &track.uuid {
|
||||
return Some(i);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn contains(&self, uuid: Uuid) -> bool {
|
||||
for track in &self.tracks {
|
||||
if track.uuid == uuid {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::wrappers::_Song;
|
|||
|
||||
#[tauri::command]
|
||||
pub async fn add_song_to_queue(app: AppHandle<Wry>, ctrl_handle: State<'_, ControllerHandle>, uuid: Uuid, location: PlayerLocation) -> Result<(), String> {
|
||||
dbg!(&location);
|
||||
ctrl_handle.lib_mail.send(dmp_core::music_controller::controller::LibraryCommand::Song(uuid)).await.unwrap();
|
||||
let LibraryResponse::Song(song, _) = ctrl_handle.lib_mail.recv().await.unwrap() else {
|
||||
unreachable!()
|
||||
|
|
|
@ -6,7 +6,7 @@ use dmp_core::{config::{Config, ConfigLibrary}, music_controller::controller::{C
|
|||
use tauri::{http::Response, Emitter, Manager, State, Url, WebviewWindowBuilder, Wry};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::wrappers::{get_library, play, pause, prev, set_volume, get_song, next, get_queue, import_playlist, get_playlist};
|
||||
use crate::wrappers::{get_library, play, pause, prev, set_volume, get_song, next, get_queue, import_playlist, get_playlist, get_playlists};
|
||||
|
||||
pub mod wrappers;
|
||||
pub mod commands;
|
||||
|
@ -76,6 +76,7 @@ pub fn run() {
|
|||
play_now,
|
||||
import_playlist,
|
||||
get_playlist,
|
||||
get_playlists
|
||||
]).manage(ConfigRx(rx))
|
||||
.manage(LibRx(lib_rx))
|
||||
.manage(HandleTx(handle_tx))
|
||||
|
@ -142,11 +143,15 @@ async fn get_config(state: State<'_, ConfigRx>) -> Result<Config, String> {
|
|||
|
||||
// dbg!(&dir);
|
||||
|
||||
let config = if let Ok(c) = Config::read_file(PathBuf::from(path).join("config")) {
|
||||
let config = if let Ok(mut c) = Config::read_file(PathBuf::from(path).join("config")) {
|
||||
if c.state_path == PathBuf::default() {
|
||||
c.state_path = PathBuf::from(path).join("state");
|
||||
}
|
||||
c
|
||||
} else {
|
||||
let c = Config {
|
||||
path: PathBuf::from(path).join("config"),
|
||||
state_path: PathBuf::from(path).join("state"),
|
||||
..Default::default()
|
||||
};
|
||||
c.write_file().unwrap();
|
||||
|
|
|
@ -39,7 +39,7 @@ pub async fn pause(app: AppHandle<Wry>, ctrl_handle: State<'_, ControllerHandle>
|
|||
|
||||
#[tauri::command]
|
||||
pub async fn set_volume(ctrl_handle: State<'_, ControllerHandle>, volume: String) -> Result<(), String> {
|
||||
let volume = volume.parse::<f64>().unwrap() / 1000.0;
|
||||
let volume = volume.parse::<f32>().unwrap() / 1000.0;
|
||||
ctrl_handle.player_mail.send(dmp_core::music_controller::controller::PlayerCommand::SetVolume(volume)).await.unwrap();
|
||||
let PlayerResponse::Empty = ctrl_handle.player_mail.recv().await.unwrap() else {
|
||||
unreachable!()
|
||||
|
@ -142,14 +142,25 @@ pub async fn get_library(ctrl_handle: State<'_, ControllerHandle>) -> Result<Vec
|
|||
|
||||
#[tauri::command]
|
||||
pub async fn get_playlist(ctrl_handle: State<'_, ControllerHandle>, uuid: Uuid) -> Result<Vec<_Song>, String> {
|
||||
ctrl_handle.lib_mail.send(LibraryCommand::Playlist(uuid)).await.unwrap();
|
||||
let LibraryResponse::Playlist(playlist) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") };
|
||||
ctrl_handle.lib_mail.send(LibraryCommand::ExternalPlaylist(uuid)).await.unwrap();
|
||||
let LibraryResponse::ExternalPlaylist(playlist) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") };
|
||||
|
||||
let songs = playlist.tracks.iter().map(|song| _Song::from(song)).collect::<Vec<_>>();
|
||||
println!("Got Playlist {}, len {}", playlist.title, playlist.tracks.len());
|
||||
Ok(songs)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_playlists(app: AppHandle<Wry>, ctrl_handle: State<'_, ControllerHandle>) -> Result<(), String> {
|
||||
println!("getting Playlists");
|
||||
ctrl_handle.lib_mail.send(LibraryCommand::Playlists).await.unwrap();
|
||||
let LibraryResponse::Playlists(lists) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!() };
|
||||
println!("gotten playlists");
|
||||
|
||||
app.emit("playlists_gotten", lists.into_iter().map(|(uuid, name)| PlaylistPayload { uuid, name }).collect_vec()).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn import_playlist(ctrl_handle: State<'_, ControllerHandle>) -> Result<PlaylistPayload, String> {
|
||||
let file = rfd::AsyncFileDialog::new()
|
||||
|
@ -161,11 +172,13 @@ pub async fn import_playlist(ctrl_handle: State<'_, ControllerHandle>) -> Result
|
|||
|
||||
ctrl_handle.lib_mail.send(LibraryCommand::ImportM3UPlayList(PathBuf::from(file.path()))).await.unwrap();
|
||||
let LibraryResponse::ImportM3UPlayList(uuid, name) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") };
|
||||
ctrl_handle.lib_mail.send(LibraryCommand::Save).await.unwrap();
|
||||
let LibraryResponse::Ok = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!() };
|
||||
println!("Imported Playlist {name}");
|
||||
Ok(PlaylistPayload {uuid, name})
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct PlaylistPayload {
|
||||
uuid: Uuid,
|
||||
name: String
|
||||
|
|
47
src/App.tsx
47
src/App.tsx
|
@ -98,7 +98,40 @@ interface PlaylistHeadProps {
|
|||
|
||||
function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary }: PlaylistHeadProps) {
|
||||
|
||||
let handle_import = () => {
|
||||
useEffect(() => {
|
||||
const unlisten = appWindow.listen<any[]>("playlists_gotten", (_res) => {
|
||||
// console.log(event);
|
||||
let res = _res.payload;
|
||||
|
||||
setPlaylists([
|
||||
...res.map( (item) => {
|
||||
return (
|
||||
<button onClick={ () => {
|
||||
invoke('get_playlist', { uuid: item.uuid }).then((list) => {
|
||||
setLibrary([...(list as any[]).map((song) => {
|
||||
// console.log(song);
|
||||
return (
|
||||
<Song
|
||||
key={ song.uuid }
|
||||
location={ song.location }
|
||||
playerLocation={ {"Playlist" : item.uuid } }
|
||||
uuid={ song.uuid }
|
||||
plays={ song.plays }
|
||||
duration={ song.duration }
|
||||
tags={ song.tags }
|
||||
/>
|
||||
)
|
||||
})])
|
||||
})
|
||||
setViewName( item.name )
|
||||
} } key={ 'playlist_' + item.uuid }>{ item.name }</button>
|
||||
)
|
||||
})
|
||||
])
|
||||
})
|
||||
return () => { unlisten.then((f) => f()) }
|
||||
}, []);
|
||||
let handle_import = () => {
|
||||
invoke('import_playlist').then((_res) => {
|
||||
let res = _res as any;
|
||||
|
||||
|
@ -114,6 +147,7 @@ function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary }: Play
|
|||
<Song
|
||||
key={ song.uuid }
|
||||
location={ song.location }
|
||||
playerLocation={ {"Playlist" : res.uuid } }
|
||||
uuid={ song.uuid }
|
||||
plays={ song.plays }
|
||||
duration={ song.duration }
|
||||
|
@ -140,6 +174,7 @@ function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary }: Play
|
|||
<Song
|
||||
key={ song.uuid }
|
||||
location={ song.location }
|
||||
playerLocation="Library"
|
||||
uuid={ song.uuid }
|
||||
plays={ song.plays }
|
||||
duration={ song.duration }
|
||||
|
@ -150,7 +185,7 @@ function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary }: Play
|
|||
})
|
||||
} }>Library</button>
|
||||
{ playlists }
|
||||
<button onClick={ handle_import }>Import .m3u8 Playlist</button>
|
||||
<button onClick={ handle_import }>Import .m3u Playlist</button>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
@ -166,15 +201,16 @@ function MainView({ lib_ref, viewName }: MainViewProps) {
|
|||
useEffect(() => {
|
||||
const unlisten = appWindow.listen<any>("library_loaded", (_) => {
|
||||
console.log("library_loaded");
|
||||
invoke('get_playlists').then(() => {})
|
||||
|
||||
invoke('get_library').then((lib) => {
|
||||
setLibrary([...(lib as any[]).map((song) => {
|
||||
console.log(song);
|
||||
|
||||
return (
|
||||
<Song
|
||||
key={ song.uuid }
|
||||
location={ song.location }
|
||||
playerLocation="Library"
|
||||
uuid={ song.uuid }
|
||||
plays={ song.plays }
|
||||
duration={ song.duration }
|
||||
|
@ -198,6 +234,7 @@ function MainView({ lib_ref, viewName }: MainViewProps) {
|
|||
|
||||
interface SongProps {
|
||||
location: any,
|
||||
playerLocation: string | {"Playlist" : any},
|
||||
uuid: string,
|
||||
plays: number,
|
||||
format?: string,
|
||||
|
@ -218,11 +255,11 @@ function Song(props: SongProps) {
|
|||
<p className="artist">{ props.tags.AlbumArtist }</p>
|
||||
<p className="duration">{ props.duration }</p>
|
||||
<button onClick={(_) => {
|
||||
invoke('add_song_to_queue', { uuid: props.uuid, location: 'Library' }).then(() => {} )
|
||||
invoke('add_song_to_queue', { uuid: props.uuid, location: props.playerLocation }).then(() => {} )
|
||||
}}
|
||||
>Add to Queue</button>
|
||||
<button onClick={() => {
|
||||
invoke("play_now", { uuid: props.uuid, location: 'Library' }).then(() => {})
|
||||
invoke("play_now", { uuid: props.uuid, location: props.playerLocation }).then(() => {})
|
||||
}}>Play Now</button>
|
||||
</div>
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue