feat: Refactor service worker registration and enhance offline download manager with client-side checks
This commit is contained in:
@@ -15,8 +15,9 @@ import { LoginForm } from "./start-screen";
|
||||
import Image from "next/image";
|
||||
import PageTransition from "./PageTransition";
|
||||
|
||||
// Service Worker registration
|
||||
if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
|
||||
// Service Worker registration - moved to useEffect to ensure it only runs client-side
|
||||
React.useEffect(() => {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js')
|
||||
.then((registration) => {
|
||||
console.log('Service Worker registered successfully:', registration);
|
||||
@@ -25,6 +26,7 @@ if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
|
||||
console.error('Service Worker registration failed:', error);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
function NavidromeErrorBoundary({ children }: { children: React.ReactNode }) {
|
||||
// For now, since we're switching to offline-first, we'll handle errors differently
|
||||
|
||||
@@ -394,7 +394,95 @@ class DownloadManager {
|
||||
}
|
||||
}
|
||||
|
||||
const downloadManager = new DownloadManager();
|
||||
// Create a singleton instance that will be initialized on the client side
|
||||
let downloadManagerInstance: DownloadManager | null = null;
|
||||
|
||||
// Only create the download manager instance on the client side
|
||||
if (typeof window !== 'undefined') {
|
||||
downloadManagerInstance = new DownloadManager();
|
||||
}
|
||||
|
||||
// Create a safe wrapper around the download manager
|
||||
const downloadManager = {
|
||||
initialize: async () => {
|
||||
if (!downloadManagerInstance) return false;
|
||||
return downloadManagerInstance.initialize();
|
||||
},
|
||||
getOfflineStats: async () => {
|
||||
if (!downloadManagerInstance) return {
|
||||
totalSize: 0,
|
||||
audioSize: 0,
|
||||
imageSize: 0,
|
||||
metaSize: 0,
|
||||
downloadedAlbums: 0,
|
||||
downloadedSongs: 0,
|
||||
lastDownload: null,
|
||||
downloadErrors: 0,
|
||||
remainingStorage: null,
|
||||
autoDownloadEnabled: false,
|
||||
downloadQuality: 'original' as const,
|
||||
downloadOnWifiOnly: true,
|
||||
priorityContent: []
|
||||
};
|
||||
return downloadManagerInstance.getOfflineStats();
|
||||
},
|
||||
downloadAlbum: async (album: Album, songs: Song[], progressCallback: (progress: DownloadProgress) => void) => {
|
||||
if (!downloadManagerInstance) return;
|
||||
return downloadManagerInstance.downloadAlbum(album, songs, progressCallback);
|
||||
},
|
||||
downloadAlbumFallback: async (album: Album, songs: Song[]) => {
|
||||
if (!downloadManagerInstance) return;
|
||||
return downloadManagerInstance.downloadAlbumFallback(album, songs);
|
||||
},
|
||||
downloadSong: async (song: Song) => {
|
||||
if (!downloadManagerInstance) return;
|
||||
return downloadManagerInstance.downloadSong(song);
|
||||
},
|
||||
getOfflineData: () => {
|
||||
if (!downloadManagerInstance) return { albums: {}, songs: {} };
|
||||
return downloadManagerInstance.getOfflineData();
|
||||
},
|
||||
saveOfflineData: (data: any) => {
|
||||
if (!downloadManagerInstance) return;
|
||||
return downloadManagerInstance.saveOfflineData(data);
|
||||
},
|
||||
checkOfflineStatus: async (id: string, type: 'album' | 'song') => {
|
||||
if (!downloadManagerInstance) return false;
|
||||
return downloadManagerInstance.checkOfflineStatus(id, type);
|
||||
},
|
||||
checkOfflineStatusFallback: (id: string, type: 'album' | 'song') => {
|
||||
if (!downloadManagerInstance) return false;
|
||||
return downloadManagerInstance.checkOfflineStatusFallback(id, type);
|
||||
},
|
||||
deleteOfflineContent: async (id: string, type: 'album' | 'song') => {
|
||||
if (!downloadManagerInstance) return;
|
||||
return downloadManagerInstance.deleteOfflineContent(id, type);
|
||||
},
|
||||
deleteOfflineContentFallback: async (id: string, type: 'album' | 'song') => {
|
||||
if (!downloadManagerInstance) return;
|
||||
return downloadManagerInstance.deleteOfflineContentFallback(id, type);
|
||||
},
|
||||
getOfflineItems: async () => {
|
||||
if (!downloadManagerInstance) return { albums: [], songs: [] };
|
||||
return downloadManagerInstance.getOfflineItems();
|
||||
},
|
||||
getOfflineAlbums: () => {
|
||||
if (!downloadManagerInstance) return [];
|
||||
return downloadManagerInstance.getOfflineAlbums();
|
||||
},
|
||||
getOfflineSongs: () => {
|
||||
if (!downloadManagerInstance) return [];
|
||||
return downloadManagerInstance.getOfflineSongs();
|
||||
},
|
||||
downloadQueue: async (songs: Song[]) => {
|
||||
if (!downloadManagerInstance) return;
|
||||
return downloadManagerInstance.downloadQueue(songs);
|
||||
},
|
||||
enableOfflineMode: async (settings: any) => {
|
||||
if (!downloadManagerInstance) return;
|
||||
return downloadManagerInstance.enableOfflineMode(settings);
|
||||
}
|
||||
};
|
||||
|
||||
export function useOfflineDownloads() {
|
||||
const [isSupported, setIsSupported] = useState(false);
|
||||
@@ -424,6 +512,13 @@ export function useOfflineDownloads() {
|
||||
|
||||
useEffect(() => {
|
||||
const initializeDownloadManager = async () => {
|
||||
// Skip initialization on server-side
|
||||
if (!downloadManager) {
|
||||
setIsSupported(false);
|
||||
setIsInitialized(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const supported = await downloadManager.initialize();
|
||||
setIsSupported(supported);
|
||||
setIsInitialized(true);
|
||||
|
||||
@@ -86,7 +86,10 @@ export function useOfflineLibrarySync() {
|
||||
window.addEventListener('online', handleOnline);
|
||||
window.addEventListener('offline', handleOffline);
|
||||
|
||||
// Check if navigator is available (client-side only)
|
||||
if (typeof navigator !== 'undefined') {
|
||||
setIsOnline(navigator.onLine);
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('online', handleOnline);
|
||||
|
||||
@@ -19,9 +19,12 @@ export interface OfflineLibraryState {
|
||||
}
|
||||
|
||||
export function useOfflineLibrary() {
|
||||
// Check if we're on the client side
|
||||
const isClient = typeof window !== 'undefined';
|
||||
|
||||
const [state, setState] = useState<OfflineLibraryState>({
|
||||
isInitialized: false,
|
||||
isOnline: navigator.onLine,
|
||||
isOnline: isClient ? navigator.onLine : true, // Default to true during SSR
|
||||
isSyncing: false,
|
||||
lastSync: null,
|
||||
stats: {
|
||||
|
||||
Reference in New Issue
Block a user