From c85808386a6bc7afb45b3e2c08654b0268c6c6ca Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Tue, 3 Jan 2023 20:16:56 +0000 Subject: [PATCH 01/34] Add search button to channel pages --- src/pages/Channel.tsx | 50 ++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/src/pages/Channel.tsx b/src/pages/Channel.tsx index 6db5cdc3..5928acb4 100644 --- a/src/pages/Channel.tsx +++ b/src/pages/Channel.tsx @@ -10,7 +10,7 @@ import { useColorModeValue, } from "@chakra-ui/react"; import axios from "axios"; -import { FiList, FiShare2, FiTwitter, FiYoutube } from "react-icons/fi"; +import { FiList, FiShare2, FiTwitter, FiYoutube, FiSearch } from "react-icons/fi"; import { useQuery } from "react-query"; import { Link, Route, Routes, useParams } from "react-router-dom"; import { ChannelCard } from "../components/channel/ChannelCard"; @@ -204,6 +204,35 @@ function ChannelSocialButtons({ ); } +interface PlaylistButton { + label: string, + link: string, + icon: any, +} + +function getPlaylistButtons({ + channel, + buttons, +}: { + channel: any, + buttons: PlaylistButton[], +}) { + return (buttons.map( button => + + )); +} + function ChannelContent({ discovery, trending, @@ -218,6 +247,10 @@ function ChannelContent({ channel: any; }) { const { t } = useTranslation(); + const ButtonData = [ + {label: "See All Songs", link: "/channel/" + channel.id + "/songs", icon: FiList}, + {label: "Search Songs", link: `/searchV2?mode=fuzzy&ch=["${channel.name}"]`, icon: FiSearch} + ]; return ( <> {trending && ( @@ -246,20 +279,7 @@ function ChannelContent({ showArtwork: true, }} limit={5} - appendRight={ - - } + appendRight={getPlaylistButtons({ channel: channel, buttons: ButtonData})} /> From 69c04aa76b9c63ab0be547d1d62040ddcae2dfd4 Mon Sep 17 00:00:00 2001 From: David Chen <3145205+RiceCakess@users.noreply.github.com> Date: Wed, 4 Jan 2023 23:02:04 -0800 Subject: [PATCH 02/34] Fix queue menu not showing --- src/components/data/SongTable/UpcomingSongList.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/data/SongTable/UpcomingSongList.tsx b/src/components/data/SongTable/UpcomingSongList.tsx index 5632a0e6..70ed24ae 100644 --- a/src/components/data/SongTable/UpcomingSongList.tsx +++ b/src/components/data/SongTable/UpcomingSongList.tsx @@ -9,7 +9,11 @@ import { } from "@chakra-ui/react"; import React, { useCallback, useContext, useEffect, useMemo } from "react"; import { VariableSizeList } from "react-window"; -import { DEFAULT_MENU_ID, QUEUE_MENU_ID } from "../../song/SongContextMenu"; +import { + DEFAULT_MENU_ID, + QUEUE_MENU_ID, + SongContextMenu, +} from "../../song/SongContextMenu"; import { RowProps, SongRow } from "./SongRow"; import { useTranslation } from "react-i18next"; import { SongTableCol, SongTableProps } from "."; @@ -244,6 +248,7 @@ export const UpcomingSongList = ({ {renderList} )} + ); }; From 2c5512f220f84b95109f10c330f96181b5e2a250 Mon Sep 17 00:00:00 2001 From: sphinxrave <62570796+sphinxrave@users.noreply.github.com> Date: Wed, 11 Jan 2023 11:28:31 -0800 Subject: [PATCH 03/34] New translations translation.json (Turkish) --- public/locales/tr-TR/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/tr-TR/translation.json b/public/locales/tr-TR/translation.json index c071aabf..a276a1bc 100644 --- a/public/locales/tr-TR/translation.json +++ b/public/locales/tr-TR/translation.json @@ -104,7 +104,7 @@ "Organization Ordering": "Organizasyon Sıralaması", "Drag and Drop to reorder list of orgs in the org dropdown": "Org menüsündeki orgların sırasını değiştirmek için Sürükleyip Bırakın", "Interface Language": "Arayüz Dili", - "Channel Name": "Kanal Adı", + "Channel Name": "Kanal İsimleri", "ErrorPart2LetUsKnow": "Yukarıdaki adımlar probleminizi çözmüyorsa lütfen Discord veya Twitter üzerinden bize bir ekran görüntüsü gönderip hata ile nasıl karşılaştığınızı anlatın.", "Please log in to use this feature.": "Bu özelliği kullanabilmek için lütfen oturum açın.", "Sign in to Musicdex": "Musicdex'e giriş yap", From a24ffc2d16a0c1a9f1cda5adc2386f1b66e5b0da Mon Sep 17 00:00:00 2001 From: David Chen <3145205+RiceCakess@users.noreply.github.com> Date: Wed, 11 Jan 2023 19:07:15 -0800 Subject: [PATCH 04/34] Update service worker --- src/service-worker.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/service-worker.ts b/src/service-worker.ts index 98760f2a..9716fdfe 100644 --- a/src/service-worker.ts +++ b/src/service-worker.ts @@ -64,15 +64,17 @@ registerRoute( // Return true to signal that we want to use the handler. return true; }, - createHandlerBoundToURL(process.env.PUBLIC_URL + "/index.html") + createHandlerBoundToURL(process.env.PUBLIC_URL + "/index.html"), ); // An example runtime caching route for requests that aren't handled by the // precache, in this case same-origin .png requests like those from in public/ +// Caches music.holodex.net images registerRoute( // Add in any other file extensions or routing criteria as needed. ({ url }) => - url.origin === self.location.origin && + (url.origin === self.location.origin || + url.origin === self.location.origin.replace(/^[^.]+\./g, "")) && (url.pathname.endsWith(".png") || url.pathname.endsWith(".jpg") || url.pathname.endsWith(".jpeg")), @@ -83,31 +85,30 @@ registerRoute( // Ensure that once this runtime cache reaches a maximum size the // least-recently used images are removed. new ExpirationPlugin({ - maxEntries: 400, + maxEntries: 100, maxAgeSeconds: 12 * 60 * 60, // 12 hours of cache? }), ], - }) + }), ); +// Cache holodex.net images registerRoute( // Add in any other file extensions or routing criteria as needed. ({ url }) => - (url.host === "i.ytimg.com" || url.host.endsWith("mzstatic.com")) && - (url.pathname.endsWith(".png") || - url.pathname.endsWith(".jpg") || - url.pathname.endsWith(".jpeg")), + url.pathname.match(new RegExp(`${self.location.origin}/statics/.*.json$`)), // Customize this strategy as needed, e.g., by changing to CacheFirst. new StaleWhileRevalidate({ - cacheName: "ytimgs", + cacheName: "holodex static json", plugins: [ // Ensure that once this runtime cache reaches a maximum size the // least-recently used images are removed. new ExpirationPlugin({ - maxEntries: 160, + maxEntries: 50, + maxAgeSeconds: 24 * 60 * 60, // 12 hours of cache? }), ], - }) + }), ); // This allows the web app to trigger skipWaiting via From 30ca63e49630ac753dd4c02b918afdd39e11f912 Mon Sep 17 00:00:00 2001 From: P-man2976 Date: Tue, 7 Feb 2023 22:15:47 +0900 Subject: [PATCH 05/34] Global styles move into chakra theme settings --- public/index.html | 16 ---------------- src/components/layout/Frame.tsx | 6 ++---- src/theme.ts | 21 ++++++++++++++++++--- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/public/index.html b/public/index.html index d7a90111..a1759026 100644 --- a/public/index.html +++ b/public/index.html @@ -68,23 +68,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - -
diff --git a/src/components/layout/Frame.tsx b/src/components/layout/Frame.tsx index 6cb5eb03..d7df376f 100644 --- a/src/components/layout/Frame.tsx +++ b/src/components/layout/Frame.tsx @@ -166,10 +166,8 @@ export default function Frame({ children }: { children?: ReactNode }) { return ( Date: Mon, 13 Feb 2023 01:26:01 +0900 Subject: [PATCH 06/34] Refactor player --- src/components/layout/Frame.tsx | 228 +++++---- src/components/player/FullPlayer.tsx | 194 ++++++++ src/components/player/Player.tsx | 343 ++------------ src/components/player/PlayerBar.tsx | 433 ++++-------------- .../player/PlayerKeyboardControls.tsx | 145 +++++- src/components/player/YoutubePlayer.tsx | 45 +- .../player/controls/PlaybackControl.tsx | 32 +- .../player/controls/PlayerOption.tsx | 10 +- .../player/controls/PlayerSongInfo.tsx | 8 +- src/components/player/controls/TimeInfo.tsx | 17 + src/components/player/controls/TimeSlider.tsx | 53 ++- .../player/controls/VolumeSlider.tsx | 81 ++-- src/theme.ts | 6 +- 13 files changed, 749 insertions(+), 846 deletions(-) create mode 100644 src/components/player/FullPlayer.tsx create mode 100644 src/components/player/controls/TimeInfo.tsx diff --git a/src/components/layout/Frame.tsx b/src/components/layout/Frame.tsx index d7df376f..8f43aae9 100644 --- a/src/components/layout/Frame.tsx +++ b/src/components/layout/Frame.tsx @@ -4,7 +4,7 @@ import { Drawer, DrawerContent, Flex, - useBreakpointValue, + Show, useColorModeValue, useDisclosure, } from "@chakra-ui/react"; @@ -15,9 +15,12 @@ import { useMemo, useRef, useState, + Dispatch, + SetStateAction, } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import { useLocation, useNavigate } from "react-router-dom"; +import { useMotionValue, useTransform } from "framer-motion"; import { YouTubePlayer } from "youtube-player/dist/types"; import { useStoreState, useStoreActions } from "../../store"; import { SongContextMenu } from "../song/SongContextMenu"; @@ -32,6 +35,7 @@ import { YoutubePlayer } from "../player/YoutubePlayer"; import { AddToPlaylistModal } from "../playlist/AddToPlaylistModal"; import { useClient } from "../../modules/client"; import Footer from "./Footer"; +import FullPlayer from "../player/FullPlayer"; const POSITIONS: { [key: string]: ChakraProps } = { background: { @@ -43,37 +47,49 @@ const POSITIONS: { [key: string]: ChakraProps } = { sidebar: { position: "absolute", zIndex: 1, - bottom: "0px", + bottom: 0, ml: -60, w: 60, + sx: { + aspectRatio: "16 / 9", + }, }, "hover-top": { width: "400px", maxWidth: "100%", - height: "225px", position: "absolute", top: "20px", right: "20px", paddingLeft: "30px", zIndex: 10, + sx: { + aspectRatio: "16 / 9", + }, }, "hover-bottom": { width: "400px", maxWidth: "100%", - height: "225px", position: "absolute", - bottom: "20px", + bottom: { base: "4.5rem", md: "20px" }, right: "20px", paddingLeft: "30px", zIndex: 10, + sx: { + aspectRatio: "16 / 9", + }, }, "full-player": { position: "fixed", - top: "calc(40vh/2 - min(40vh, calc(100vw * .5625))/2 + 56px + env(safe-area-inset-top))", - left: { base: "0", lg: "6" }, - width: { base: "100vw", lg: "calc(50vw - 2.75rem)" }, - h: "min(40vh, calc(100vw * .5625))", + top: { base: "10vh", md: 12 }, + right: { base: undefined, md: "calc(50vw + 1rem)" }, + w: { + base: "100vw", + md: "min(calc(50vw - 2.5rem), calc(var(--chakra-sizes-container-xl) / 2 - 2.5rem))", + }, zIndex: 15, + sx: { + aspectRatio: "16 / 9", + }, }, hidden: { display: "none", @@ -84,16 +100,21 @@ const POSITIONS: { [key: string]: ChakraProps } = { export const FrameRef = createContext(null); +// YouTubePlayer context +export const PlayerContext = createContext< + [YouTubePlayer | null, Dispatch>] +>([null, () => {}]); + export default function Frame({ children }: { children?: ReactNode }) { const { isOpen, onOpen, onClose } = useDisclosure(); const client = useClient(); + // Full player drag value + const y = useMotionValue(0); + const playerY = useTransform(y, [-500, 0, 500], [-500, 0, 500]); + const opacity = useTransform(y, [0, 500], [1, 0.5]); + const colorMode = useColorModeValue("applight", "appdark"); - const showBottomNav = useBreakpointValue({ - base: true, - md: false, - default: false, - }); const pos = useStoreState((state) => state.player.position); const props = useMemo(() => POSITIONS[pos], [pos]); @@ -109,8 +130,6 @@ export default function Frame({ children }: { children?: ReactNode }) { }, [pathname]); // END navigation scrolling behavior. - const [player, setPlayer] = useState(null); - const currentlyPlaying = useStoreState( (state) => state.playback.currentlyPlaying, ); @@ -125,10 +144,6 @@ export default function Frame({ children }: { children?: ReactNode }) { if (!loadPlayer && currentlyPlaying.song) setLoadPlayer(true); }, [currentlyPlaying.song, currentlyPlaying.repeat, loadPlayer]); - function onReady(event: { target: YouTubePlayer }) { - setPlayer(event.target); - } - const location = useLocation(); useEffect(() => { if (isOpen) { @@ -172,92 +187,105 @@ export default function Frame({ children }: { children?: ReactNode }) { bg={useColorModeValue("bg.100", "bg.900")} overflow="hidden" > - - {/* Generic Display: always present */} - - - {/* Mobile Display: (provide close method) */} - - - - - - - (null)}> + + {/* Generic Display: always present */} + - + + {/* Mobile Display: (provide close method) */} + + + + + - - - {children} -
- {/* */} -
-
- {loadPlayer && ( - - - - - )} + + + + + + {children} +