diff --git a/.directory b/.directory deleted file mode 100644 index bdef6c5a..00000000 --- a/.directory +++ /dev/null @@ -1,3 +0,0 @@ -[Dolphin] -Timestamp=2021,2,13,23,13,52 -Version=4 diff --git a/src/app.tsx b/src/app.tsx index de7840b8..a88ed54c 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from "react"; -import { Window, hot, BoxView, View } from "@nodegui/react-nodegui"; -import { Direction, QIcon, QMainWindow, WidgetEventTypes, WindowState } from "@nodegui/nodegui"; +import { Window, hot, View } from "@nodegui/react-nodegui"; +import { QIcon, QMainWindow, WidgetEventTypes, WindowState } from "@nodegui/nodegui"; import nodeguiIcon from "../assets/nodegui.jpg"; import { MemoryRouter } from "react-router"; import Routes from "./routes"; @@ -19,7 +19,7 @@ export interface Credentials { clientSecret: string; } -const minSize = { width: 700, height: 520 }; +const minSize = { width: 700, height: 750 }; const winIcon = new QIcon(nodeguiIcon); global.localStorage = new LocalStorage("./local"); @@ -35,13 +35,21 @@ function RootApp() { const credentialStr = localStorage.getItem(CredentialKeys.credentials); useEffect(() => { - windowRef.current?.addEventListener(WidgetEventTypes.Close, () => { + setIsLoggedIn(!!credentialStr); + }, []); + + useEffect(() => { + const onWindowClose = () => { if (audioPlayer.isRunning()) { audioPlayer.stop().catch((e) => console.error("Failed to quit MPV player: ", e)); } - }); - setIsLoggedIn(!!credentialStr); - }, []); + }; + + windowRef.current?.addEventListener(WidgetEventTypes.Close, onWindowClose); + return () => { + windowRef.current?.removeEventListener(WidgetEventTypes.Close, onWindowClose); + }; + }); useEffect(() => { if (isLoggedIn) { @@ -67,10 +75,10 @@ function RootApp() { - + {isLoggedIn && } - + diff --git a/src/components/Home.tsx b/src/components/Home.tsx index adf7ea57..1b68a50e 100644 --- a/src/components/Home.tsx +++ b/src/components/Home.tsx @@ -1,5 +1,5 @@ import React, { useContext, useEffect, useState } from "react"; -import { Button, Text, View, ScrollArea } from "@nodegui/react-nodegui"; +import { Button, View, ScrollArea } from "@nodegui/react-nodegui"; import playerContext from "../context/playerContext"; import authContext from "../context/authContext"; import { useHistory } from "react-router"; @@ -7,7 +7,7 @@ import CachedImage from "./shared/CachedImage"; import { CursorShape } from "@nodegui/nodegui"; function Home() { - const { spotifyApi, currentPlaylist, currentTrack } = useContext(playerContext); + const { spotifyApi } = useContext(playerContext); const { isLoggedIn, access_token } = useContext(authContext); const [categories, setCategories] = useState([]); @@ -26,8 +26,8 @@ function Home() { }, [access_token]); return ( - - + + {isLoggedIn && categories.map(({ id, name }, index) => { @@ -75,6 +75,7 @@ function CategoryCard({ id, name }: CategoryCardProps) { const categoryStylesheet = ` #container{ + flex: 1; flex-direction: column; justify-content: 'center'; margin-bottom: 20px; @@ -94,7 +95,10 @@ function CategoryCard({ id, name }: CategoryCardProps) { text-decoration: underline; } #child-view{ + flex: 1; justify-content: 'space-evenly'; + align-items: 'center'; + flex-wrap: 'wrap'; } `; diff --git a/src/components/Player.tsx b/src/components/Player.tsx index dabbfd32..c2cd68ca 100644 --- a/src/components/Player.tsx +++ b/src/components/Player.tsx @@ -23,7 +23,7 @@ export const audioPlayer = new NodeMpv( function Player(): ReactElement { const { currentTrack, currentPlaylist, setCurrentTrack, setCurrentPlaylist } = useContext(playerContext); - const [volume, setVolume] = useState(55); + const [volume, setVolume] = useState(parseFloat(localStorage.getItem("volume") ?? "55")); const [totalDuration, setTotalDuration] = useState(0); const [shuffle, setShuffle] = useState(false); const [realPlaylist, setRealPlaylist] = useState([]); @@ -34,6 +34,9 @@ function Player(): ReactElement { sliderMoved: (value) => { setVolume(value); }, + sliderReleased: () => { + localStorage.setItem("volume", volume.toString()); + } }, [] ); @@ -47,10 +50,8 @@ function Player(): ReactElement { if (!playerRunning) { await audioPlayer.start(); } - await audioPlayer.volume(55); } catch (error) { - console.error("Failed to start audio player"); - console.error(error); + console.error("Failed to start audio player", error); } })(); @@ -157,9 +158,9 @@ function Player(): ReactElement { } } - const artistsNames = currentTrack?.artists.map((x) => x.name); + const artistsNames = currentTrack?.artists?.map((x) => x.name); return ( - + diff --git a/src/components/PlaylistView.tsx b/src/components/PlaylistView.tsx index 725f5432..09962f31 100644 --- a/src/components/PlaylistView.tsx +++ b/src/components/PlaylistView.tsx @@ -1,11 +1,14 @@ import React, { FC, useContext, useEffect, useState } from "react"; -import { BoxView, Button, ScrollArea, Text, View } from "@nodegui/react-nodegui"; +import { BoxView, Button, GridView, ScrollArea, Text, View } from "@nodegui/react-nodegui"; import BackButton from "./BackButton"; import { useLocation, useParams } from "react-router"; -import { Direction, QAbstractButtonSignals } from "@nodegui/nodegui"; +import { Direction, QAbstractButtonSignals, QIcon } from "@nodegui/nodegui"; import { WidgetEventListeners } from "@nodegui/react-nodegui/dist/components/View/RNView"; import authContext from "../context/authContext"; import playerContext from "../context/playerContext"; +import IconButton from "./shared/IconButton"; +import { heartRegular, play, stop } from "../icons"; +import { audioPlayer } from "./Player"; export interface PlaylistTrackRes { name: string; @@ -21,20 +24,9 @@ const PlaylistView: FC = () => { const { isLoggedIn, access_token } = useContext(authContext); const { spotifyApi, setCurrentTrack, currentPlaylist, currentTrack, setCurrentPlaylist } = useContext(playerContext); const params = useParams<{ id: string }>(); - const location = useLocation<{ name: string, thumbnail: string }>(); + const location = useLocation<{ name: string; thumbnail: string }>(); const [tracks, setTracks] = useState([]); - const trackClickHandler = async (track: SpotifyApi.TrackObjectFull) => { - try { - setCurrentTrack(track); - if (currentPlaylist?.id !== params.id) { - setCurrentPlaylist({...params, ...location.state, tracks}); - } - } catch (error) { - console.error("Failed to resolve track's youtube url: ", error); - } - }; - useEffect(() => { if (isLoggedIn) { (async () => { @@ -49,9 +41,34 @@ const PlaylistView: FC = () => { } }, []); + const handlePlaylistPlayPause = () => { + if (currentPlaylist?.id !== params.id) { + setCurrentPlaylist({ ...params, ...location.state, tracks }); + setCurrentTrack(tracks[0].track); + } else { + audioPlayer.stop().catch((error) => console.error("Failed to stop audio player: ", error)); + setCurrentTrack(undefined); + setCurrentPlaylist(undefined); + } + }; + + const trackClickHandler = async (track: SpotifyApi.TrackObjectFull) => { + try { + setCurrentTrack(track); + } catch (error) { + console.error("Failed to resolve track's youtube url: ", error); + } + }; + return ( - - + + + + + + + + {`

${location.state.name[0].toUpperCase()}${location.state.name.slice(1)}

`}
@@ -70,7 +87,7 @@ const PlaylistView: FC = () => { })} -
+
); };