feat: Implement offline library management with IndexedDB support

- Added `useOfflineLibrary` hook for managing offline library state and synchronization.
- Created `OfflineLibraryManager` class for handling IndexedDB operations and syncing with Navidrome API.
- Implemented methods for retrieving and storing albums, artists, songs, and playlists.
- Added support for offline favorites management (star/unstar).
- Implemented playlist creation, updating, and deletion functionalities.
- Added search functionality for offline data.
- Created a manifest file for PWA support with icons and shortcuts.
- Added service worker file for caching and offline capabilities.
This commit is contained in:
2025-08-07 22:07:53 +00:00
committed by GitHub
parent af5e24b80e
commit f6a6ee5d2e
23 changed files with 4239 additions and 229 deletions

View File

@@ -2,7 +2,7 @@
import React from "react";
import { AudioPlayerProvider } from "../components/AudioPlayerContext";
import { NavidromeProvider, useNavidrome } from "../components/NavidromeContext";
import { OfflineNavidromeProvider, useOfflineNavidrome } from "../components/OfflineNavidromeProvider";
import { NavidromeConfigProvider } from "../components/NavidromeConfigContext";
import { ThemeProvider } from "../components/ThemeProvider";
import { PostHogProvider } from "../components/PostHogProvider";
@@ -14,8 +14,20 @@ import { useViewportThemeColor } from "@/hooks/use-viewport-theme-color";
import { LoginForm } from "./start-screen";
import Image from "next/image";
// Service Worker registration
if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then((registration) => {
console.log('Service Worker registered successfully:', registration);
})
.catch((error) => {
console.error('Service Worker registration failed:', error);
});
}
function NavidromeErrorBoundary({ children }: { children: React.ReactNode }) {
const { error } = useNavidrome();
// For now, since we're switching to offline-first, we'll handle errors differently
// The offline provider will handle connectivity issues automatically
const [isClient, setIsClient] = React.useState(false);
const [hasCompletedOnboarding, setHasCompletedOnboarding] = React.useState(true); // Default to true to prevent flash
@@ -58,10 +70,9 @@ function NavidromeErrorBoundary({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}
// Show start screen ONLY if:
// 1. First-time user (no onboarding completed), OR
// 2. User has completed onboarding BUT there's an error AND no config exists
const shouldShowStartScreen = !hasCompletedOnboarding || (hasCompletedOnboarding && error && !hasAnyConfig);
// Show start screen ONLY if first-time user (no onboarding completed)
// In offline-first mode, we don't need to check for errors since the app works offline
const shouldShowStartScreen = !hasCompletedOnboarding;
if (shouldShowStartScreen) {
return (
@@ -87,7 +98,7 @@ export default function RootLayoutClient({ children }: { children: React.ReactNo
<DynamicViewportTheme />
<ThemeColorHandler />
<NavidromeConfigProvider>
<NavidromeProvider>
<OfflineNavidromeProvider>
<NavidromeErrorBoundary>
<AudioPlayerProvider>
<Ihateserverside>
@@ -96,7 +107,7 @@ export default function RootLayoutClient({ children }: { children: React.ReactNo
<WhatsNewPopup />
</AudioPlayerProvider>
</NavidromeErrorBoundary>
</NavidromeProvider>
</OfflineNavidromeProvider>
</NavidromeConfigProvider>
</ThemeProvider>
</PostHogProvider>