From 35da4d5fd435eb0c9387cb7564d663dbe36a01c6 Mon Sep 17 00:00:00 2001 From: KRTirtho Date: Mon, 3 May 2021 13:25:17 +0600 Subject: [PATCH] fixed webpack rmSync is not a function & added cached playback --- src/app.tsx | 9 +------- src/components/Player.tsx | 27 +++++++++++++++++------ src/conf.ts | 33 ++++++++++++++++++----------- src/helpers/getCachedImageBuffer.ts | 15 ++++++------- src/hooks/useSpotifyApi.ts | 2 +- 5 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index 3e5c6928..52bd8621 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -14,17 +14,10 @@ import spotifyApi from "./initializations/spotifyApi"; import showError from "./helpers/showError"; import fs from "fs"; import path from "path"; -import { confDir } from "./conf"; +import { confDir, LocalStorageKeys } from "./conf"; import spotubeIcon from "../assets/icon.svg"; import preferencesContext, { PreferencesContextProperties } from "./context/preferencesContext"; -export enum LocalStorageKeys { - credentials = "credentials", - refresh_token = "refresh_token", - preferences = "user-preferences", - volume = "volume", -} - export interface Credentials { clientId: string; clientSecret: string; diff --git a/src/components/Player.tsx b/src/components/Player.tsx index 263e814b..b299df2f 100644 --- a/src/components/Player.tsx +++ b/src/components/Player.tsx @@ -4,14 +4,14 @@ import React, { ReactElement, useContext, useEffect, useRef, useState } from "re import playerContext, { CurrentPlaylist } from "../context/playerContext"; import { shuffleArray } from "../helpers/shuffleArray"; import NodeMpv from "node-mpv"; -import { getYoutubeTrack } from "../helpers/getYoutubeTrack"; +import { getYoutubeTrack, YoutubeTrack } from "../helpers/getYoutubeTrack"; import PlayerProgressBar from "./PlayerProgressBar"; import { random as shuffleIcon, play, pause, backward, forward, stop, heartRegular, heart, musicNode } from "../icons"; import IconButton from "./shared/IconButton"; import showError from "../helpers/showError"; import useTrackReaction from "../hooks/useTrackReaction"; import ManualLyricDialog from "./ManualLyricDialog"; -import { LocalStorageKeys } from "../app"; +import { LocalStorageKeys } from "../conf"; export const audioPlayer = new NodeMpv( { @@ -35,6 +35,7 @@ function Player(): ReactElement { const [realPlaylist, setRealPlaylist] = useState([]); const [isStopped, setIsStopped] = useState(false); const [openLyrics, setOpenLyrics] = useState(false); + const [currentYtTrack, setCurrentYtTrack] = useState(); const playlistTracksIds = currentPlaylist?.tracks.map((t) => t.track.id); const volumeHandler = useEventHandler( { @@ -49,6 +50,8 @@ function Player(): ReactElement { ); const playerRunning = audioPlayer.isRunning(); const titleRef = useRef(); + const cachedPlaylist = localStorage.getItem(LocalStorageKeys.cachedPlaylist); + const cachedTrack = localStorage.getItem(LocalStorageKeys.cachedTrack); // initial Effect useEffect(() => { @@ -61,21 +64,31 @@ function Player(): ReactElement { } catch (error) { showError(error, "[Failed starting audio player]: "); } - })(); + })().then(() => { + if (cachedPlaylist && !currentPlaylist) { + setCurrentPlaylist(JSON.parse(cachedPlaylist)); + } + if (cachedTrack && !currentTrack) { + setCurrentTrack(JSON.parse(cachedTrack)); + } + }); return () => { if (playerRunning) { - audioPlayer.quit().catch((e: any) => console.log(e)); + audioPlayer.quit().catch((e: unknown) => console.log(e)); } }; }, []); // track change effect useEffect(() => { + // caching current track + localStorage.setItem(LocalStorageKeys.cachedTrack, JSON.stringify(currentTrack ?? "")); (async () => { try { if (currentTrack && playerRunning) { const youtubeTrack = await getYoutubeTrack(currentTrack); + setCurrentYtTrack(youtubeTrack); await audioPlayer.load(youtubeTrack.youtube_uri, "replace"); await audioPlayer.play(); setIsPaused(false); @@ -94,6 +107,8 @@ function Player(): ReactElement { // changing shuffle to default useEffect(() => { setShuffle(false); + // caching playlist + localStorage.setItem(LocalStorageKeys.cachedPlaylist, JSON.stringify(currentPlaylist ?? "")); }, [currentPlaylist]); useEffect(() => { @@ -191,10 +206,10 @@ function Player(): ReactElement { - + {artistsNames && currentTrack ? ` -

${currentTrack.name} - ${artistsNames[0]} ${artistsNames.length > 1 ? "feat. " + artistsNames.slice(1).join(", ") : ""}

+

${currentTrack.name} - ${artistsNames[0]} ${artistsNames.length > 1 ? "feat. " + artistsNames.slice(1).join(", ") : ""}

` : `Oh, dear don't waste time`}
diff --git a/src/conf.ts b/src/conf.ts index 7f727fb2..70f7fafd 100644 --- a/src/conf.ts +++ b/src/conf.ts @@ -1,23 +1,32 @@ -import dotenv from "dotenv" +import dotenv from "dotenv"; import { homedir } from "os"; import { join } from "path"; -const env = dotenv.config({path: join(process.cwd(), ".env")}).parsed as any +const env = dotenv.config({ path: join(process.cwd(), ".env") }).parsed as any; export const clientId = ""; -export const trace = process.argv.find(arg => arg === "--trace") ?? false; -export const redirectURI = "http://localhost:4304/auth/spotify/callback" -export const confDir = join(homedir(), ".config", "spotube") -export const cacheDir = join(homedir(), ".cache", "spotube") +export const trace = process.argv.find((arg) => arg === "--trace") ?? false; +export const redirectURI = "http://localhost:4304/auth/spotify/callback"; +export const confDir = join(homedir(), ".config", "spotube"); +export const cacheDir = join(homedir(), ".cache", "spotube"); -export enum QueryCacheKeys{ - categories="categories", +export enum QueryCacheKeys { + categories = "categories", categoryPlaylists = "categoryPlaylists", featuredPlaylists = "featuredPlaylists", - genrePlaylists="genrePlaylists", - playlistTracks="playlistTracks", + genrePlaylists = "genrePlaylists", + playlistTracks = "playlistTracks", userPlaylists = "user-palylists", userSavedTracks = "user-saved-tracks", search = "search", searchPlaylist = "searchPlaylist", - searchSongs = "searchSongs" -} \ No newline at end of file + searchSongs = "searchSongs", +} + +export enum LocalStorageKeys { + credentials = "credentials", + refresh_token = "refresh_token", + preferences = "user-preferences", + volume = "volume", + cachedPlaylist = "cached-playlist", + cachedTrack = "cached-track" +} diff --git a/src/helpers/getCachedImageBuffer.ts b/src/helpers/getCachedImageBuffer.ts index 38661f8e..31f8410d 100644 --- a/src/helpers/getCachedImageBuffer.ts +++ b/src/helpers/getCachedImageBuffer.ts @@ -1,6 +1,6 @@ import path from "path"; import isUrl from "is-url"; -import * as fs from "fs" +import fs from "fs"; import axios from "axios"; import { Stream } from "stream"; import { streamToBuffer } from "./streamToBuffer"; @@ -8,7 +8,6 @@ import Jimp from "jimp"; import du from "du"; import { cacheDir } from "../conf"; - interface ImageDimensions { height: number; width: number; @@ -22,20 +21,20 @@ export async function getCachedImageBuffer(name: string, dims?: ImageDimensions) const cacheImgFolder = path.join(cacheDir, "images"); // for clearing up the cache if it reaches out of the size const cacheName = `${isUrl(name) ? name.split("/").slice(-1)[0] : name}.cnim`; - const cachePath = path.join(cacheImgFolder, cacheName); + const cacheImgPath = path.join(cacheImgFolder, cacheName); // checking if the cached image already exists or not - if (fs.existsSync(cachePath)) { + if (fs.existsSync(cacheImgPath)) { // automatically removing cache after a certain 50 MB oversize if ((await du(cacheImgFolder)) > MB_5) { - fs.rmSync(cacheImgFolder, { recursive: true, force: true }); + fs.rmdirSync(cacheImgFolder, { recursive: true }); } - const cachedImg = await fsm.readFile(cachePath); + const cachedImg = await fsm.readFile(cacheImgPath); const cachedImgMeta = (await Jimp.read(cachedImg)).bitmap; // if the dimensions are changed then the previously cached // images are removed and replaced with a new one if (dims && (cachedImgMeta.height !== dims.height || cachedImgMeta.width !== dims?.width)) { - fs.rmSync(cachePath); + fs.unlinkSync(cacheImgPath); return await imageResizeAndWrite(cachedImg, { cacheFolder: cacheImgFolder, cacheName, dims }); } return cachedImg; @@ -61,7 +60,7 @@ export async function getCachedImageBuffer(name: string, dims?: ImageDimensions) async function imageResizeAndWrite(img: Buffer, { cacheFolder, cacheName, dims }: { dims: ImageDimensions; cacheFolder: string; cacheName: string }): Promise { // caching the images by resizing if the max/fixed (Width/Height) // is available in the args - const resizedImg = (await Jimp.read(img)).resize(dims.width, dims.height) + const resizedImg = (await Jimp.read(img)).resize(dims.width, dims.height); const resizedImgBuffer = await resizedImg.getBufferAsync(resizedImg._originalMime); await fsm.writeFile(path.join(cacheFolder, cacheName), resizedImgBuffer); return resizedImgBuffer; diff --git a/src/hooks/useSpotifyApi.ts b/src/hooks/useSpotifyApi.ts index ae672268..a3dce157 100644 --- a/src/hooks/useSpotifyApi.ts +++ b/src/hooks/useSpotifyApi.ts @@ -1,6 +1,6 @@ import chalk from "chalk"; import { useContext, useEffect } from "react"; -import { LocalStorageKeys } from "../app"; +import { LocalStorageKeys } from "../conf"; import authContext from "../context/authContext"; import showError from "../helpers/showError"; import spotifyApi from "../initializations/spotifyApi";