mirror of
https://github.com/mudabbir-ahmad/Media-Aggregation-and-Sorting-System.git
synced 2026-10-07 19:40:20 +00:00
refactored code into components (major cleanup for reused code) added email for local acccount creation and changes to how nas and google photo connections work and added themes
This commit is contained in:
1 parent
c1d7139055
commit
6f4ec66e2e
17 files changed
+1761
-1018
No files matched your search
@@ -63,6 +63,14 @@ const DatabaseService = {
|
||||
)
|
||||
`);
|
||||
|
||||
// Migration: add columns if they don't exist
|
||||
try {
|
||||
await db.execAsync(`ALTER TABLE users ADD COLUMN auto_backup_services TEXT DEFAULT '[]'`);
|
||||
} catch (e) { /* column already exists */ }
|
||||
try {
|
||||
await db.execAsync(`ALTER TABLE users ADD COLUMN theme_preference TEXT DEFAULT 'light'`);
|
||||
} catch (e) { /* column already exists */ }
|
||||
|
||||
console.log('Database initialized successfully');
|
||||
return true;
|
||||
} catch (error) {
|
||||
@@ -299,6 +307,65 @@ const DatabaseService = {
|
||||
}
|
||||
},
|
||||
|
||||
getAutoBackupServices: async (userId) => {
|
||||
try {
|
||||
await DatabaseService.ensureDb();
|
||||
const row = await db.getFirstAsync('SELECT auto_backup_services FROM users WHERE id = ?', [userId]);
|
||||
if (!row?.auto_backup_services) return [];
|
||||
return JSON.parse(row.auto_backup_services);
|
||||
} catch (error) {
|
||||
console.error('Error getting auto backup services:', error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
setAutoBackupServices: async (userId, services) => {
|
||||
try {
|
||||
await DatabaseService.ensureDb();
|
||||
await db.runAsync('UPDATE users SET auto_backup_services = ? WHERE id = ?', [JSON.stringify(services), userId]);
|
||||
} catch (error) {
|
||||
console.error('Error setting auto backup services:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
toggleAccountEnabled: async (accountId, enabled) => {
|
||||
try {
|
||||
await DatabaseService.ensureDb();
|
||||
await db.runAsync('UPDATE linked_accounts SET is_enabled = ? WHERE id = ?', [enabled ? 1 : 0, accountId]);
|
||||
} catch (error) {
|
||||
console.error('Error toggling account:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
removeLinkedAccount: async (accountId) => {
|
||||
try {
|
||||
await DatabaseService.ensureDb();
|
||||
await db.runAsync('DELETE FROM linked_accounts WHERE id = ?', [accountId]);
|
||||
} catch (error) {
|
||||
console.error('Error removing account:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
getAllLinkedAccounts: async (userId) => {
|
||||
try {
|
||||
await DatabaseService.ensureDb();
|
||||
const rows = await db.getAllAsync(
|
||||
'SELECT * FROM linked_accounts WHERE user_id = ?',
|
||||
[userId]
|
||||
);
|
||||
return rows.map((row) => ({
|
||||
...row,
|
||||
account_data: CredentialEncryption.decrypt(row.account_data),
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error getting all linked accounts:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
closeDatabase: async () => {
|
||||
try {
|
||||
if (db?.closeAsync) await db.closeAsync();
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
|
||||
const THEME_KEY = 'app_theme_preference';
|
||||
|
||||
const lightTheme = {
|
||||
name: 'light',
|
||||
background: '#ffffff',
|
||||
surface: '#f8f9fa',
|
||||
surfaceElevated: '#ffffff',
|
||||
text: '#202124',
|
||||
textSecondary: '#5f6368',
|
||||
textTertiary: '#9aa0a6',
|
||||
primary: '#1a73e8',
|
||||
primaryLight: '#d2e3fc',
|
||||
accent: '#34a853',
|
||||
danger: '#d93025',
|
||||
border: '#dadce0',
|
||||
borderLight: '#e8eaed',
|
||||
inputBg: '#ffffff',
|
||||
chipBg: '#f1f3f4',
|
||||
chipActiveBg: '#d2e3fc',
|
||||
tabBar: '#ffffff',
|
||||
tabBarBorder: '#e0e0e0',
|
||||
tabActive: '#1a73e8',
|
||||
tabInactive: '#5f6368',
|
||||
card: '#f8f9fa',
|
||||
cardActive: '#e8f0fe',
|
||||
overlay: 'rgba(0,0,0,0.3)',
|
||||
statusBarStyle: 'dark',
|
||||
searchBg: '#f1f3f4',
|
||||
profileBg: '#1a73e8',
|
||||
modalBg: '#000000',
|
||||
modalInfoBg: '#1a1a1a',
|
||||
blur: false,
|
||||
};
|
||||
|
||||
const darkTheme = {
|
||||
name: 'dark',
|
||||
background: '#121212',
|
||||
surface: '#1e1e1e',
|
||||
surfaceElevated: '#2d2d2d',
|
||||
text: '#e8eaed',
|
||||
textSecondary: '#9aa0a6',
|
||||
textTertiary: '#5f6368',
|
||||
primary: '#8ab4f8',
|
||||
primaryLight: '#1f3a5f',
|
||||
accent: '#81c995',
|
||||
danger: '#f28b82',
|
||||
border: '#3c4043',
|
||||
borderLight: '#2d2d2d',
|
||||
inputBg: '#2d2d2d',
|
||||
chipBg: '#2d2d2d',
|
||||
chipActiveBg: '#1f3a5f',
|
||||
tabBar: '#1e1e1e',
|
||||
tabBarBorder: '#3c4043',
|
||||
tabActive: '#8ab4f8',
|
||||
tabInactive: '#9aa0a6',
|
||||
card: '#1e1e1e',
|
||||
cardActive: '#1f3a5f',
|
||||
overlay: 'rgba(0,0,0,0.6)',
|
||||
statusBarStyle: 'light',
|
||||
searchBg: '#2d2d2d',
|
||||
profileBg: '#8ab4f8',
|
||||
modalBg: '#000000',
|
||||
modalInfoBg: '#1e1e1e',
|
||||
blur: false,
|
||||
};
|
||||
|
||||
const liquidGlassTheme = {
|
||||
name: 'liquidGlass',
|
||||
background: '#f0f0f3',
|
||||
surface: 'rgba(255,255,255,0.45)',
|
||||
surfaceElevated: 'rgba(255,255,255,0.7)',
|
||||
text: '#1c1c1e',
|
||||
textSecondary: '#636366',
|
||||
textTertiary: '#aeaeb2',
|
||||
primary: '#007aff',
|
||||
primaryLight: 'rgba(0,122,255,0.12)',
|
||||
accent: '#34c759',
|
||||
danger: '#ff3b30',
|
||||
border: 'rgba(0,0,0,0.08)',
|
||||
borderLight: 'rgba(0,0,0,0.04)',
|
||||
inputBg: 'rgba(255,255,255,0.6)',
|
||||
chipBg: 'rgba(255,255,255,0.5)',
|
||||
chipActiveBg: 'rgba(0,122,255,0.15)',
|
||||
tabBar: 'rgba(249,249,249,0.8)',
|
||||
tabBarBorder: 'rgba(0,0,0,0.08)',
|
||||
tabActive: '#007aff',
|
||||
tabInactive: '#8e8e93',
|
||||
card: 'rgba(255,255,255,0.5)',
|
||||
cardActive: 'rgba(0,122,255,0.12)',
|
||||
overlay: 'rgba(0,0,0,0.25)',
|
||||
statusBarStyle: 'dark',
|
||||
searchBg: 'rgba(118,118,128,0.12)',
|
||||
profileBg: '#007aff',
|
||||
modalBg: 'rgba(0,0,0,0.9)',
|
||||
modalInfoBg: 'rgba(30,30,30,0.9)',
|
||||
blur: true,
|
||||
blurIntensity: 60,
|
||||
blurTint: 'light',
|
||||
};
|
||||
|
||||
const themes = { light: lightTheme, dark: darkTheme, liquidGlass: liquidGlassTheme };
|
||||
|
||||
const ThemeContext = createContext({
|
||||
theme: lightTheme,
|
||||
themeName: 'light',
|
||||
setThemeName: () => {},
|
||||
themes,
|
||||
});
|
||||
|
||||
export const ThemeProvider = ({ children }) => {
|
||||
const [themeName, setThemeNameState] = useState('light');
|
||||
|
||||
useEffect(() => {
|
||||
loadTheme();
|
||||
}, []);
|
||||
|
||||
const loadTheme = async () => {
|
||||
try {
|
||||
const saved = await SecureStore.getItemAsync(THEME_KEY);
|
||||
if (saved && themes[saved]) {
|
||||
setThemeNameState(saved);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Could not load theme preference:', err.message);
|
||||
}
|
||||
};
|
||||
|
||||
const setThemeName = async (name) => {
|
||||
if (!themes[name]) return;
|
||||
setThemeNameState(name);
|
||||
try {
|
||||
await SecureStore.setItemAsync(THEME_KEY, name);
|
||||
} catch (err) {
|
||||
console.log('Could not save theme preference:', err.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ theme: themes[themeName], themeName, setThemeName, themes }}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useTheme = () => useContext(ThemeContext);
|
||||
|
||||
export default ThemeContext;
|
||||
|
||||
Reference in new issue
Block a user