import { useCallback } from "react"; import { useRouter } from 'next/navigation'; import Image from "next/image"; import { Github, Mail } from "lucide-react" import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarLabel, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, } from "@/components/ui/menubar" import { useState, useEffect } from "react" import { Button } from "@/components/ui/button" import { Separator } from '@/components/ui/separator'; import { useNavidrome } from "./NavidromeContext"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" interface MenuProps { toggleSidebar: () => void; isSidebarVisible: boolean; toggleStatusBar: () => void; isStatusBarVisible: boolean; } export function Menu({ toggleSidebar, isSidebarVisible, toggleStatusBar, isStatusBarVisible }: MenuProps) { const [isFullScreen, setIsFullScreen] = useState(false) const router = useRouter(); const [open, setOpen] = useState(false); const { isConnected } = useNavidrome(); const [isClient, setIsClient] = useState(false); const [navidromeUrl, setNavidromeUrl] = useState(null); // For this demo, we'll show connection status instead of user auth const connectionStatus = isConnected ? "Connected to Navidrome" : "Not connected"; const handleFullScreen = useCallback(() => { if (!isFullScreen) { document.documentElement.requestFullscreen() } else { document.exitFullscreen() } setIsFullScreen(!isFullScreen) }, [isFullScreen]) useEffect(() => { setIsClient(true); // Get Navidrome URL from localStorage const config = localStorage.getItem("navidrome-config"); if (config) { try { const { serverUrl } = JSON.parse(config); if (serverUrl) { // Remove protocol (http:// or https://) and trailing slash const prettyUrl = serverUrl.replace(/^https?:\/\//, "").replace(/\/$/, ""); setNavidromeUrl(prettyUrl); } else { setNavidromeUrl(null); } } catch { setNavidromeUrl(null); } } else { setNavidromeUrl(null); } }, []); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if ((event.metaKey || event.ctrlKey) && event.key === ',') { event.preventDefault(); router.push('/settings'); } if ((event.metaKey || event.ctrlKey) && event.key === 's') { event.preventDefault(); toggleSidebar(); } if ((event.metaKey || event.ctrlKey) && event.key === 'f') { event.preventDefault(); handleFullScreen(); } }; if (isClient) { window.addEventListener('keydown', handleKeyDown); } return () => { if (isClient) { window.removeEventListener('keydown', handleKeyDown); } }; }, [router, toggleSidebar, handleFullScreen, isClient]); return ( <>
mice setOpen(true)}>About Music router.push('/settings')}> Preferences ⌘, isClient && window.close()}> Quit Music ⌘Q

j

File New Playlist ⌘N Playlist from Selection ⇧⌘N Smart Playlist ⌥⌘N Playlist Folder Genius Playlist Open Stream URL ⌘U Close Window ⌘W Library Update Cloud Library Update Genius Organize Library Export Library Import Playlist Export Playlist Show Duplicate Items Get Album Artwork Get Track Names Import ⌘O Burn Playlist to Disc Show in Finder ⇧⌘R{" "} Convert Page Setup Print ⌘P Edit Undo ⌘Z Redo ⇧⌘Z Cut ⌘X Copy ⌘C Paste ⌘V Select All ⌘A Deselect All ⇧⌘A Smart Dictation{" "} Emoji & Symbols{" "} View Show Playing Next Show Lyrics {isStatusBarVisible ? "Hide Status Bar" : "Show Status Bar"} {isSidebarVisible ? "Hide Sidebar" : "Show Sidebar"} ⌘S {isFullScreen ? "Exit Full Screen" : "Enter Full Screen"}
music

mice

{/* Version 1.0.0 */}

A Navidrome client built with Next.js and Shadcn/UI.

Server Status

{isConnected ? "Connected" : "Not connected"}

Navidrome URL {!isClient ? ( Loading... ) : navidromeUrl ? ( navidromeUrl ) : ( Not set )}
Commit: {process.env.NEXT_PUBLIC_COMMIT_SHA || 'unknown'} Copyright © {new Date().getFullYear()} sillyangel
) }