playlist play, optimized layout & better player style implemented

This commit is contained in:
KRTirtho 2021-02-15 00:32:06 +06:00
parent 23394e437b
commit b97a8edc5b
5 changed files with 66 additions and 39 deletions

View File

@ -1,3 +0,0 @@
[Dolphin]
Timestamp=2021,2,13,23,13,52
Version=4

View File

@ -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() {
<MemoryRouter>
<authContext.Provider value={{ isLoggedIn, setIsLoggedIn, access_token }}>
<playerContext.Provider value={{ spotifyApi, currentPlaylist, currentTrack, setCurrentPlaylist, setCurrentTrack }}>
<BoxView direction={Direction.TopToBottom}>
<View style={`flex: 1; flex-direction: 'column'; justify-content: 'center'; align-items: 'stretch'; height: '100%';`}>
<Routes />
{isLoggedIn && <Player />}
</BoxView>
</View>
</playerContext.Provider>
</authContext.Provider>
</MemoryRouter>

View File

@ -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<SpotifyApi.CategoryObject[]>([]);
@ -26,8 +26,8 @@ function Home() {
}, [access_token]);
return (
<ScrollArea style={`flex-grow: 1; border: none;`}>
<View style={`flex-direction: 'column'; justify-content: 'center'; align-items: 'stretch';`}>
<ScrollArea style={`flex-grow: 1; border: none; flex: 1;`}>
<View style={`flex-direction: 'column'; justify-content: 'center'; flex: 1;`}>
<CategoryCard key={((Math.random() * Date.now()) / Math.random()) * 100} id="current" name="Currently Playing" />
{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';
}
`;

View File

@ -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<number>(parseFloat(localStorage.getItem("volume") ?? "55"));
const [totalDuration, setTotalDuration] = useState(0);
const [shuffle, setShuffle] = useState<boolean>(false);
const [realPlaylist, setRealPlaylist] = useState<CurrentPlaylist["tracks"]>([]);
@ -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 (
<GridView style="flex: 1; max-height: 100px;">
<GridView enabled={!!currentTrack} style="flex: 1; max-height: 100px;">
<GridRow>
<GridColumn width={2}>
<Text ref={titleRef} wordWrap>

View File

@ -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<PlaylistViewProps> = () => {
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<SpotifyApi.PlaylistTrackObject[]>([]);
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<PlaylistViewProps> = () => {
}
}, []);
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 (
<BoxView direction={Direction.TopToBottom}>
<BackButton />
<View style={`flex-direction: 'column'; flex-grow: 1;`}>
<View style={`justify-content: 'space-between'; padding-bottom: 10px; padding-left: 10px;`}>
<BackButton />
<View style={`height: 50px; justify-content: 'space-between'; width: 100px; padding-right: 20px;`}>
<IconButton icon={new QIcon(heartRegular)} />
<IconButton style={`background-color: #00be5f; color: white;`} on={{ clicked: handlePlaylistPlayPause }} icon={new QIcon(currentPlaylist?.id === params.id ? stop : play)} />
</View>
</View>
<Text>{`<center><h2>${location.state.name[0].toUpperCase()}${location.state.name.slice(1)}</h2></center>`}</Text>
<ScrollArea style={`flex-grow: 1; border: none;`}>
<View style={`flex-direction:column;`}>
@ -70,7 +87,7 @@ const PlaylistView: FC<PlaylistViewProps> = () => {
})}
</View>
</ScrollArea>
</BoxView>
</View>
);
};