Merge branch 'main' into feature/firebase
This commit is contained in:
commit
bf344268e7
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "pickle-glass",
|
||||
"version": "0.2.2",
|
||||
"version": "0.2.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pickle-glass",
|
||||
"version": "0.2.2",
|
||||
"version": "0.2.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
|
@ -1,7 +1,9 @@
|
||||
{
|
||||
"name": "pickle-glass",
|
||||
"productName": "Glass",
|
||||
"version": "0.2.2",
|
||||
|
||||
"version": "0.2.3",
|
||||
|
||||
"description": "Cl*ely for Free",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
|
@ -6,7 +6,8 @@ const LATEST_SCHEMA = {
|
||||
{ name: 'email', type: 'TEXT NOT NULL' },
|
||||
{ name: 'created_at', type: 'INTEGER' },
|
||||
{ name: 'api_key', type: 'TEXT' },
|
||||
{ name: 'provider', type: 'TEXT DEFAULT \'openai\'' }
|
||||
{ name: 'provider', type: 'TEXT DEFAULT \'openai\'' },
|
||||
{ name: 'auto_update_enabled', type: 'INTEGER DEFAULT 1' }
|
||||
]
|
||||
},
|
||||
sessions: {
|
||||
|
@ -41,11 +41,13 @@ class AuthService {
|
||||
// Initialize immediately for the default local user on startup.
|
||||
// This ensures the key is ready before any login/logout state change.
|
||||
encryptionService.initializeKey(this.currentUserId);
|
||||
this.initializationPromise = null;
|
||||
}
|
||||
|
||||
initialize() {
|
||||
if (this.isInitialized) return;
|
||||
if (this.isInitialized) return this.initializationPromise;
|
||||
|
||||
this.initializationPromise = new Promise((resolve) => {
|
||||
const auth = getFirebaseAuth();
|
||||
onAuthStateChanged(auth, async (user) => {
|
||||
const previousUser = this.currentUser;
|
||||
@ -94,10 +96,16 @@ class AuthService {
|
||||
await encryptionService.initializeKey(this.currentUserId);
|
||||
}
|
||||
this.broadcastUserState();
|
||||
|
||||
if (!this.isInitialized) {
|
||||
this.isInitialized = true;
|
||||
console.log('[AuthService] Initialized and resolved initialization promise.');
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.isInitialized = true;
|
||||
console.log('[AuthService] Initialized and attached to Firebase Auth state.');
|
||||
return this.initializationPromise;
|
||||
}
|
||||
|
||||
async signInWithCustomToken(token) {
|
||||
|
@ -456,6 +456,8 @@ export class SettingsView extends LitElement {
|
||||
presets: { type: Array, state: true },
|
||||
selectedPreset: { type: Object, state: true },
|
||||
showPresets: { type: Boolean, state: true },
|
||||
autoUpdateEnabled: { type: Boolean, state: true },
|
||||
autoUpdateLoading: { type: Boolean, state: true },
|
||||
};
|
||||
//////// after_modelStateService ////////
|
||||
|
||||
@ -479,10 +481,48 @@ export class SettingsView extends LitElement {
|
||||
this.selectedPreset = null;
|
||||
this.showPresets = false;
|
||||
this.handleUsePicklesKey = this.handleUsePicklesKey.bind(this)
|
||||
this.autoUpdateEnabled = true;
|
||||
this.autoUpdateLoading = true;
|
||||
this.loadInitialData();
|
||||
//////// after_modelStateService ////////
|
||||
}
|
||||
|
||||
async loadAutoUpdateSetting() {
|
||||
if (!window.require) return;
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
this.autoUpdateLoading = true;
|
||||
try {
|
||||
const enabled = await ipcRenderer.invoke('settings:get-auto-update');
|
||||
this.autoUpdateEnabled = enabled;
|
||||
console.log('Auto-update setting loaded:', enabled);
|
||||
} catch (e) {
|
||||
console.error('Error loading auto-update setting:', e);
|
||||
this.autoUpdateEnabled = true; // fallback
|
||||
}
|
||||
this.autoUpdateLoading = false;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
async handleToggleAutoUpdate() {
|
||||
if (!window.require || this.autoUpdateLoading) return;
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
this.autoUpdateLoading = true;
|
||||
this.requestUpdate();
|
||||
try {
|
||||
const newValue = !this.autoUpdateEnabled;
|
||||
const result = await ipcRenderer.invoke('settings:set-auto-update', newValue);
|
||||
if (result && result.success) {
|
||||
this.autoUpdateEnabled = newValue;
|
||||
} else {
|
||||
console.error('Failed to update auto-update setting');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error toggling auto-update:', e);
|
||||
}
|
||||
this.autoUpdateLoading = false;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
//////// after_modelStateService ////////
|
||||
async loadInitialData() {
|
||||
if (!window.require) return;
|
||||
@ -617,6 +657,7 @@ export class SettingsView extends LitElement {
|
||||
this.setupEventListeners();
|
||||
this.setupIpcListeners();
|
||||
this.setupWindowResize();
|
||||
this.loadAutoUpdateSetting();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
@ -648,6 +689,7 @@ export class SettingsView extends LitElement {
|
||||
} else {
|
||||
this.firebaseUser = null;
|
||||
}
|
||||
this.loadAutoUpdateSetting();
|
||||
this.requestUpdate();
|
||||
};
|
||||
|
||||
@ -1161,6 +1203,9 @@ export class SettingsView extends LitElement {
|
||||
<button class="settings-button full-width" @click=${this.handlePersonalize}>
|
||||
<span>Personalize / Meeting Notes</span>
|
||||
</button>
|
||||
<button class="settings-button full-width" @click=${this.handleToggleAutoUpdate} ?disabled=${this.autoUpdateLoading}>
|
||||
<span>Automatic Updates: ${this.autoUpdateEnabled ? 'On' : 'Off'}</span>
|
||||
</button>
|
||||
|
||||
<div class="move-buttons">
|
||||
<button class="settings-button half-width" @click=${this.handleMoveLeft}>
|
||||
|
@ -85,10 +85,53 @@ async function deletePreset(id, uid) {
|
||||
return { changes: 1 };
|
||||
}
|
||||
|
||||
async function getAutoUpdate(uid) {
|
||||
// Assume users are stored in a "users" collection, and auto_update_enabled is a field
|
||||
const userDocRef = doc(getFirestore(), 'users', uid);
|
||||
try {
|
||||
const userSnap = await getDoc(userDocRef);
|
||||
if (userSnap.exists()) {
|
||||
const data = userSnap.data();
|
||||
if (typeof data.auto_update_enabled !== 'undefined') {
|
||||
console.log('Firebase: Auto update setting found:', data.auto_update_enabled);
|
||||
return !!data.auto_update_enabled;
|
||||
} else {
|
||||
// Field does not exist, just return default
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// User doc does not exist, just return default
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Firebase: Error getting auto_update_enabled setting:', error);
|
||||
return true; // fallback to enabled
|
||||
}
|
||||
}
|
||||
|
||||
async function setAutoUpdate(uid, isEnabled) {
|
||||
const userDocRef = doc(getFirestore(), 'users', uid);
|
||||
try {
|
||||
const userSnap = await getDoc(userDocRef);
|
||||
if (userSnap.exists()) {
|
||||
await updateDoc(userDocRef, { auto_update_enabled: !!isEnabled });
|
||||
}
|
||||
// If user doc does not exist, do nothing (no creation)
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Firebase: Error setting auto-update:', error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
getPresets,
|
||||
getPresetTemplates,
|
||||
createPreset,
|
||||
updatePreset,
|
||||
deletePreset,
|
||||
getAutoUpdate,
|
||||
setAutoUpdate,
|
||||
};
|
@ -34,6 +34,16 @@ const settingsRepositoryAdapter = {
|
||||
const uid = authService.getCurrentUserId();
|
||||
return getBaseRepository().deletePreset(id, uid);
|
||||
},
|
||||
|
||||
getAutoUpdate: () => {
|
||||
const uid = authService.getCurrentUserId();
|
||||
return getBaseRepository().getAutoUpdate(uid);
|
||||
},
|
||||
|
||||
setAutoUpdate: (isEnabled) => {
|
||||
const uid = authService.getCurrentUserId();
|
||||
return getBaseRepository().setAutoUpdate(uid, isEnabled);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = settingsRepositoryAdapter;
|
@ -90,10 +90,57 @@ function deletePreset(id, uid) {
|
||||
}
|
||||
}
|
||||
|
||||
function getAutoUpdate(uid) {
|
||||
const db = sqliteClient.getDb();
|
||||
const targetUid = uid;
|
||||
|
||||
try {
|
||||
const row = db.prepare('SELECT auto_update_enabled FROM users WHERE uid = ?').get(targetUid);
|
||||
|
||||
if (row) {
|
||||
console.log('SQLite: Auto update setting found:', row.auto_update_enabled);
|
||||
return row.auto_update_enabled !== 0;
|
||||
} else {
|
||||
// User doesn't exist, create them with default settings
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const stmt = db.prepare(
|
||||
'INSERT OR REPLACE INTO users (uid, display_name, email, created_at, auto_update_enabled) VALUES (?, ?, ?, ?, ?)');
|
||||
stmt.run(targetUid, 'User', 'user@example.com', now, 1);
|
||||
return true; // default to enabled
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('SQLite: Error getting auto_update_enabled setting:', error);
|
||||
return true; // fallback to enabled
|
||||
}
|
||||
}
|
||||
|
||||
function setAutoUpdate(uid, isEnabled) {
|
||||
const db = sqliteClient.getDb();
|
||||
const targetUid = uid || sqliteClient.defaultUserId;
|
||||
|
||||
try {
|
||||
const result = db.prepare('UPDATE users SET auto_update_enabled = ? WHERE uid = ?').run(isEnabled ? 1 : 0, targetUid);
|
||||
|
||||
// If no rows were updated, the user might not exist, so create them
|
||||
if (result.changes === 0) {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const stmt = db.prepare('INSERT OR REPLACE INTO users (uid, display_name, email, created_at, auto_update_enabled) VALUES (?, ?, ?, ?, ?)');
|
||||
stmt.run(targetUid, 'User', 'user@example.com', now, isEnabled ? 1 : 0);
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('SQLite: Error setting auto-update:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getPresets,
|
||||
getPresetTemplates,
|
||||
createPreset,
|
||||
updatePreset,
|
||||
deletePreset
|
||||
deletePreset,
|
||||
getAutoUpdate,
|
||||
setAutoUpdate
|
||||
};
|
@ -364,6 +364,25 @@ async function updateContentProtection(enabled) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getAutoUpdateSetting() {
|
||||
try {
|
||||
return settingsRepository.getAutoUpdate();
|
||||
} catch (error) {
|
||||
console.error('[SettingsService] Error getting auto update setting:', error);
|
||||
return true; // Fallback to enabled
|
||||
}
|
||||
}
|
||||
|
||||
async function setAutoUpdateSetting(isEnabled) {
|
||||
try {
|
||||
await settingsRepository.setAutoUpdate(isEnabled);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('[SettingsService] Error setting auto update setting:', error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
// cleanup
|
||||
windowNotificationManager.cleanup();
|
||||
@ -410,6 +429,15 @@ function initialize() {
|
||||
return await updateContentProtection(enabled);
|
||||
});
|
||||
|
||||
ipcMain.handle('settings:get-auto-update', async () => {
|
||||
return await getAutoUpdateSetting();
|
||||
});
|
||||
|
||||
ipcMain.handle('settings:set-auto-update', async (event, isEnabled) => {
|
||||
console.log('[SettingsService] Setting auto update setting:', isEnabled);
|
||||
return await setAutoUpdateSetting(isEnabled);
|
||||
});
|
||||
|
||||
console.log('[SettingsService] Initialized and ready.');
|
||||
}
|
||||
|
||||
@ -440,4 +468,5 @@ module.exports = {
|
||||
saveApiKey,
|
||||
removeApiKey,
|
||||
updateContentProtection,
|
||||
getAutoUpdateSetting,
|
||||
};
|
11
src/index.js
11
src/index.js
@ -26,6 +26,7 @@ const askService = require('./features/ask/askService');
|
||||
const settingsService = require('./features/settings/settingsService');
|
||||
const sessionRepository = require('./common/repositories/session');
|
||||
const ModelStateService = require('./common/services/modelStateService');
|
||||
const sqliteClient = require('./common/services/sqliteClient');
|
||||
|
||||
const eventBridge = new EventEmitter();
|
||||
let WEB_PORT = 3000;
|
||||
@ -189,7 +190,7 @@ app.whenReady().then(async () => {
|
||||
// Clean up zombie sessions from previous runs first
|
||||
sessionRepository.endAllActiveSessions();
|
||||
|
||||
authService.initialize();
|
||||
await authService.initialize();
|
||||
|
||||
//////// after_modelStateService ////////
|
||||
modelStateService.initialize();
|
||||
@ -215,6 +216,7 @@ app.whenReady().then(async () => {
|
||||
);
|
||||
}
|
||||
|
||||
// initAutoUpdater should be called after auth is initialized
|
||||
initAutoUpdater();
|
||||
|
||||
// Process any pending deep link after everything is initialized
|
||||
@ -677,8 +679,13 @@ async function startWebStack() {
|
||||
}
|
||||
|
||||
// Auto-update initialization
|
||||
function initAutoUpdater() {
|
||||
async function initAutoUpdater() {
|
||||
try {
|
||||
const autoUpdateEnabled = await settingsService.getAutoUpdateSetting();
|
||||
if (!autoUpdateEnabled) {
|
||||
console.log('[AutoUpdater] Skipped because auto-updates are disabled in settings');
|
||||
return;
|
||||
}
|
||||
// Skip auto-updater in development mode
|
||||
if (!app.isPackaged) {
|
||||
console.log('[AutoUpdater] Skipped in development (app is not packaged)');
|
||||
|
Loading…
x
Reference in New Issue
Block a user