import React, { useEffect, useState } from 'react'; import { usePlayerStore } from '../store/playerStore'; import { open } from '@tauri-apps/plugin-shell'; import { version as appVersion } from '../../package.json'; import { NavLink } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Disc3, Users, Music4, Radio, Settings, Heart, BarChart3, Shuffle, ListMusic, PanelLeftClose, PanelLeft, HelpCircle, Dices, ArrowUpCircle, AudioLines } from 'lucide-react'; import PsysonicLogo from './PsysonicLogo'; import PSmallLogo from './PSmallLogo'; const navItems = [ { icon: Disc3, labelKey: 'sidebar.mainstage', to: '/' }, { icon: Radio, labelKey: 'sidebar.newReleases', to: '/new-releases' }, { icon: Music4, labelKey: 'sidebar.allAlbums', to: '/albums' }, { icon: Dices, labelKey: 'sidebar.randomAlbums', to: '/random-albums' }, { icon: Users, labelKey: 'sidebar.artists', to: '/artists' }, { icon: ListMusic, labelKey: 'sidebar.playlists', to: '/playlists' }, { icon: Shuffle, labelKey: 'sidebar.randomMix', to: '/random-mix' }, { icon: Heart, labelKey: 'sidebar.favorites', to: '/favorites' }, ]; function isNewer(latest: string, current: string): boolean { const parse = (v: string) => v.replace(/^[^0-9]*/, '').split('.').map(Number); const [lMaj, lMin, lPat] = parse(latest); const [cMaj, cMin, cPat] = parse(current); if (lMaj !== cMaj) return lMaj > cMaj; if (lMin !== cMin) return lMin > cMin; return lPat > cPat; } function UpdateToast({ isCollapsed, latestVersion }: { isCollapsed: boolean; latestVersion: string }) { const { t } = useTranslation(); if (isCollapsed) { return (
); } return (
{t('sidebar.updateAvailable')}
{t('sidebar.updateReady', { version: latestVersion })}
); } export default function Sidebar({ isCollapsed = false, toggleCollapse }: { isCollapsed?: boolean; toggleCollapse?: () => void; }) { const { t } = useTranslation(); const isPlaying = usePlayerStore(s => s.isPlaying); const currentTrack = usePlayerStore(s => s.currentTrack); const [latestVersion, setLatestVersion] = useState(null); useEffect(() => { let cancelled = false; const check = async () => { try { const res = await fetch('https://api.github.com/repos/Psychotoxical/psysonic/releases/latest'); if (!res.ok) return; const data = await res.json(); const tag: string = data.tag_name ?? ''; if (!cancelled && tag && isNewer(tag, appVersion)) { setLatestVersion(tag.replace(/^v/i, '')); } } catch { // network unavailable — silently skip } }; const initial = setTimeout(check, 1500); const interval = setInterval(check, 10 * 60 * 1000); // every 10 minutes return () => { cancelled = true; clearTimeout(initial); clearInterval(interval); }; }, []); return ( ); }