minor fix

This commit is contained in:
jhyang0 2025-07-10 17:30:33 +09:00
parent 2a1edb6ed8
commit 3031d0d288
5 changed files with 28 additions and 105 deletions

View File

@ -43,9 +43,10 @@ export default function LoginPage() {
window.location.href = deepLinkUrl
setTimeout(() => {
alert('Login completed. Please return to Pickle Glass app.')
}, 1000)
// Maybe we don't need this
// setTimeout(() => {
// alert('Login completed. Please return to Pickle Glass app.')
// }, 1000)
} catch (error) {
console.error('❌ Deep link processing failed:', error)

View File

@ -1,89 +0,0 @@
const crypto = require('crypto');
const { app } = require('electron');
const os = require('os');
class CryptoService {
constructor() {
this.algorithm = 'aes-256-gcm';
this.saltLength = 32;
this.tagLength = 16;
this.ivLength = 16;
this.iterations = 100000;
this.keyLength = 32;
this._derivedKey = null;
}
_getMachineId() {
const machineInfo = `${os.hostname()}-${os.platform()}-${os.arch()}`;
const appPath = app.getPath('userData');
return crypto.createHash('sha256').update(machineInfo + appPath).digest('hex');
}
_deriveKey() {
if (this._derivedKey) return this._derivedKey;
const machineId = this._getMachineId();
const salt = crypto.createHash('sha256').update('pickle-glass-salt').digest();
this._derivedKey = crypto.pbkdf2Sync(machineId, salt, this.iterations, this.keyLength, 'sha256');
return this._derivedKey;
}
encrypt(text) {
if (!text) return null;
try {
const iv = crypto.randomBytes(this.ivLength);
const salt = crypto.randomBytes(this.saltLength);
const key = this._deriveKey();
const cipher = crypto.createCipheriv(this.algorithm, key, iv);
const encrypted = Buffer.concat([
cipher.update(text, 'utf8'),
cipher.final()
]);
const tag = cipher.getAuthTag();
const combined = Buffer.concat([salt, iv, tag, encrypted]);
return combined.toString('base64');
} catch (error) {
console.error('[CryptoService] Encryption failed:', error.message);
throw new Error('Encryption failed');
}
}
decrypt(encryptedData) {
if (!encryptedData) return null;
try {
const combined = Buffer.from(encryptedData, 'base64');
const salt = combined.slice(0, this.saltLength);
const iv = combined.slice(this.saltLength, this.saltLength + this.ivLength);
const tag = combined.slice(this.saltLength + this.ivLength, this.saltLength + this.ivLength + this.tagLength);
const encrypted = combined.slice(this.saltLength + this.ivLength + this.tagLength);
const key = this._deriveKey();
const decipher = crypto.createDecipheriv(this.algorithm, key, iv);
decipher.setAuthTag(tag);
const decrypted = Buffer.concat([
decipher.update(encrypted),
decipher.final()
]);
return decrypted.toString('utf8');
} catch (error) {
console.error('[CryptoService] Decryption failed:', error.message);
throw new Error('Decryption failed');
}
}
clearCache() {
this._derivedKey = null;
}
}
module.exports = new CryptoService();

View File

@ -2,7 +2,7 @@ const Store = require('electron-store');
const fetch = require('node-fetch');
const { ipcMain, webContents } = require('electron');
const { PROVIDERS } = require('../ai/factory');
const cryptoService = require('./cryptoService');
const encryptionService = require('./encryptionService');
class ModelStateService {
constructor(authService) {
@ -11,8 +11,8 @@ class ModelStateService {
this.state = {};
}
initialize() {
this._loadStateForCurrentUser();
async initialize() {
await this._loadStateForCurrentUser();
this.setupIpcHandlers();
console.log('[ModelStateService] Initialized.');
@ -64,8 +64,12 @@ class ModelStateService {
});
}
_loadStateForCurrentUser() {
async _loadStateForCurrentUser() {
const userId = this.authService.getCurrentUserId();
// Initialize encryption service for current user
await encryptionService.initializeKey(userId);
const initialApiKeys = Object.keys(PROVIDERS).reduce((acc, key) => {
acc[key] = null;
return acc;
@ -83,7 +87,7 @@ class ModelStateService {
this.state.apiKeys[p] = null;
} else if (this.state.apiKeys[p] && p !== 'ollama' && p !== 'whisper') {
try {
this.state.apiKeys[p] = cryptoService.decrypt(this.state.apiKeys[p]);
this.state.apiKeys[p] = encryptionService.decrypt(this.state.apiKeys[p]);
} catch (error) {
console.error(`[ModelStateService] Failed to decrypt API key for ${p}, resetting`);
this.state.apiKeys[p] = null;
@ -107,7 +111,7 @@ class ModelStateService {
for (const [provider, key] of Object.entries(stateToSave.apiKeys)) {
if (key && provider !== 'ollama' && provider !== 'whisper') {
try {
stateToSave.apiKeys[provider] = cryptoService.encrypt(key);
stateToSave.apiKeys[provider] = encryptionService.encrypt(key);
} catch (error) {
console.error(`[ModelStateService] Failed to encrypt API key for ${provider}`);
stateToSave.apiKeys[provider] = null;

View File

@ -415,7 +415,7 @@ export class AskView extends LitElement {
background: rgba(0, 0, 0, 0.1);
border-top: 1px solid rgba(255, 255, 255, 0.1);
flex-shrink: 0;
transition: all 0.3s ease-in-out;
transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out;
transform-origin: bottom;
}
@ -541,6 +541,7 @@ export class AskView extends LitElement {
this.handleStreamChunk = this.handleStreamChunk.bind(this);
this.handleStreamEnd = this.handleStreamEnd.bind(this);
this.handleSendText = this.handleSendText.bind(this);
this.handleGlobalSendRequest = this.handleGlobalSendRequest.bind(this);
this.handleTextKeydown = this.handleTextKeydown.bind(this);
this.closeResponsePanel = this.closeResponsePanel.bind(this);
this.handleCopy = this.handleCopy.bind(this);
@ -556,7 +557,6 @@ export class AskView extends LitElement {
this.loadLibraries();
// --- Resize helpers ---
this.adjustHeightThrottle = null;
this.isThrottled = false;
}
@ -1220,6 +1220,14 @@ export class AskView extends LitElement {
handleGlobalSendRequest() {
const textInput = this.shadowRoot?.getElementById('textInput');
if (!this.showTextInput) {
this.showTextInput = true;
this.requestUpdate();
this.focusTextInput();
return;
}
if (!textInput) return;
textInput.focus();
@ -1349,12 +1357,11 @@ export class AskView extends LitElement {
adjustWindowHeightThrottled() {
if (this.isThrottled) return;
this.adjustWindowHeight();
this.isThrottled = true;
this.adjustHeightThrottle = setTimeout(() => {
requestAnimationFrame(() => {
this.adjustWindowHeight();
this.isThrottled = false;
}, 16);
});
}
}

View File

@ -199,7 +199,7 @@ app.whenReady().then(async () => {
await authService.initialize();
//////// after_modelStateService ////////
modelStateService.initialize();
await modelStateService.initialize();
//////// after_modelStateService ////////
listenService.setupIpcHandlers();