Remove SyncService and introduce context-based offline mode and state management
- 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.
This commit is contained in:
129
context/OfflineProvider.tsx
Normal file
129
context/OfflineProvider.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
'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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user