diff --git a/package-lock.json b/package-lock.json index 944e413..bad6efc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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": { diff --git a/package.json b/package.json index 84777a5..ea125a0 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "pickle-glass", "productName": "Glass", - "version": "0.2.2", + "version": "0.2.3", "description": "Cl*ely for Free", "main": "src/index.js", diff --git a/src/common/config/schema.js b/src/common/config/schema.js index 19e0d8c..00b58f7 100644 --- a/src/common/config/schema.js +++ b/src/common/config/schema.js @@ -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: { diff --git a/src/common/services/authService.js b/src/common/services/authService.js index a664ba1..fd4b9de 100644 --- a/src/common/services/authService.js +++ b/src/common/services/authService.js @@ -37,56 +37,64 @@ class AuthService { this.currentUserMode = 'local'; // 'local' or 'firebase' this.currentUser = null; this.isInitialized = false; + this.initializationPromise = null; } initialize() { - if (this.isInitialized) return; + if (this.isInitialized) return this.initializationPromise; - const auth = getFirebaseAuth(); - onAuthStateChanged(auth, async (user) => { - const previousUser = this.currentUser; + this.initializationPromise = new Promise((resolve) => { + const auth = getFirebaseAuth(); + onAuthStateChanged(auth, async (user) => { + const previousUser = this.currentUser; - if (user) { - // User signed IN - console.log(`[AuthService] Firebase user signed in:`, user.uid); - this.currentUser = user; - this.currentUserId = user.uid; - this.currentUserMode = 'firebase'; + if (user) { + // User signed IN + console.log(`[AuthService] Firebase user signed in:`, user.uid); + this.currentUser = user; + this.currentUserId = user.uid; + this.currentUserMode = 'firebase'; - // Start background task to fetch and save virtual key - (async () => { - try { - const idToken = await user.getIdToken(true); - const virtualKey = await getVirtualKeyByEmail(user.email, idToken); + // Start background task to fetch and save virtual key + (async () => { + try { + const idToken = await user.getIdToken(true); + const virtualKey = await getVirtualKeyByEmail(user.email, idToken); - if (global.modelStateService) { - global.modelStateService.setFirebaseVirtualKey(virtualKey); + if (global.modelStateService) { + global.modelStateService.setFirebaseVirtualKey(virtualKey); + } + console.log(`[AuthService] BG: Virtual key for ${user.email} has been processed.`); + + } catch (error) { + console.error('[AuthService] BG: Failed to fetch or save virtual key:', error); } - console.log(`[AuthService] BG: Virtual key for ${user.email} has been processed.`); + })(); - } catch (error) { - console.error('[AuthService] BG: Failed to fetch or save virtual key:', error); - } - })(); - - } else { - // User signed OUT - console.log(`[AuthService] No Firebase user.`); - if (previousUser) { - console.log(`[AuthService] Clearing API key for logged-out user: ${previousUser.uid}`); - if (global.modelStateService) { - global.modelStateService.setFirebaseVirtualKey(null); + } else { + // User signed OUT + console.log(`[AuthService] No Firebase user.`); + if (previousUser) { + console.log(`[AuthService] Clearing API key for logged-out user: ${previousUser.uid}`); + if (global.modelStateService) { + global.modelStateService.setFirebaseVirtualKey(null); + } } + this.currentUser = null; + this.currentUserId = 'default_user'; + this.currentUserMode = 'local'; } - this.currentUser = null; - this.currentUserId = 'default_user'; - this.currentUserMode = 'local'; - } - this.broadcastUserState(); + 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) { diff --git a/src/electron/smoothMovementManager.js b/src/electron/smoothMovementManager.js index a676c82..d7ccfae 100644 --- a/src/electron/smoothMovementManager.js +++ b/src/electron/smoothMovementManager.js @@ -120,6 +120,11 @@ class SmoothMovementManager { let targetX = this.headerPosition.x; let targetY = this.headerPosition.y; + const windowSize = { + width: currentBounds.width, + height: currentBounds.height + }; + switch (direction) { case 'left': targetX -= this.stepSize; break; case 'right': targetX += this.stepSize; break; @@ -130,22 +135,23 @@ class SmoothMovementManager { const displays = screen.getAllDisplays(); let validPosition = displays.some(d => ( - targetX >= d.workArea.x && targetX + currentBounds.width <= d.workArea.x + d.workArea.width && - targetY >= d.workArea.y && targetY + currentBounds.height <= d.workArea.y + d.workArea.height + targetX >= d.workArea.x && targetX + windowSize.width <= d.workArea.x + d.workArea.width && + targetY >= d.workArea.y && targetY + windowSize.height <= d.workArea.y + d.workArea.height )); if (!validPosition) { const nearestDisplay = screen.getDisplayNearestPoint({ x: targetX, y: targetY }); const { x, y, width, height } = nearestDisplay.workArea; - targetX = Math.max(x, Math.min(x + width - currentBounds.width, targetX)); - targetY = Math.max(y, Math.min(y + height - currentBounds.height, targetY)); + targetX = Math.max(x, Math.min(x + width - windowSize.width, targetX)); + targetY = Math.max(y, Math.min(y + height - windowSize.height, targetY)); } if (targetX === this.headerPosition.x && targetY === this.headerPosition.y) return; - this.animateToPosition(header, targetX, targetY); + + this.animateToPosition(header, targetX, targetY, windowSize); } - animateToPosition(header, targetX, targetY) { + animateToPosition(header, targetX, targetY, windowSize) { if (!this._isWindowValid(header)) return; this.isAnimating = true; @@ -173,7 +179,13 @@ class SmoothMovementManager { } if (!this._isWindowValid(header)) return; - header.setPosition(Math.round(currentX), Math.round(currentY)); + const { width, height } = windowSize || header.getBounds(); + header.setBounds({ + x: Math.round(currentX), + y: Math.round(currentY), + width, + height + }); if (progress < 1) { this.animationFrameId = setTimeout(animate, 8); @@ -198,20 +210,40 @@ class SmoothMovementManager { const display = this.getCurrentDisplay(header); const { width, height } = display.workAreaSize; const { x: workAreaX, y: workAreaY } = display.workArea; - const headerBounds = header.getBounds(); const currentBounds = header.getBounds(); + + const windowSize = { + width: currentBounds.width, + height: currentBounds.height + }; + let targetX = currentBounds.x; let targetY = currentBounds.y; switch (direction) { - case 'left': targetX = workAreaX; break; - case 'right': targetX = workAreaX + width - headerBounds.width; break; - case 'up': targetY = workAreaY; break; - case 'down': targetY = workAreaY + height - headerBounds.height; break; + case 'left': + targetX = workAreaX; + break; + case 'right': + targetX = workAreaX + width - windowSize.width; + break; + case 'up': + targetY = workAreaY; + break; + case 'down': + targetY = workAreaY + height - windowSize.height; + break; } - this.headerPosition = { x: currentBounds.x, y: currentBounds.y }; - this.animateToPosition(header, targetX, targetY); + header.setBounds({ + x: Math.round(targetX), + y: Math.round(targetY), + width: windowSize.width, + height: windowSize.height + }); + + this.headerPosition = { x: targetX, y: targetY }; + this.updateLayout(); } destroy() { @@ -224,4 +256,4 @@ class SmoothMovementManager { } } -module.exports = SmoothMovementManager; \ No newline at end of file +module.exports = SmoothMovementManager; diff --git a/src/features/settings/SettingsView.js b/src/features/settings/SettingsView.js index 7dbd9f1..bd99937 100644 --- a/src/features/settings/SettingsView.js +++ b/src/features/settings/SettingsView.js @@ -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 { +