From 9660ba3f775e843478c1d32b8222ad4414a728e6 Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 22:20:21 +0100 Subject: [PATCH 01/20] Feat(Dockerfile): Change Created User to Root --- Dockerfile | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7e9d3e4c..c38ba13a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -69,21 +69,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ && rm -rf /var/lib/apt/lists/* -RUN addgroup --system --gid 1001 nodejs -RUN adduser --system --uid 1001 --ingroup nodejs nextjs +# Change ownership of the /app directory to the root user +# RUN chown -R root:root /app -# Change ownership of the /app directory to the nextjs user -RUN chown -R nextjs:nodejs /app - -# Create and set permissions for the directories -RUN mkdir -p /ParsonLabsMusic /music && \ - chown -R nextjs:nodejs /ParsonLabsMusic /music && \ - chmod -R 755 /ParsonLabsMusic /music - -USER nextjs -COPY --from=backend-builder --chown=nextjs:nodejs /usr/src/crates/backend/target/release/music-server /usr/local/bin/music-server -COPY --from=backend-builder --chown=nextjs:nodejs /usr/src/crates/backend/music.db /usr/src/crates/backend/music.db -COPY --from=installer --chown=nextjs:nodejs /app/apps/web/out ./apps/web/out +# Copy files as root +COPY --from=backend-builder /usr/src/crates/backend/target/release/music-server /usr/local/bin/music-server +COPY --from=backend-builder /usr/src/crates/backend/music.db /usr/src/crates/backend/music.db +COPY --from=installer /app/apps/web/out ./apps/web/out ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt ENV RUNNING_IN_DOCKER=true From 365a011843e5ee2635867bc85d018745fb42abfe Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 22:21:03 +0100 Subject: [PATCH 02/20] Feat((app)/layout.tsx): Global Auth Wrapped Layout --- apps/web/app/layout.tsx | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 apps/web/app/layout.tsx diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx new file mode 100644 index 00000000..c654ae1f --- /dev/null +++ b/apps/web/app/layout.tsx @@ -0,0 +1,59 @@ +import "@music/ui/globals.css"; +import { Inter as FontSans } from "next/font/google"; +import { Metadata, Viewport } from "next"; +import SplashScreen from "@/components/Layout/SplashScreen"; +import { cn } from "@music/ui/lib/utils"; +import AuthProvider from "@/components/Providers/AuthProvider"; + +export const metadata: Metadata = { + applicationName: "ParsonLabs Music", + title: { + default: "ParsonLabs Music", + template: "%s | ParsonLabs Music", + }, + description: "Own your music.", + manifest: "/manifest.json", + appleWebApp: { + capable: true, + statusBarStyle: "default", + title: "ParsonLabs Music", + }, + formatDetection: { + telephone: false, + }, + openGraph: { + type: "website", + title: { + default: "ParsonLabs Music", + template: "%s | ParsonLabs Music", + }, + description: "Own your music.", + }, +}; + +const fontSans = FontSans({ + subsets: ["latin"], + variable: "--font-sans", +}) + +export const viewport: Viewport = { + themeColor: "#FFFFFF", +}; + +export default async function RootLayout({ children }: any) { + return ( + + + + + + {children} + + + + + ); +} \ No newline at end of file From 3587e8abb1b04cf8b269a15e21aa0e74cb210520 Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 22:22:18 +0100 Subject: [PATCH 03/20] Feat((app)/layout): Remove Wrapped Auth and Metadata --- apps/web/app/(app)/layout.tsx | 43 +++++------------------------------ 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/apps/web/app/(app)/layout.tsx b/apps/web/app/(app)/layout.tsx index 90125715..2a94adf2 100644 --- a/apps/web/app/(app)/layout.tsx +++ b/apps/web/app/(app)/layout.tsx @@ -1,36 +1,9 @@ +import SplashScreen from "@/components/Layout/SplashScreen"; import "@music/ui/globals.css"; -import { Inter as FontSans } from "next/font/google"; +import { cn } from "@music/ui/lib/utils"; import { Metadata, Viewport } from "next"; +import { Inter as FontSans } from "next/font/google"; import MainLayout from "./main-layout"; -import SplashScreen from "@/components/Layout/SplashScreen"; -import { cn } from "@music/ui/lib/utils"; -import AuthProvider from "@/components/Providers/AuthProvider"; - -export const metadata: Metadata = { - applicationName: "ParsonLabs Music", - title: { - default: "ParsonLabs Music", - template: "%s | ParsonLabs Music", - }, - description: "Own your music.", - manifest: "/manifest.json", - appleWebApp: { - capable: true, - statusBarStyle: "default", - title: "ParsonLabs Music", - }, - formatDetection: { - telephone: false, - }, - openGraph: { - type: "website", - title: { - default: "ParsonLabs Music", - template: "%s | ParsonLabs Music", - }, - description: "Own your music.", - }, -}; const fontSans = FontSans({ subsets: ["latin"], @@ -49,13 +22,9 @@ export default async function RootLayout({ children }: any) { "min-h-screen bg-background font-sans antialiased bg-gray-900 texxt-white", fontSans.variable )}> - - - - {children} - - - + + {children} + ); From a325ba894f48ddee3d1069f5ce619817ad36c928 Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 22:22:36 +0100 Subject: [PATCH 04/20] Feat((dashboard)/layout): Remove Auth Wrapping --- apps/web/app/(dashboard)/layout.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/web/app/(dashboard)/layout.tsx b/apps/web/app/(dashboard)/layout.tsx index 2691a515..0c365423 100644 --- a/apps/web/app/(dashboard)/layout.tsx +++ b/apps/web/app/(dashboard)/layout.tsx @@ -4,14 +4,11 @@ import "@music/ui/globals.css" import { Inter as FontSans } from "next/font/google" import pl from "@/assets/pl-tp.png" +import SettingsAuth from "@/components/Layout/Settings/SettingsAuth" import SettingsSidebar from "@/components/Layout/Settings/Sidebar" import { cn } from "@music/ui/lib/utils" -import Link from "next/link" import Image from "next/image" -import { usePathname, useRouter } from "next/navigation" -import { useEffect } from "react" -import AuthProvider, { useSession } from "@/components/Providers/AuthProvider" -import SettingsAuth from "@/components/Layout/Settings/SettingsAuth" +import Link from "next/link" const fontSans = FontSans({ subsets: ["latin"], @@ -39,7 +36,6 @@ export default function RootLayout({ children }: RootLayoutProps) { -
@@ -47,7 +43,6 @@ export default function RootLayout({ children }: RootLayoutProps) {
{children} -
) From 4763996122f310c9f13bee595d2221b9744acaf0 Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 22:22:58 +0100 Subject: [PATCH 05/20] Feat((unprotected)): Remove Auth Wrapping & Metadata --- apps/web/app/(unprotected)/layout.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/web/app/(unprotected)/layout.tsx b/apps/web/app/(unprotected)/layout.tsx index 682e5d6f..95e7bbde 100644 --- a/apps/web/app/(unprotected)/layout.tsx +++ b/apps/web/app/(unprotected)/layout.tsx @@ -5,17 +5,12 @@ import pl from "@/assets/pl-tp.png" import { cn } from "@music/ui/lib/utils" import { Metadata } from "next" import Image from "next/image" -import AuthProvider from "@/components/Providers/AuthProvider" const fontSans = FontSans({ subsets: ["latin"], variable: "--font-sans", }) -export const metadata: Metadata = { - title: "ParsonLabs Music" -} - type RootLayoutProps = { children: React.ReactNode } @@ -36,9 +31,7 @@ export default function RootLayout({ children }: RootLayoutProps) { - - {children} - + {children} ) From 5b5aff38e3ddcb4af1ca0839dc4dedcf6627102b Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 22:24:29 +0100 Subject: [PATCH 06/20] Feat((unprotected)): Manually Fetch Server Info with Submitted Credentials (Axios BaseURL Setting Delay) --- apps/web/app/(unprotected)/page.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/web/app/(unprotected)/page.tsx b/apps/web/app/(unprotected)/page.tsx index 3969c088..cee5c205 100644 --- a/apps/web/app/(unprotected)/page.tsx +++ b/apps/web/app/(unprotected)/page.tsx @@ -87,10 +87,16 @@ export default function MainPage() { const onSubmit: SubmitHandler = async (data) => { setLoading(true); - + try { - localStorage.setItem("server", JSON.stringify({ local_address: data.serverUrl })); - let serverInfo = await getServerInfo(); + const response = await fetch(`${data.serverUrl}/api/s/server/info`, { + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'include' + }); + + const serverInfo = await response.json() if (serverInfo.product_name && serverInfo.startup_wizard_completed) { localStorage.setItem("server", JSON.stringify(serverInfo)); @@ -101,6 +107,7 @@ export default function MainPage() { push("/login"); } } else { + localStorage.setItem("server", JSON.stringify({ local_address: data.serverUrl })); if (!serverInfo.startup_wizard_completed && session) { push("/setup/library"); } else { From 2fe3b2586e5dc3331c5b225a9782c9ae73c44dcd Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:19:02 +0100 Subject: [PATCH 07/20] Feat(AlbumComponent): Increased Visibility & Moved Album Information Below Artist --- apps/web/app/(app)/album/AlbumComponent.tsx | 48 ++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/apps/web/app/(app)/album/AlbumComponent.tsx b/apps/web/app/(app)/album/AlbumComponent.tsx index 2916be5e..a0be187f 100644 --- a/apps/web/app/(app)/album/AlbumComponent.tsx +++ b/apps/web/app/(app)/album/AlbumComponent.tsx @@ -87,7 +87,7 @@ export default function AlbumComponent() { ); return ( -
+
-
+

{album.name}

{album.release_group_album?.rating.value !== 0 && renderStars(album.release_group_album?.rating.value || 0)} - -
+
-

-

{releaseDate}

-

-

{album.songs.length} Songs

-

-

{formatDuration(totalDuration)}

-
+
+

{releaseDate}

+

+

{album.songs.length} Songs

+

+

{formatDuration(totalDuration)}

+
+

{album.release_group_album?.genres.map((tag) => ( Date: Mon, 14 Oct 2024 23:36:51 +0100 Subject: [PATCH 08/20] Feat(home): Make Responsive on Mobile --- apps/web/app/(app)/home/page.tsx | 222 ++++++++++++++++--------------- 1 file changed, 118 insertions(+), 104 deletions(-) diff --git a/apps/web/app/(app)/home/page.tsx b/apps/web/app/(app)/home/page.tsx index 37ce7a07..c6616bb8 100644 --- a/apps/web/app/(app)/home/page.tsx +++ b/apps/web/app/(app)/home/page.tsx @@ -1,104 +1,118 @@ - "use client"; - - import FromYourLibrary from "@/components/Home/FromYourLibrary"; - import LandingCarousel from "@/components/Home/LandingCarousel"; - import ListenAgain from "@/components/Home/ListenAgain"; - import MusicVideos from "@/components/Home/MusicVideos"; - import RandomSongs from "@/components/Home/RandomSongs"; - import RecommendedAlbums from "@/components/Home/RecommendedAlbums"; - import SimilarTo from "@/components/Home/SimilarTo"; - import CustomiseFeed from "@/components/Layout/CustomiseFeed"; - import GenreButtons from "@/components/Layout/GenreButtons"; - import { useGradientHover } from "@/components/Providers/GradientHoverProvider"; - import { hasConfig } from "@music/sdk"; - import { Button } from "@music/ui/components/button"; - import Link from "next/link"; - import { useEffect, useState } from "react"; - import { useLayoutConfig } from "@/components/Providers/LayoutConfigContext"; - - export default function Home() { - const [configExists, setConfigExists] = useState(true); - const { components, setComponents } = useLayoutConfig(); - - const { setGradient } = useGradientHover(); - - useEffect(() => { - async function checkConfig() { - const config = await hasConfig(); - if (config) { - setConfigExists(true); - } else { - setConfigExists(false); - setGradient("#FFFFFF"); - } - } - - checkConfig(); - }, [setGradient]); - - useEffect(() => { - const savedConfig = localStorage.getItem("layoutConfig"); - if (savedConfig) { - setComponents(JSON.parse(savedConfig)); - } - }, [setComponents]); - - type ComponentConfig = { - id: string; - name: string; - visible: boolean; - pinned: boolean; - }; - - const renderComponent = (component: ComponentConfig): JSX.Element | null => { - if (!component.visible) return null; - switch (component.id) { - case "LandingCarousel": - return ; - case "ListenAgain": - return ; - case "SimilarTo": - return ; - case "RecommendedAlbums": - return ; - case "RandomSongs": - return ; - case "FromYourLibrary": - return ; - case "MusicVideos": - return ; - default: - return null; - } - }; - - return configExists ? ( -

-
- -
- - {components - .filter((component) => component.pinned) - .map(renderComponent)} - {components - .filter((component) => !component.pinned) - .map(renderComponent)} - -
- ) : ( -
-

No Config Found!

-

- - Head to the setup page to index your library - -

- - - -
- ); - } \ No newline at end of file +"use client"; + +import FromYourLibrary from "@/components/Home/FromYourLibrary"; +import LandingCarousel from "@/components/Home/LandingCarousel"; +import ListenAgain from "@/components/Home/ListenAgain"; +import MusicVideos from "@/components/Home/MusicVideos"; +import RandomSongs from "@/components/Home/RandomSongs"; +import RecommendedAlbums from "@/components/Home/RecommendedAlbums"; +import SimilarTo from "@/components/Home/SimilarTo"; +import CustomiseFeed from "@/components/Layout/CustomiseFeed"; +import GenreButtons from "@/components/Layout/GenreButtons"; +import { useGradientHover } from "@/components/Providers/GradientHoverProvider"; +import { hasConfig } from "@music/sdk"; +import { Button } from "@music/ui/components/button"; +import Link from "next/link"; +import { useEffect, useState } from "react"; +import { useLayoutConfig } from "@/components/Providers/LayoutConfigContext"; + +export default function Home() { + const [configExists, setConfigExists] = useState(true); + const { components, setComponents } = useLayoutConfig(); + const { setGradient } = useGradientHover(); + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + async function checkConfig() { + const config = await hasConfig(); + if (config) { + setConfigExists(true); + } else { + setConfigExists(false); + setGradient("#FFFFFF"); + } + } + + checkConfig(); + }, [setGradient]); + + useEffect(() => { + const savedConfig = localStorage.getItem("layoutConfig"); + if (savedConfig) { + setComponents(JSON.parse(savedConfig)); + } + }, [setComponents]); + + useEffect(() => { + const handleResize = () => { + setIsMobile(window.innerWidth < 768); + }; + + window.addEventListener('resize', handleResize); + + handleResize(); + + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + + type ComponentConfig = { + id: string; + name: string; + visible: boolean; + pinned: boolean; + }; + + const renderComponent = (component: ComponentConfig): JSX.Element | null => { + if (!component.visible) return null; + switch (component.id) { + case "LandingCarousel": + return ; + case "ListenAgain": + return ; + case "SimilarTo": + return ; + case "RecommendedAlbums": + return ; + case "RandomSongs": + return ; + case "FromYourLibrary": + return ; + case "MusicVideos": + return ; + default: + return null; + } + }; + + return configExists ? ( +
+
+ {!isMobile && } +
+ + {components + .filter((component) => component.pinned) + .map(renderComponent)} + {components + .filter((component) => !component.pinned) + .map(renderComponent)} + +
+ ) : ( +
+

No Config Found!

+

+ + Head to the setup page to index your library + +

+ + + +
+ ); +} \ No newline at end of file From 61a6b96b73b08076728110da51b33cc999ad5773 Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:37:26 +0100 Subject: [PATCH 09/20] Feat(login): Redirect When Logging In --- apps/web/app/(unprotected)/login/page.tsx | 30 ++++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/apps/web/app/(unprotected)/login/page.tsx b/apps/web/app/(unprotected)/login/page.tsx index 3eddb166..8d67fce1 100644 --- a/apps/web/app/(unprotected)/login/page.tsx +++ b/apps/web/app/(unprotected)/login/page.tsx @@ -1,5 +1,6 @@ "use client"; +import { useSession } from "@/components/Providers/AuthProvider"; import getBaseURL from "@/lib/Server/getBaseURL"; import { zodResolver } from '@hookform/resolvers/zod'; import { getServerInfo } from "@music/sdk"; @@ -13,7 +14,6 @@ import { FormMessage, } from "@music/ui/components/form"; import { Input } from '@music/ui/components/input'; -import { setCookie } from 'cookies-next'; import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; import { SubmitHandler, useForm } from 'react-hook-form'; @@ -27,13 +27,21 @@ const schema = z.object({ type FormData = z.infer; export default function Login() { - const router = useRouter(); + const { push } = useRouter(); const [errorMessage, setErrorMessage] = useState(null); const [serverInfo, setServerInfo] = useState<{ login_disclaimer?: string } | null>(null); const form = useForm({ resolver: zodResolver(schema), }); + const { session } = useSession() + + useEffect(() => { + if (session && session?.username) { + push("/home") + } + }, [session?.username, session, push]) + useEffect(() => { async function fetchServerInfo() { try { @@ -44,8 +52,12 @@ export default function Login() { } }; + if (session && session?.username) { + push("/home") + } + fetchServerInfo(); - }, []); + }, [session, push]); const { handleSubmit } = form; @@ -59,15 +71,15 @@ export default function Login() { body: JSON.stringify(data), credentials: 'include' }); - - if (response.ok) { - router.push("/"); + + const result = await response.json(); + + if (response.ok && result.status) { + push("/home"); } else { - const errorMessage = await response.text(); - setErrorMessage(errorMessage || 'Authentication failed'); + setErrorMessage(result.message || 'Authentication failed'); } } catch (error) { - console.error('Login error:', error); setErrorMessage('An error occurred during login'); } }; From b2b428d8a286914cf4562eaf8bb88b5584cecc92 Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:40:18 +0100 Subject: [PATCH 10/20] Feat(LandingCarousel): Hide when on Mobile --- apps/web/components/Home/LandingCarousel.tsx | 22 +++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/apps/web/components/Home/LandingCarousel.tsx b/apps/web/components/Home/LandingCarousel.tsx index aef8d095..fa0df354 100644 --- a/apps/web/components/Home/LandingCarousel.tsx +++ b/apps/web/components/Home/LandingCarousel.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import getBaseURL from "@/lib/Server/getBaseURL"; import setCache, { getCache } from "@/lib/Caching/cache"; @@ -9,7 +9,7 @@ import { Skeleton } from "@music/ui/components/skeleton"; import { Play } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; -import { useEffect, useState, useRef } from "react"; +import { useEffect, useState } from "react"; import { FastAverageColor } from 'fast-average-color'; async function getRandomAlbumAndSongs(): Promise<{ album: Album & { artist_object: Artist }, songs: LibrarySong[] }> { @@ -62,7 +62,7 @@ export function LandingCarouselSkeleton() { />
- ) + ); } export default function LandingCarousel() { @@ -73,7 +73,7 @@ export default function LandingCarousel() { useEffect(() => { async function fetchAlbumAndSongs() { const cachedData = getCache("landingCarousel"); - + if (cachedData) { setAlbum(cachedData.album); setSongs(cachedData.songs); @@ -84,27 +84,29 @@ export default function LandingCarousel() { setCache("landingCarousel", { album, songs }, 86400000); } } - + fetchAlbumAndSongs(); }, []); useEffect(() => { async function getButtonColour() { - const albumCoverURL = `${getBaseURL()}/image/${encodeURIComponent(album?.cover_url || "")}?raw=true` + const albumCoverURL = `${getBaseURL()}/image/${encodeURIComponent(album?.cover_url || "")}?raw=true`; const fac = new FastAverageColor(); - const color = await fac.getColorAsync(albumCoverURL) + const color = await fac.getColorAsync(albumCoverURL); setButtonColor(color.hex); } - getButtonColour() - }) + if (album) { + getButtonColour(); + } + }, [album]); if (!album) return null; const albumCoverURL = `${getBaseURL()}/image/${encodeURIComponent(album.cover_url)}?raw=true`; return ( -
+
{`${album.name} Date: Mon, 14 Oct 2024 23:40:39 +0100 Subject: [PATCH 11/20] Feat(SimilarTo): Remove Logging --- apps/web/components/Home/SimilarTo.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/web/components/Home/SimilarTo.tsx b/apps/web/components/Home/SimilarTo.tsx index 0a1d4bd7..35cd8a6c 100644 --- a/apps/web/components/Home/SimilarTo.tsx +++ b/apps/web/components/Home/SimilarTo.tsx @@ -27,8 +27,6 @@ export default function SimilarTo() { throw new Error("Invalid session"); } const similarTo = await getSimilarTo(Number(session.sub)); - console.log("Fetched similar albums:", similarTo[0]); - console.log("Fetched genre:", similarTo[1]); setGenre(similarTo[1]); setSimilarAlbums(similarTo[0]); } catch (err: any) { From ff7cf8ba687e2fbe1b304d381c323ea85a8d6bdf Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:41:11 +0100 Subject: [PATCH 12/20] Feat(Sidebar): Disable on Mobile --- apps/web/components/Layout/Sidebar.tsx | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/apps/web/components/Layout/Sidebar.tsx b/apps/web/components/Layout/Sidebar.tsx index 83e320a1..ac6e146d 100644 --- a/apps/web/components/Layout/Sidebar.tsx +++ b/apps/web/components/Layout/Sidebar.tsx @@ -16,7 +16,7 @@ type SidebarProps = { export default function Sidebar({ children, sidebarContent }: SidebarProps) { - const { isOpen } = useSidebar(); + const { isOpen, closeSidebar, openSidebar } = useSidebar(); const { onTopOfPage } = useContext(ScrollContext); const { areLyricsVisible } = useContext(LyricsContext); const pathname = usePathname(); @@ -26,6 +26,24 @@ export default function Sidebar({ children, sidebarContent }: SidebarProps) { setCurrentPath(pathname); }, [pathname]); + useEffect(() => { + const handleResize = () => { + if (window.innerWidth < 768) { + closeSidebar(); + } else { + openSidebar(); + } + }; + + window.addEventListener('resize', handleResize); + + handleResize(); + + return () => { + window.removeEventListener('resize', handleResize); + }; + }, [closeSidebar, openSidebar]); + if (currentPath === null) { return null; } From 0998f1e6f8eac3831ab07b654a82a0c5713664c6 Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:49:55 +0100 Subject: [PATCH 13/20] Feat(Dockerfile): Add FFMPEG for Slowed / Reverb --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c38ba13a..7d7499fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,7 +31,7 @@ FROM rust:1.81 AS backend-builder WORKDIR /usr/src RUN apt-get update && apt-get install -y --no-install-recommends \ - sqlite3 libsqlite3-dev wget make build-essential pkg-config libssl-dev \ + sqlite3 libsqlite3-dev wget make build-essential pkg-config libssl-dev ffmpeg \ && rm -rf /var/lib/apt/lists/* RUN wget https://www.nasm.us/pub/nasm/releasebuilds/2.16/nasm-2.16.tar.gz \ @@ -67,6 +67,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libsqlite3-dev \ wget \ ca-certificates \ + ffmpeg \ && rm -rf /var/lib/apt/lists/* # Change ownership of the /app directory to the root user From 0de4ee90ec3c24f9a81e95f8f75d5f60ca8b5c2f Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:50:57 +0100 Subject: [PATCH 14/20] Feat(SplashScreen): Remove Loading Local Storage --- apps/web/components/Layout/SplashScreen.tsx | 40 ++------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/apps/web/components/Layout/SplashScreen.tsx b/apps/web/components/Layout/SplashScreen.tsx index 9af9f9ed..adec660f 100644 --- a/apps/web/components/Layout/SplashScreen.tsx +++ b/apps/web/components/Layout/SplashScreen.tsx @@ -1,7 +1,6 @@ "use client" import pl from '@/assets/pl-tp.png'; -import getSession from '@/lib/Authentication/JWT/getSession'; import { Loader2Icon } from 'lucide-react'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; @@ -12,29 +11,6 @@ interface SplashScreenProps { children: React.ReactNode; } -const setItemWithExpiry = (key: string, value: string, ttl: number) => { - const now = new Date(); - const item = { - value: value, - expiry: now.getTime() + ttl, - }; - localStorage.setItem(key, JSON.stringify(item)); -}; - -const getItemWithExpiry = (key: string) => { - const itemStr = localStorage.getItem(key); - if (!itemStr) { - return null; - } - const item = JSON.parse(itemStr); - const now = new Date(); - if (now.getTime() > item.expiry) { - localStorage.removeItem(key); - return null; - } - return item.value; -}; - const SplashScreen: React.FC = ({ children }) => { const [loading, setLoading] = useState(true); const { push } = useRouter(); @@ -48,41 +24,29 @@ const SplashScreen: React.FC = ({ children }) => { ); if (response.ok) { - if (session) { + if (session?.username) { const currentPath = window.location.pathname; const queryParams = window.location.search; - if (currentPath === "/") { + if (currentPath === "/" || currentPath === "/login" || currentPath === "/login/") { push("/home"); } else { push(`${currentPath}${queryParams}`); } setLoading(false); - setItemWithExpiry("loading", "false", 3600000); } else { push("/login"); setLoading(false); - setItemWithExpiry("loading", "false", 3600000); } } else { push("/") setLoading(false); - setItemWithExpiry("loading", "false", 3600000); } }; checkServerUrl(); }, [push, session]); - useEffect(() => { - const storedLoading = getItemWithExpiry("loading"); - if (storedLoading === "false") { - setLoading(false); - return; - } - - }, [push]); - if (loading) { return (
From da49c9d04a2e1862043f1ff45e498e383777e16d Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:51:20 +0100 Subject: [PATCH 15/20] Feat(AdminPanelLayout): Remove AuthProvider --- .../Layout/Sidebar/AdminPanellayout.tsx | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/apps/web/components/Layout/Sidebar/AdminPanellayout.tsx b/apps/web/components/Layout/Sidebar/AdminPanellayout.tsx index 7e28cab2..df4bb64d 100644 --- a/apps/web/components/Layout/Sidebar/AdminPanellayout.tsx +++ b/apps/web/components/Layout/Sidebar/AdminPanellayout.tsx @@ -1,6 +1,5 @@ "use client"; -import AuthProvider from "@/components/Providers/AuthProvider"; import { cn } from "@music/ui/lib/utils"; import Sidebar from "./Sidebar"; @@ -19,16 +18,14 @@ export default function AdminPanelLayout({ return ( <> - -
- {children} -
-
+
+ {children} +
); } From 0c55051809b397362512eaf78e1f4ff22b8b56dd Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:52:50 +0100 Subject: [PATCH 16/20] Feat(AlbumTable): Increase Visibility of Text & Remove Gap Between Track Number and Song Name --- apps/web/components/Music/Album/AlbumTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/components/Music/Album/AlbumTable.tsx b/apps/web/components/Music/Album/AlbumTable.tsx index 1494f653..1bdb27ae 100644 --- a/apps/web/components/Music/Album/AlbumTable.tsx +++ b/apps/web/components/Music/Album/AlbumTable.tsx @@ -133,9 +133,9 @@ export default function AlbumTable({ songs, album, artist }: PlaylistTableProps) handlePlay(album.cover_url, song, `${getBaseURL()}/api/stream/${encodeURIComponent(song.path)}?bitrate=${bitrate}`, artist)}> {song.track_number} -
+
-
+
{artist.name} From 3985cbd2a3b44dfa4451f1674e3f62088e4fdd7a Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:53:31 +0100 Subject: [PATCH 17/20] Feat(ServerSelectIcon): Refresh instead of Pushing --- apps/web/components/Setup/Server/ServerSelectIcon.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/components/Setup/Server/ServerSelectIcon.tsx b/apps/web/components/Setup/Server/ServerSelectIcon.tsx index 7ed0a1df..51cb217e 100644 --- a/apps/web/components/Setup/Server/ServerSelectIcon.tsx +++ b/apps/web/components/Setup/Server/ServerSelectIcon.tsx @@ -44,7 +44,7 @@ export default function ServerSelectIcon() { const handleDelete = () => { localStorage.removeItem("server"); deleteCookie("server"); - router.push("/"); + router.refresh() }; return ( From 67c9e5855ce58824aec92eba6e8d6f92eaef098d Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:53:53 +0100 Subject: [PATCH 18/20] Feat(NavbarProfilePicture): Delete plm Tokens instead of music_jwt --- apps/web/components/User/NavbarProfilePicture.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/web/components/User/NavbarProfilePicture.tsx b/apps/web/components/User/NavbarProfilePicture.tsx index 106c800b..2ea29a8b 100644 --- a/apps/web/components/User/NavbarProfilePicture.tsx +++ b/apps/web/components/User/NavbarProfilePicture.tsx @@ -18,21 +18,18 @@ import { } from "@music/ui/components/dropdown-menu" import { - Dialog, - DialogTrigger, + Dialog } from "@music/ui/components/dialog" import { Avatar, AvatarFallback, AvatarImage } from "@music/ui/components/avatar" import Link from "next/link" import SettingsDialog from "./SettingsDialog" -import getSession from "@/lib/Authentication/JWT/getSession" import { getProfilePicture } from "@music/sdk" import { deleteCookie } from "cookies-next" import { Inter as FontSans } from "next/font/google" import { useRouter } from "next/navigation" import { useEffect, useState } from "react" -import { cn } from "@music/ui/lib/utils" import { useSession } from "../Providers/AuthProvider" const fontSans = FontSans({ @@ -62,7 +59,9 @@ export default function NavbarProfilePicture() { const { push } = useRouter() function signOut() { - deleteCookie("music_jwt") + deleteCookie("plm_accessToken") + deleteCookie("plm_refreshToken") + push("/login") } From fa8f6a5ae8501dc140bd42e19fa157e31e01629d Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:55:28 +0100 Subject: [PATCH 19/20] Feat(Username): Remove Logging of Username when Submitting --- apps/web/components/User/Username.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/web/components/User/Username.tsx b/apps/web/components/User/Username.tsx index 9cc8163c..6037526d 100644 --- a/apps/web/components/User/Username.tsx +++ b/apps/web/components/User/Username.tsx @@ -6,7 +6,6 @@ import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { z } from "zod" -import getSession from "@/lib/Authentication/JWT/getSession" import { Button } from "@music/ui/components/button" import { Form, @@ -40,7 +39,7 @@ export default function Username() { }) function onSubmit(data: z.infer) { - console.log(data.username) + // console.log(data.username) } return ( From 0d131bae58ac0aaf06b84d377b0c3df815b4747f Mon Sep 17 00:00:00 2001 From: WillKirkmanM Date: Mon, 14 Oct 2024 23:56:47 +0100 Subject: [PATCH 20/20] Feat(authentication.rs): Add Secure and No SameSite to Authentication Cookies --- crates/backend/src/routes/authentication.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/backend/src/routes/authentication.rs b/crates/backend/src/routes/authentication.rs index 06b8914c..b054f4b7 100644 --- a/crates/backend/src/routes/authentication.rs +++ b/crates/backend/src/routes/authentication.rs @@ -116,7 +116,8 @@ pub async fn login(form: web::Json) -> impl Responder { if let Err(_) = response.add_cookie( &Cookie::build("plm_refreshToken", generated_refresh_token) .http_only(true) - .same_site(SameSite::Lax) + .same_site(SameSite::None) + .secure(true) .path("/") .finish(), ) { @@ -127,10 +128,11 @@ pub async fn login(form: web::Json) -> impl Responder { message: Some(String::from("Failed to set refresh token cookie")), }); } - + if let Err(_) = response.add_cookie( &Cookie::build("plm_accessToken", generated_access_token) - .same_site(SameSite::Lax) + .same_site(SameSite::None) + .secure(true) .path("/") .finish(), ) {