- Delete `SyncService` and its associated bidirectional synchronization logic. - Add multiple context providers (`OfflineProvider`, `AlertProvider`, `LangContext`, `UserContext`, `SessionContext`, `WorldContext`, `SettingBookContext`) for contextual state management. - Implement `SecureStorage` for OS-level secure data encryption and replace dependency on `SyncService` synchronization. - Update localization files (`en.json`, `fr.json`) with offline mode and error-related strings.
130 lines
4.3 KiB
TypeScript
130 lines
4.3 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState, useEffect, useCallback, ReactNode } from 'react';
|
|
import OfflineContext, { OfflineMode, defaultOfflineMode } from './OfflineContext';
|
|
|
|
interface OfflineProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
export default function OfflineProvider({ children }: OfflineProviderProps) {
|
|
const [offlineMode, setOfflineMode] = useState<OfflineMode>(defaultOfflineMode);
|
|
|
|
const initializeDatabase = useCallback(async (userId: string, encryptionKey?: string): Promise<boolean> => {
|
|
try {
|
|
if (typeof window === 'undefined' || !(window as any).electron) {
|
|
console.warn('Not running in Electron, offline mode not available');
|
|
return false;
|
|
}
|
|
|
|
let userKey = encryptionKey;
|
|
if (!userKey) {
|
|
const storedKey = await (window as any).electron.getUserEncryptionKey(userId);
|
|
if (storedKey) {
|
|
userKey = storedKey;
|
|
} else {
|
|
const keyResult = await (window as any).electron.generateEncryptionKey(userId);
|
|
if (!keyResult.success) {
|
|
throw new Error(keyResult.error || 'Failed to generate encryption key');
|
|
}
|
|
userKey = keyResult.key;
|
|
await (window as any).electron.setUserEncryptionKey(userId, userKey);
|
|
}
|
|
}
|
|
|
|
const result = await (window as any).electron.dbInitialize(userId, userKey);
|
|
if (!result.success) {
|
|
throw new Error(result.error || 'Failed to initialize database');
|
|
}
|
|
|
|
setOfflineMode(prev => ({
|
|
...prev,
|
|
isDatabaseInitialized: true,
|
|
error: null
|
|
}));
|
|
|
|
console.log('Database initialized successfully for user:', userId);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Failed to initialize database:', error);
|
|
setOfflineMode(prev => ({
|
|
...prev,
|
|
isDatabaseInitialized: false,
|
|
error: error instanceof Error ? error.message : 'Failed to initialize database'
|
|
}));
|
|
return false;
|
|
}
|
|
}, []);
|
|
|
|
const toggleOfflineMode = useCallback(() => {
|
|
setOfflineMode(prev => {
|
|
const newManuallyOffline = !prev.isManuallyOffline;
|
|
const newIsOffline = newManuallyOffline || !prev.isNetworkOnline;
|
|
|
|
console.log('Toggle offline mode:', {
|
|
wasManuallyOffline: prev.isManuallyOffline,
|
|
nowManuallyOffline: newManuallyOffline,
|
|
wasOffline: prev.isOffline,
|
|
nowOffline: newIsOffline,
|
|
networkOnline: prev.isNetworkOnline
|
|
});
|
|
|
|
return {
|
|
...prev,
|
|
isManuallyOffline: newManuallyOffline,
|
|
isOffline: newIsOffline
|
|
};
|
|
});
|
|
}, []);
|
|
|
|
const isCurrentlyOffline = useCallback((): boolean => {
|
|
return offlineMode.isOffline;
|
|
}, [offlineMode.isOffline]);
|
|
|
|
useEffect(() => {
|
|
const handleOnline = () => {
|
|
setOfflineMode(prev => {
|
|
const newIsOffline = prev.isManuallyOffline;
|
|
|
|
return {
|
|
...prev,
|
|
isNetworkOnline: true,
|
|
isOffline: newIsOffline
|
|
};
|
|
});
|
|
};
|
|
|
|
const handleOffline = () => {
|
|
setOfflineMode(prev => {
|
|
return {
|
|
...prev,
|
|
isNetworkOnline: false,
|
|
isOffline: true
|
|
};
|
|
});
|
|
};
|
|
|
|
window.addEventListener('online', handleOnline);
|
|
window.addEventListener('offline', handleOffline);
|
|
|
|
return () => {
|
|
window.removeEventListener('online', handleOnline);
|
|
window.removeEventListener('offline', handleOffline);
|
|
};
|
|
}, []);
|
|
|
|
const value = {
|
|
offlineMode,
|
|
setOfflineMode,
|
|
toggleOfflineMode,
|
|
initializeDatabase,
|
|
isCurrentlyOffline
|
|
};
|
|
|
|
return (
|
|
<OfflineContext.Provider value={value}>
|
|
{children}
|
|
</OfflineContext.Provider>
|
|
);
|
|
}
|