minor fix
This commit is contained in:
parent
2a1edb6ed8
commit
3031d0d288
@ -43,9 +43,10 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
window.location.href = deepLinkUrl
|
window.location.href = deepLinkUrl
|
||||||
|
|
||||||
setTimeout(() => {
|
// Maybe we don't need this
|
||||||
alert('Login completed. Please return to Pickle Glass app.')
|
// setTimeout(() => {
|
||||||
}, 1000)
|
// alert('Login completed. Please return to Pickle Glass app.')
|
||||||
|
// }, 1000)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Deep link processing failed:', error)
|
console.error('❌ Deep link processing failed:', error)
|
||||||
|
@ -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();
|
|
@ -2,7 +2,7 @@ const Store = require('electron-store');
|
|||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
const { ipcMain, webContents } = require('electron');
|
const { ipcMain, webContents } = require('electron');
|
||||||
const { PROVIDERS } = require('../ai/factory');
|
const { PROVIDERS } = require('../ai/factory');
|
||||||
const cryptoService = require('./cryptoService');
|
const encryptionService = require('./encryptionService');
|
||||||
|
|
||||||
class ModelStateService {
|
class ModelStateService {
|
||||||
constructor(authService) {
|
constructor(authService) {
|
||||||
@ -11,8 +11,8 @@ class ModelStateService {
|
|||||||
this.state = {};
|
this.state = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
async initialize() {
|
||||||
this._loadStateForCurrentUser();
|
await this._loadStateForCurrentUser();
|
||||||
|
|
||||||
this.setupIpcHandlers();
|
this.setupIpcHandlers();
|
||||||
console.log('[ModelStateService] Initialized.');
|
console.log('[ModelStateService] Initialized.');
|
||||||
@ -64,8 +64,12 @@ class ModelStateService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_loadStateForCurrentUser() {
|
async _loadStateForCurrentUser() {
|
||||||
const userId = this.authService.getCurrentUserId();
|
const userId = this.authService.getCurrentUserId();
|
||||||
|
|
||||||
|
// Initialize encryption service for current user
|
||||||
|
await encryptionService.initializeKey(userId);
|
||||||
|
|
||||||
const initialApiKeys = Object.keys(PROVIDERS).reduce((acc, key) => {
|
const initialApiKeys = Object.keys(PROVIDERS).reduce((acc, key) => {
|
||||||
acc[key] = null;
|
acc[key] = null;
|
||||||
return acc;
|
return acc;
|
||||||
@ -83,7 +87,7 @@ class ModelStateService {
|
|||||||
this.state.apiKeys[p] = null;
|
this.state.apiKeys[p] = null;
|
||||||
} else if (this.state.apiKeys[p] && p !== 'ollama' && p !== 'whisper') {
|
} else if (this.state.apiKeys[p] && p !== 'ollama' && p !== 'whisper') {
|
||||||
try {
|
try {
|
||||||
this.state.apiKeys[p] = cryptoService.decrypt(this.state.apiKeys[p]);
|
this.state.apiKeys[p] = encryptionService.decrypt(this.state.apiKeys[p]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[ModelStateService] Failed to decrypt API key for ${p}, resetting`);
|
console.error(`[ModelStateService] Failed to decrypt API key for ${p}, resetting`);
|
||||||
this.state.apiKeys[p] = null;
|
this.state.apiKeys[p] = null;
|
||||||
@ -107,7 +111,7 @@ class ModelStateService {
|
|||||||
for (const [provider, key] of Object.entries(stateToSave.apiKeys)) {
|
for (const [provider, key] of Object.entries(stateToSave.apiKeys)) {
|
||||||
if (key && provider !== 'ollama' && provider !== 'whisper') {
|
if (key && provider !== 'ollama' && provider !== 'whisper') {
|
||||||
try {
|
try {
|
||||||
stateToSave.apiKeys[provider] = cryptoService.encrypt(key);
|
stateToSave.apiKeys[provider] = encryptionService.encrypt(key);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[ModelStateService] Failed to encrypt API key for ${provider}`);
|
console.error(`[ModelStateService] Failed to encrypt API key for ${provider}`);
|
||||||
stateToSave.apiKeys[provider] = null;
|
stateToSave.apiKeys[provider] = null;
|
||||||
|
@ -415,7 +415,7 @@ export class AskView extends LitElement {
|
|||||||
background: rgba(0, 0, 0, 0.1);
|
background: rgba(0, 0, 0, 0.1);
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
flex-shrink: 0;
|
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;
|
transform-origin: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,6 +541,7 @@ export class AskView extends LitElement {
|
|||||||
this.handleStreamChunk = this.handleStreamChunk.bind(this);
|
this.handleStreamChunk = this.handleStreamChunk.bind(this);
|
||||||
this.handleStreamEnd = this.handleStreamEnd.bind(this);
|
this.handleStreamEnd = this.handleStreamEnd.bind(this);
|
||||||
this.handleSendText = this.handleSendText.bind(this);
|
this.handleSendText = this.handleSendText.bind(this);
|
||||||
|
this.handleGlobalSendRequest = this.handleGlobalSendRequest.bind(this);
|
||||||
this.handleTextKeydown = this.handleTextKeydown.bind(this);
|
this.handleTextKeydown = this.handleTextKeydown.bind(this);
|
||||||
this.closeResponsePanel = this.closeResponsePanel.bind(this);
|
this.closeResponsePanel = this.closeResponsePanel.bind(this);
|
||||||
this.handleCopy = this.handleCopy.bind(this);
|
this.handleCopy = this.handleCopy.bind(this);
|
||||||
@ -556,7 +557,6 @@ export class AskView extends LitElement {
|
|||||||
this.loadLibraries();
|
this.loadLibraries();
|
||||||
|
|
||||||
// --- Resize helpers ---
|
// --- Resize helpers ---
|
||||||
this.adjustHeightThrottle = null;
|
|
||||||
this.isThrottled = false;
|
this.isThrottled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1220,6 +1220,14 @@ export class AskView extends LitElement {
|
|||||||
|
|
||||||
handleGlobalSendRequest() {
|
handleGlobalSendRequest() {
|
||||||
const textInput = this.shadowRoot?.getElementById('textInput');
|
const textInput = this.shadowRoot?.getElementById('textInput');
|
||||||
|
|
||||||
|
if (!this.showTextInput) {
|
||||||
|
this.showTextInput = true;
|
||||||
|
this.requestUpdate();
|
||||||
|
this.focusTextInput();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!textInput) return;
|
if (!textInput) return;
|
||||||
|
|
||||||
textInput.focus();
|
textInput.focus();
|
||||||
@ -1349,12 +1357,11 @@ export class AskView extends LitElement {
|
|||||||
adjustWindowHeightThrottled() {
|
adjustWindowHeightThrottled() {
|
||||||
if (this.isThrottled) return;
|
if (this.isThrottled) return;
|
||||||
|
|
||||||
this.adjustWindowHeight();
|
|
||||||
this.isThrottled = true;
|
this.isThrottled = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
this.adjustHeightThrottle = setTimeout(() => {
|
this.adjustWindowHeight();
|
||||||
this.isThrottled = false;
|
this.isThrottled = false;
|
||||||
}, 16);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ app.whenReady().then(async () => {
|
|||||||
await authService.initialize();
|
await authService.initialize();
|
||||||
|
|
||||||
//////// after_modelStateService ////////
|
//////// after_modelStateService ////////
|
||||||
modelStateService.initialize();
|
await modelStateService.initialize();
|
||||||
//////// after_modelStateService ////////
|
//////// after_modelStateService ////////
|
||||||
|
|
||||||
listenService.setupIpcHandlers();
|
listenService.setupIpcHandlers();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user