Moved context menu from Songs to MainView to improve loading speed

This commit is contained in:
MrDulfin 2025-06-05 06:11:53 -04:00
parent 624e6f2db6
commit 672d472742

View file

@ -19,6 +19,8 @@ function App() {
const [playlists, setPlaylists] = useState<JSX.Element[]>([]); const [playlists, setPlaylists] = useState<JSX.Element[]>([]);
const [viewName, setViewName] = useState("Library"); const [viewName, setViewName] = useState("Library");
const playlistsInfo= useRef<PlaylistInfo[]>([]); const playlistsInfo= useRef<PlaylistInfo[]>([]);
const selectedSong = useRef<SongProps>();
const setSelected = (props: SongProps) => {selectedSong.current = props;}
const [nowPlaying, setNowPlaying] = useState<JSX.Element>( const [nowPlaying, setNowPlaying] = useState<JSX.Element>(
<NowPlaying <NowPlaying
@ -84,8 +86,8 @@ function App() {
<main> <main>
<div className="container"> <div className="container">
<div className="leftSide"> <div className="leftSide">
<PlaylistHead playlists={ playlists } setPlaylists={ setPlaylists } setViewName={ setViewName } setLibrary={ library[1] } playlistsInfo={ playlistsInfo }/> <PlaylistHead playlists={ playlists } setPlaylists={ setPlaylists } setViewName={ setViewName } setLibrary={ library[1] } playlistsInfo={ playlistsInfo } setSelected={ setSelected } />
<MainView lib_ref={ library } viewName={ viewName } playlistsInfo={ playlistsInfo } /> <MainView lib_ref={ library } viewName={ viewName } playlistsInfo={ playlistsInfo } setSelected={ setSelected } selectedSong={ selectedSong} />
</div> </div>
<div className="rightSide"> <div className="rightSide">
{ nowPlaying } { nowPlaying }
@ -113,14 +115,17 @@ interface PlaylistHeadProps {
setViewName: React.Dispatch<React.SetStateAction<string>>, setViewName: React.Dispatch<React.SetStateAction<string>>,
setLibrary: React.Dispatch<React.SetStateAction<JSX.Element[]>>, setLibrary: React.Dispatch<React.SetStateAction<JSX.Element[]>>,
playlistsInfo: MutableRefObject<PlaylistInfo[]>, playlistsInfo: MutableRefObject<PlaylistInfo[]>,
setSelected: (props: SongProps) => void,
} }
function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary, playlistsInfo }: PlaylistHeadProps) { function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary, playlistsInfo, setSelected }: PlaylistHeadProps) {
function getPlaylist(playlist: PlaylistInfo) { function getPlaylist(playlist: PlaylistInfo) {
invoke('get_playlist', { uuid: playlist.uuid }).then((list) => { invoke('get_playlist', { uuid: playlist.uuid }).then((list) => {
let i = 0;
setLibrary([...(list as any[]).map((song) => { setLibrary([...(list as any[]).map((song) => {
// console.log(song); // console.log(song);
const reload = () => getPlaylist(playlist) const reload = () => getPlaylist(playlist)
i++;
return ( return (
<Song <Song
key={ song.uuid + Math.floor(Math.random() * 100_000_000_000) } key={ song.uuid + Math.floor(Math.random() * 100_000_000_000) }
@ -132,6 +137,8 @@ function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary, playli
tags={ song.tags } tags={ song.tags }
playlists={ playlistsInfo } playlists={ playlistsInfo }
reload = { reload } reload = { reload }
index = { i - 1 }
setSelected={ setSelected }
/> />
) )
})]) })])
@ -189,9 +196,10 @@ function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary, playli
<button onClick={() => { <button onClick={() => {
setViewName("Library"); setViewName("Library");
invoke('get_library').then((lib) => { invoke('get_library').then((lib) => {
let i = 0;
setLibrary([...(lib as any[]).map((song) => { setLibrary([...(lib as any[]).map((song) => {
// console.log(song); // console.log(song);
i++;
return ( return (
<Song <Song
key={ song.uuid + Math.floor(Math.random() * 100_000_000_000) } key={ song.uuid + Math.floor(Math.random() * 100_000_000_000) }
@ -202,6 +210,8 @@ function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary, playli
duration={ song.duration } duration={ song.duration }
tags={ song.tags } tags={ song.tags }
playlists={ playlistsInfo } playlists={ playlistsInfo }
index={ i - 1 }
setSelected={ setSelected }
/> />
) )
})]) })])
@ -218,17 +228,66 @@ interface MainViewProps {
lib_ref: [JSX.Element[], React.Dispatch<React.SetStateAction<JSX.Element[]>>], lib_ref: [JSX.Element[], React.Dispatch<React.SetStateAction<JSX.Element[]>>],
viewName: string, viewName: string,
playlistsInfo: MutableRefObject<PlaylistInfo[]>, playlistsInfo: MutableRefObject<PlaylistInfo[]>,
setSelected: (props: SongProps) => void,
selectedSong: MutableRefObject<SongProps | undefined>,
} }
function MainView({ lib_ref, viewName, playlistsInfo }: MainViewProps) { function MainView({ lib_ref, viewName, playlistsInfo, setSelected, selectedSong }: MainViewProps) {
const [library, setLibrary] = lib_ref; const [library, setLibrary] = lib_ref;
const addToQueue = (_: string) => {
invoke('add_song_to_queue', { uuid: selectedSong.current!.uuid, location: selectedSong.current!.playerLocation }).then(() => {});
}
const playNow = () => invoke("play_now", { uuid: selectedSong.current!.uuid, location: selectedSong.current!.playerLocation }).then(() => {})
const playNext = () => invoke("play_next_queue", { uuid: selectedSong.current!.uuid, location: selectedSong.current!.playerLocation }).then(() => {})
const removeLibPlaylist = () => {
invoke("remove_from_lib_playlist", { song: selectedSong.current!.uuid, location: selectedSong.current!.playerLocation }).then(() => {
if (selectedSong.current!.reload !== undefined) {
selectedSong.current!.reload()
}
})
}
async function clickHandler(event: React.MouseEvent) {
event.preventDefault();
const _ = await invoke('get_playlists');
let removeText = "Remove from Library";
if (selectedSong.current!.playerLocation != "Library") {
removeText = "Remove from Playlist";
}
const menu = await Menu.new({
items: [
{ id: "play_now_" + selectedSong.current!.uuid, text: "Play Now", action: playNow },
{ id: "play_next_" + selectedSong.current!.uuid, text: "Play Next", action: playNext },
{ id: "add_song_to_queue" + selectedSong.current!.uuid, text: "Add to Queue", action: addToQueue },
await Submenu.new(
{
text: "Add to Playlist...",
items: [...selectedSong.current!.playlists.current.map((list) => {
const addToPlaylist = () => {
invoke('add_song_to_playlist', { playlist: list.uuid, song: selectedSong.current!.uuid }).then(() => {});
}
return { id: "add_song_to_playlists" + selectedSong.current!.uuid + list.uuid, text: list.name, action: addToPlaylist }
})]
} as SubmenuOptions
),
{ id: "remove_from_lib_playlist" + selectedSong.current!.location + selectedSong.current!.uuid, text: removeText, action: removeLibPlaylist },
]
})
;
const pos = new LogicalPosition(event.clientX, event.clientY);
menu.popup(pos);
}
useEffect(() => { useEffect(() => {
const unlisten = appWindow.listen<any>("library_loaded", (_) => { const unlisten = appWindow.listen<any>("library_loaded", (_) => {
console.log("library_loaded"); console.log("library_loaded");
invoke('get_library').then((lib) => { invoke('get_library').then((lib) => {
let i = 0;
setLibrary([...(lib as any[]).map((song) => { setLibrary([...(lib as any[]).map((song) => {
i++;
return ( return (
<Song <Song
key={ song.uuid + Math.floor(Math.random() * 100_000_000_000) } key={ song.uuid + Math.floor(Math.random() * 100_000_000_000) }
@ -239,6 +298,8 @@ function MainView({ lib_ref, viewName, playlistsInfo }: MainViewProps) {
duration={ song.duration } duration={ song.duration }
tags={ song.tags } tags={ song.tags }
playlists={ playlistsInfo } playlists={ playlistsInfo }
index={ i - 1 }
setSelected={ setSelected }
/> />
) )
})]) })])
@ -251,7 +312,10 @@ function MainView({ lib_ref, viewName, playlistsInfo }: MainViewProps) {
return ( return (
<div className="mainView"> <div
onDoubleClick={ playNow }
onContextMenu={ clickHandler }
className="mainView">
<h1>{ viewName }</h1> <h1>{ viewName }</h1>
<div>{ library }</div> <div>{ library }</div>
</div> </div>
@ -271,55 +335,13 @@ interface SongProps {
date_modified?: string, date_modified?: string,
tags: any, tags: any,
playlists: MutableRefObject<PlaylistInfo[]>, playlists: MutableRefObject<PlaylistInfo[]>,
index: number,
setSelected: (props: SongProps) => void,
reload?: () => void reload?: () => void
} }
function Song(props: SongProps) { function Song(props: SongProps) {
// console.log(props.tags); // console.log(props.tags);
const addToQueue = (_: string) => {
invoke('add_song_to_queue', { uuid: props.uuid, location: props.playerLocation }).then(() => {});
}
const playNow = () => invoke("play_now", { uuid: props.uuid, location: props.playerLocation }).then(() => {})
const playNext = () => invoke("play_next_queue", { uuid: props.uuid, location: props.playerLocation }).then(() => {})
const removeLibPlaylist = () => {
invoke("remove_from_lib_playlist", { song: props.uuid, location: props.playerLocation }).then(() => {
if (props.reload !== undefined) {
props.reload()
}
})
}
async function clickHandler(event: React.MouseEvent) {
event.preventDefault();
const _ = await invoke('get_playlists');
let removeText = "Remove from Library";
if (props.playerLocation != "Library") {
removeText = "Remove from Playlist";
}
const menu = await Menu.new({
items: [
{ id: "play_now_" + props.uuid, text: "Play Now", action: playNow },
{ id: "play_next_" + props.uuid, text: "Play Next", action: playNext },
{ id: "add_song_to_queue" + props.uuid, text: "Add to Queue", action: addToQueue },
await Submenu.new(
{
text: "Add to Playlist...",
items: [...props.playlists.current.map((list) => {
const addToPlaylist = () => {
invoke('add_song_to_playlist', { playlist: list.uuid, song: props.uuid }).then(() => {});
}
return { id: "add_song_to_playlists" + props.uuid + list.uuid, text: list.name, action: addToPlaylist }
})]
} as SubmenuOptions
),
{ id: "remove_from_lib_playlist" + props.location + props.uuid, text: removeText, action: removeLibPlaylist },
]
})
;
const pos = new LogicalPosition(event.clientX, event.clientY);
menu.popup(pos);
}
// useEffect(() => { // useEffect(() => {
// const unlistenPromise = listen<string>("add_song_to_queue", (event) => { // const unlistenPromise = listen<string>("add_song_to_queue", (event) => {
// switch (event.payload) { // switch (event.payload) {
@ -332,11 +354,14 @@ function Song(props: SongProps) {
// unlistenPromise.then((unlisten) => unlisten()); // unlistenPromise.then((unlisten) => unlisten());
// }; // };
// }, []); // }, []);
const setSelected = () => {
props.setSelected(props);
console.log(props.tags.TrackTitle);
}
return( return(
<div <div
onDoubleClick = { playNow } onContextMenu={ setSelected }
onContextMenu={ clickHandler } onClick={ setSelected }
className="song"> className="song">
<p className="artist unselectable">{ props.tags.TrackArtist }</p> <p className="artist unselectable">{ props.tags.TrackArtist }</p>
<p className="title unselectable">{ props.tags.TrackTitle }</p> <p className="title unselectable">{ props.tags.TrackTitle }</p>