fix dependency
This commit is contained in:
		
							parent
							
								
									86e903ec4b
								
							
						
					
					
						commit
						427be2a293
					
				
							
								
								
									
										1
									
								
								.npmrc
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								.npmrc
									
									
									
									
									
								
							@ -1,3 +1,2 @@
 | 
			
		||||
better-sqlite3:ignore-scripts=true
 | 
			
		||||
electron-deeplink:ignore-scripts=true
 | 
			
		||||
sharp:ignore-scripts=true
 | 
			
		||||
@ -10,6 +10,7 @@
 | 
			
		||||
        "package": "npm run build:renderer && electron-forge package",
 | 
			
		||||
        "make": "npm run build:renderer && electron-forge make",
 | 
			
		||||
        "build": "npm run build:renderer && electron-builder --config electron-builder.yml --publish never",
 | 
			
		||||
        "build:win": "npm run build:renderer && electron-builder --win --x64 --publish never", 
 | 
			
		||||
        "publish": "npm run build:renderer && electron-builder --config electron-builder.yml --publish always",
 | 
			
		||||
        "lint": "eslint --ext .ts,.tsx,.js .",
 | 
			
		||||
        "postinstall": "electron-builder install-app-deps",
 | 
			
		||||
@ -35,7 +36,7 @@
 | 
			
		||||
        "better-sqlite3": "^9.4.3",
 | 
			
		||||
        "cors": "^2.8.5",
 | 
			
		||||
        "dotenv": "^17.0.0",
 | 
			
		||||
        "electron-deeplink": "^1.0.10",
 | 
			
		||||
 | 
			
		||||
        "electron-squirrel-startup": "^1.0.1",
 | 
			
		||||
        "electron-store": "^8.2.0",
 | 
			
		||||
        "electron-updater": "^6.6.2",
 | 
			
		||||
@ -47,7 +48,6 @@
 | 
			
		||||
        "openai": "^4.70.0",
 | 
			
		||||
        "react-hot-toast": "^2.5.2",
 | 
			
		||||
        "sharp": "^0.34.2",
 | 
			
		||||
        "sqlite3": "^5.1.7",
 | 
			
		||||
        "validator": "^13.11.0",
 | 
			
		||||
        "wait-on": "^8.0.3",
 | 
			
		||||
        "ws": "^8.18.0"
 | 
			
		||||
@ -69,8 +69,6 @@
 | 
			
		||||
        "esbuild": "^0.25.5"
 | 
			
		||||
    },
 | 
			
		||||
    "optionalDependencies": {
 | 
			
		||||
        "@img/sharp-darwin-x64": "^0.34.2",
 | 
			
		||||
        "@img/sharp-libvips-darwin-x64": "^1.1.0",
 | 
			
		||||
        "electron-liquid-glass": "^1.0.1"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -2,40 +2,34 @@ const sqliteClient = require('../../services/sqliteClient');
 | 
			
		||||
 | 
			
		||||
function getPresets(uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = `
 | 
			
		||||
        SELECT * FROM prompt_presets 
 | 
			
		||||
        WHERE uid = ? OR is_default = 1 
 | 
			
		||||
        ORDER BY is_default DESC, title ASC
 | 
			
		||||
    `;
 | 
			
		||||
        db.all(query, [uid], (err, rows) => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        return db.prepare(query).all(uid);
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to get presets:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve(rows);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getPresetTemplates() {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = `
 | 
			
		||||
        SELECT * FROM prompt_presets 
 | 
			
		||||
        WHERE is_default = 1 
 | 
			
		||||
        ORDER BY title ASC
 | 
			
		||||
    `;
 | 
			
		||||
        db.all(query, [], (err, rows) => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        return db.prepare(query).all();
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to get preset templates:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve(rows);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function create({ uid, title, prompt }) {
 | 
			
		||||
@ -44,38 +38,42 @@ function create({ uid, title, prompt }) {
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `INSERT INTO prompt_presets (id, uid, title, prompt, is_default, created_at, sync_state) VALUES (?, ?, ?, ?, 0, ?, 'dirty')`;
 | 
			
		||||
    
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.run(query, [presetId, uid, title, prompt, now], function(err) {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve({ id: presetId });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    try {
 | 
			
		||||
        db.prepare(query).run(presetId, uid, title, prompt, now);
 | 
			
		||||
        return { id: presetId };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update(id, { title, prompt }, uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    const query = `UPDATE prompt_presets SET title = ?, prompt = ?, sync_state = 'dirty' WHERE id = ? AND uid = ? AND is_default = 0`;
 | 
			
		||||
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.run(query, [title, prompt, id, uid], function(err) {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else if (this.changes === 0) reject(new Error("Preset not found or permission denied."));
 | 
			
		||||
            else resolve({ changes: this.changes });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    try {
 | 
			
		||||
        const result = db.prepare(query).run(title, prompt, id, uid);
 | 
			
		||||
        if (result.changes === 0) {
 | 
			
		||||
            throw new Error("Preset not found or permission denied.");
 | 
			
		||||
        }
 | 
			
		||||
        return { changes: result.changes };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function del(id, uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    const query = `DELETE FROM prompt_presets WHERE id = ? AND uid = ? AND is_default = 0`;
 | 
			
		||||
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.run(query, [id, uid], function(err) {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else if (this.changes === 0) reject(new Error("Preset not found or permission denied."));
 | 
			
		||||
            else resolve({ changes: this.changes });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    try {
 | 
			
		||||
        const result = db.prepare(query).run(id, uid);
 | 
			
		||||
        if (result.changes === 0) {
 | 
			
		||||
            throw new Error("Preset not found or permission denied.");
 | 
			
		||||
        }
 | 
			
		||||
        return { changes: result.changes };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 | 
			
		||||
@ -2,124 +2,79 @@ const sqliteClient = require('../../services/sqliteClient');
 | 
			
		||||
 | 
			
		||||
function getById(id) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.get('SELECT * FROM sessions WHERE id = ?', [id], (err, row) => {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve(row);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    return db.prepare('SELECT * FROM sessions WHERE id = ?').get(id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function create(uid, type = 'ask') {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const sessionId = require('crypto').randomUUID();
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `INSERT INTO sessions (id, uid, title, session_type, started_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)`;
 | 
			
		||||
    
 | 
			
		||||
        db.run(query, [sessionId, uid, `Session @ ${new Date().toLocaleTimeString()}`, type, now, now], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                console.error('SQLite: Failed to create session:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
    try {
 | 
			
		||||
        db.prepare(query).run(sessionId, uid, `Session @ ${new Date().toLocaleTimeString()}`, type, now, now);
 | 
			
		||||
        console.log(`SQLite: Created session ${sessionId} for user ${uid} (type: ${type})`);
 | 
			
		||||
                resolve(sessionId);
 | 
			
		||||
        return sessionId;
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to create session:', err);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getAllByUserId(uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = "SELECT id, uid, title, session_type, started_at, ended_at, sync_state, updated_at FROM sessions WHERE uid = ? ORDER BY started_at DESC";
 | 
			
		||||
        db.all(query, [uid], (err, rows) => {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve(rows);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    return db.prepare(query).all(uid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateTitle(id, title) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.run('UPDATE sessions SET title = ? WHERE id = ?', [title, id], function(err) {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve({ changes: this.changes });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    const result = db.prepare('UPDATE sessions SET title = ? WHERE id = ?').run(title, id);
 | 
			
		||||
    return { changes: result.changes };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function deleteWithRelatedData(id) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.serialize(() => {
 | 
			
		||||
            db.run("BEGIN TRANSACTION;");
 | 
			
		||||
            const queries = [
 | 
			
		||||
                "DELETE FROM transcripts WHERE session_id = ?",
 | 
			
		||||
                "DELETE FROM ai_messages WHERE session_id = ?",
 | 
			
		||||
                "DELETE FROM summaries WHERE session_id = ?",
 | 
			
		||||
                "DELETE FROM sessions WHERE id = ?"
 | 
			
		||||
            ];
 | 
			
		||||
            queries.forEach(query => {
 | 
			
		||||
                db.run(query, [id], (err) => {
 | 
			
		||||
                    if (err) {
 | 
			
		||||
                        db.run("ROLLBACK;");
 | 
			
		||||
                        return reject(err);
 | 
			
		||||
    const transaction = db.transaction(() => {
 | 
			
		||||
        db.prepare("DELETE FROM transcripts WHERE session_id = ?").run(id);
 | 
			
		||||
        db.prepare("DELETE FROM ai_messages WHERE session_id = ?").run(id);
 | 
			
		||||
        db.prepare("DELETE FROM summaries WHERE session_id = ?").run(id);
 | 
			
		||||
        db.prepare("DELETE FROM sessions WHERE id = ?").run(id);
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        transaction();
 | 
			
		||||
        return { success: true };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            db.run("COMMIT;", (err) => {
 | 
			
		||||
                if (err) {
 | 
			
		||||
                    db.run("ROLLBACK;");
 | 
			
		||||
                    return reject(err);
 | 
			
		||||
                }
 | 
			
		||||
                resolve({ success: true });
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function end(id) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `UPDATE sessions SET ended_at = ?, updated_at = ? WHERE id = ?`;
 | 
			
		||||
        db.run(query, [now, now, id], function(err) {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve({ changes: this.changes });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    const result = db.prepare(query).run(now, now, id);
 | 
			
		||||
    return { changes: result.changes };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateType(id, type) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = 'UPDATE sessions SET session_type = ?, updated_at = ? WHERE id = ?';
 | 
			
		||||
        db.run(query, [type, now, id], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve({ changes: this.changes });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    const result = db.prepare(query).run(type, now, id);
 | 
			
		||||
    return { changes: result.changes };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function touch(id) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = 'UPDATE sessions SET updated_at = ? WHERE id = ?';
 | 
			
		||||
        db.run(query, [now, id], function(err) {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve({ changes: this.changes });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    const result = db.prepare(query).run(now, id);
 | 
			
		||||
    return { changes: result.changes };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getOrCreateActive(uid, requestedType = 'ask') {
 | 
			
		||||
function getOrCreateActive(uid, requestedType = 'ask') {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    
 | 
			
		||||
    // 1. Look for ANY active session for the user (ended_at IS NULL).
 | 
			
		||||
@ -131,12 +86,7 @@ async function getOrCreateActive(uid, requestedType = 'ask') {
 | 
			
		||||
        LIMIT 1
 | 
			
		||||
    `;
 | 
			
		||||
 | 
			
		||||
    const activeSession = await new Promise((resolve, reject) => {
 | 
			
		||||
        db.get(findQuery, [uid], (err, row) => {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve(row);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    const activeSession = db.prepare(findQuery).get(uid);
 | 
			
		||||
 | 
			
		||||
    if (activeSession) {
 | 
			
		||||
        // An active session exists.
 | 
			
		||||
@ -144,12 +94,12 @@ async function getOrCreateActive(uid, requestedType = 'ask') {
 | 
			
		||||
        
 | 
			
		||||
        // 2. Promotion Logic: If it's an 'ask' session and we need 'listen', promote it.
 | 
			
		||||
        if (activeSession.session_type === 'ask' && requestedType === 'listen') {
 | 
			
		||||
            await updateType(activeSession.id, 'listen');
 | 
			
		||||
            updateType(activeSession.id, 'listen');
 | 
			
		||||
            console.log(`[Repo] Promoted session ${activeSession.id} to 'listen' type.`);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 3. Touch the session and return its ID.
 | 
			
		||||
        await touch(activeSession.id);
 | 
			
		||||
        touch(activeSession.id);
 | 
			
		||||
        return activeSession.id;
 | 
			
		||||
    } else {
 | 
			
		||||
        // 4. No active session found, create a new one.
 | 
			
		||||
@ -160,19 +110,17 @@ async function getOrCreateActive(uid, requestedType = 'ask') {
 | 
			
		||||
 | 
			
		||||
function endAllActiveSessions() {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `UPDATE sessions SET ended_at = ?, updated_at = ? WHERE ended_at IS NULL`;
 | 
			
		||||
        db.run(query, [now, now], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        const result = db.prepare(query).run(now, now);
 | 
			
		||||
        console.log(`[Repo] Ended ${result.changes} active session(s).`);
 | 
			
		||||
        return { changes: result.changes };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to end all active sessions:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                console.log(`[Repo] Ended ${this.changes} active session(s).`);
 | 
			
		||||
                resolve({ changes: this.changes });
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 | 
			
		||||
@ -13,66 +13,44 @@ function findOrCreate(user) {
 | 
			
		||||
            email=excluded.email
 | 
			
		||||
    `;
 | 
			
		||||
    
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.run(query, [uid, displayName, email, now], (err) => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    try {
 | 
			
		||||
        db.prepare(query).run(uid, displayName, email, now);
 | 
			
		||||
        return getById(uid);
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to find or create user:', err);
 | 
			
		||||
                return reject(err);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
            getById(uid).then(resolve).catch(reject);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getById(uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.get('SELECT * FROM users WHERE uid = ?', [uid], (err, row) => {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve(row);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    return db.prepare('SELECT * FROM users WHERE uid = ?').get(uid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function saveApiKey(apiKey, uid, provider = 'openai') {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.run(
 | 
			
		||||
            'UPDATE users SET api_key = ?, provider = ? WHERE uid = ?',
 | 
			
		||||
            [apiKey, provider, uid],
 | 
			
		||||
            function(err) {
 | 
			
		||||
                if (err) {
 | 
			
		||||
                    console.error('SQLite: Failed to save API key:', err);
 | 
			
		||||
                    reject(err);
 | 
			
		||||
                } else {
 | 
			
		||||
    try {
 | 
			
		||||
        const result = db.prepare('UPDATE users SET api_key = ?, provider = ? WHERE uid = ?').run(apiKey, provider, uid);
 | 
			
		||||
        console.log(`SQLite: API key saved for user ${uid} with provider ${provider}.`);
 | 
			
		||||
                    resolve({ changes: this.changes });
 | 
			
		||||
        return { changes: result.changes };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to save API key:', err);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update({ uid, displayName }) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        db.run('UPDATE users SET display_name = ? WHERE uid = ?', [displayName, uid], function(err) {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve({ changes: this.changes });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    const result = db.prepare('UPDATE users SET display_name = ? WHERE uid = ?').run(displayName, uid);
 | 
			
		||||
    return { changes: result.changes };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function deleteById(uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const userSessions = db.prepare('SELECT id FROM sessions WHERE uid = ?').all(uid);
 | 
			
		||||
    const sessionIds = userSessions.map(s => s.id);
 | 
			
		||||
 | 
			
		||||
        db.serialize(() => {
 | 
			
		||||
            db.run("BEGIN TRANSACTION;");
 | 
			
		||||
            
 | 
			
		||||
            try {
 | 
			
		||||
    const transaction = db.transaction(() => {
 | 
			
		||||
        if (sessionIds.length > 0) {
 | 
			
		||||
            const placeholders = sessionIds.map(() => '?').join(',');
 | 
			
		||||
            db.prepare(`DELETE FROM transcripts WHERE session_id IN (${placeholders})`).run(...sessionIds);
 | 
			
		||||
@ -82,20 +60,14 @@ function deleteById(uid) {
 | 
			
		||||
        }
 | 
			
		||||
        db.prepare('DELETE FROM prompt_presets WHERE uid = ? AND is_default = 0').run(uid);
 | 
			
		||||
        db.prepare('DELETE FROM users WHERE uid = ?').run(uid);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
                db.run("COMMIT;", (err) => {
 | 
			
		||||
                    if (err) {
 | 
			
		||||
                        db.run("ROLLBACK;");
 | 
			
		||||
                        return reject(err);
 | 
			
		||||
                    }
 | 
			
		||||
                    resolve({ success: true });
 | 
			
		||||
                });
 | 
			
		||||
    try {
 | 
			
		||||
        transaction();
 | 
			
		||||
        return { success: true };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
                db.run("ROLLBACK;");
 | 
			
		||||
                reject(err);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 | 
			
		||||
@ -123,7 +123,7 @@ class AuthService {
 | 
			
		||||
        const userState = this.getCurrentUser();
 | 
			
		||||
        console.log('[AuthService] Broadcasting user state change:', userState);
 | 
			
		||||
        BrowserWindow.getAllWindows().forEach(win => {
 | 
			
		||||
            if (win && !win.isDestroyed()) {
 | 
			
		||||
            if (win && !win.isDestroyed() && win.webContents && !win.webContents.isDestroyed()) {
 | 
			
		||||
                win.webContents.send('user-state-changed', userState);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
const sqlite3 = require('sqlite3').verbose();
 | 
			
		||||
const Database = require('better-sqlite3');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const LATEST_SCHEMA = require('../config/schema');
 | 
			
		||||
 | 
			
		||||
@ -10,28 +10,20 @@ class SQLiteClient {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    connect(dbPath) {
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
        if (this.db) {
 | 
			
		||||
            console.log('[SQLiteClient] Already connected.');
 | 
			
		||||
                return resolve();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            this.dbPath = dbPath;
 | 
			
		||||
            this.db = new sqlite3.Database(this.dbPath, (err) => {
 | 
			
		||||
                if (err) {
 | 
			
		||||
                    console.error('[SQLiteClient] Could not connect to database', err);
 | 
			
		||||
                    return reject(err);
 | 
			
		||||
                }
 | 
			
		||||
            this.db = new Database(this.dbPath);
 | 
			
		||||
            this.db.pragma('journal_mode = WAL');
 | 
			
		||||
            console.log('[SQLiteClient] Connected successfully to:', this.dbPath);
 | 
			
		||||
                
 | 
			
		||||
                this.db.run('PRAGMA journal_mode = WAL;', (err) => {
 | 
			
		||||
                    if (err) {
 | 
			
		||||
                        return reject(err);
 | 
			
		||||
        } catch (err) {
 | 
			
		||||
            console.error('[SQLiteClient] Could not connect to database', err);
 | 
			
		||||
            throw err;
 | 
			
		||||
        }
 | 
			
		||||
                    resolve();
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getDb() {
 | 
			
		||||
@ -41,51 +33,39 @@ class SQLiteClient {
 | 
			
		||||
        return this.db;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async synchronizeSchema() {
 | 
			
		||||
    synchronizeSchema() {
 | 
			
		||||
        console.log('[DB Sync] Starting schema synchronization...');
 | 
			
		||||
        const tablesInDb = await this.getTablesFromDb();
 | 
			
		||||
        const tablesInDb = this.getTablesFromDb();
 | 
			
		||||
 | 
			
		||||
        for (const tableName of Object.keys(LATEST_SCHEMA)) {
 | 
			
		||||
            const tableSchema = LATEST_SCHEMA[tableName];
 | 
			
		||||
 | 
			
		||||
            if (!tablesInDb.includes(tableName)) {
 | 
			
		||||
                // Table doesn't exist, create it
 | 
			
		||||
                await this.createTable(tableName, tableSchema);
 | 
			
		||||
                this.createTable(tableName, tableSchema);
 | 
			
		||||
            } else {
 | 
			
		||||
                // Table exists, check for missing columns
 | 
			
		||||
                await this.updateTable(tableName, tableSchema);
 | 
			
		||||
                this.updateTable(tableName, tableSchema);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        console.log('[DB Sync] Schema synchronization finished.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async getTablesFromDb() {
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
            this.db.all("SELECT name FROM sqlite_master WHERE type='table'", (err, tables) => {
 | 
			
		||||
                if (err) return reject(err);
 | 
			
		||||
                resolve(tables.map(t => t.name));
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    getTablesFromDb() {
 | 
			
		||||
        const tables = this.db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all();
 | 
			
		||||
        return tables.map(t => t.name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async createTable(tableName, tableSchema) {
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
    createTable(tableName, tableSchema) {
 | 
			
		||||
        const columnDefs = tableSchema.columns.map(col => `"${col.name}" ${col.type}`).join(', ');
 | 
			
		||||
        const query = `CREATE TABLE IF NOT EXISTS "${tableName}" (${columnDefs})`;
 | 
			
		||||
 | 
			
		||||
        console.log(`[DB Sync] Creating table: ${tableName}`);
 | 
			
		||||
            this.db.run(query, (err) => {
 | 
			
		||||
                if (err) return reject(err);
 | 
			
		||||
                resolve();
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        this.db.prepare(query).run();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async updateTable(tableName, tableSchema) {
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
            this.db.all(`PRAGMA table_info("${tableName}")`, async (err, existingColumns) => {
 | 
			
		||||
                if (err) return reject(err);
 | 
			
		||||
 | 
			
		||||
    updateTable(tableName, tableSchema) {
 | 
			
		||||
        const existingColumns = this.db.prepare(`PRAGMA table_info("${tableName}")`).all();
 | 
			
		||||
        const existingColumnNames = existingColumns.map(c => c.name);
 | 
			
		||||
        const columnsToAdd = tableSchema.columns.filter(col => !existingColumnNames.includes(col.name));
 | 
			
		||||
 | 
			
		||||
@ -93,28 +73,16 @@ class SQLiteClient {
 | 
			
		||||
            console.log(`[DB Sync] Updating table: ${tableName}. Adding columns: ${columnsToAdd.map(c=>c.name).join(', ')}`);
 | 
			
		||||
            for (const column of columnsToAdd) {
 | 
			
		||||
                const addColumnQuery = `ALTER TABLE "${tableName}" ADD COLUMN "${column.name}" ${column.type}`;
 | 
			
		||||
                        try {
 | 
			
		||||
                            await this.runQuery(addColumnQuery);
 | 
			
		||||
                        } catch (alterErr) {
 | 
			
		||||
                            return reject(alterErr);
 | 
			
		||||
                this.db.prepare(addColumnQuery).run();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
                resolve();
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async runQuery(query, params = []) {
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
            this.db.run(query, params, function(err) {
 | 
			
		||||
                if (err) return reject(err);
 | 
			
		||||
                resolve(this);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    runQuery(query, params = []) {
 | 
			
		||||
        return this.db.prepare(query).run(params);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async cleanupEmptySessions() {
 | 
			
		||||
    cleanupEmptySessions() {
 | 
			
		||||
        console.log('[DB Cleanup] Checking for empty sessions...');
 | 
			
		||||
        const query = `
 | 
			
		||||
            SELECT s.id FROM sessions s
 | 
			
		||||
@ -124,16 +92,11 @@ class SQLiteClient {
 | 
			
		||||
            WHERE t.id IS NULL AND a.id IS NULL AND su.session_id IS NULL
 | 
			
		||||
        `;
 | 
			
		||||
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
            this.db.all(query, [], (err, rows) => {
 | 
			
		||||
                if (err) {
 | 
			
		||||
                    console.error('[DB Cleanup] Error finding empty sessions:', err);
 | 
			
		||||
                    return reject(err);
 | 
			
		||||
                }
 | 
			
		||||
        const rows = this.db.prepare(query).all();
 | 
			
		||||
 | 
			
		||||
        if (rows.length === 0) {
 | 
			
		||||
            console.log('[DB Cleanup] No empty sessions found.');
 | 
			
		||||
                    return resolve();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const idsToDelete = rows.map(r => r.id);
 | 
			
		||||
@ -141,36 +104,23 @@ class SQLiteClient {
 | 
			
		||||
        const deleteQuery = `DELETE FROM sessions WHERE id IN (${placeholders})`;
 | 
			
		||||
 | 
			
		||||
        console.log(`[DB Cleanup] Found ${idsToDelete.length} empty sessions. Deleting...`);
 | 
			
		||||
                this.db.run(deleteQuery, idsToDelete, function(deleteErr) {
 | 
			
		||||
                    if (deleteErr) {
 | 
			
		||||
                        console.error('[DB Cleanup] Error deleting empty sessions:', deleteErr);
 | 
			
		||||
                        return reject(deleteErr);
 | 
			
		||||
                    }
 | 
			
		||||
                    console.log(`[DB Cleanup] Successfully deleted ${this.changes} empty sessions.`);
 | 
			
		||||
                    resolve();
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        const result = this.db.prepare(deleteQuery).run(idsToDelete);
 | 
			
		||||
        console.log(`[DB Cleanup] Successfully deleted ${result.changes} empty sessions.`);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async initTables() {
 | 
			
		||||
        await this.synchronizeSchema();
 | 
			
		||||
        await this.initDefaultData();
 | 
			
		||||
    initTables() {
 | 
			
		||||
        this.synchronizeSchema();
 | 
			
		||||
        this.initDefaultData();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async initDefaultData() {
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
    initDefaultData() {
 | 
			
		||||
        const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
        const initUserQuery = `
 | 
			
		||||
            INSERT OR IGNORE INTO users (uid, display_name, email, created_at)
 | 
			
		||||
            VALUES (?, ?, ?, ?)
 | 
			
		||||
        `;
 | 
			
		||||
 | 
			
		||||
            this.db.run(initUserQuery, [this.defaultUserId, 'Default User', 'contact@pickle.com', now], (err) => {
 | 
			
		||||
                if (err) {
 | 
			
		||||
                    console.error('Failed to initialize default user:', err);
 | 
			
		||||
                    return reject(err);
 | 
			
		||||
                }
 | 
			
		||||
        this.db.prepare(initUserQuery).run(this.defaultUserId, 'Default User', 'contact@pickle.com', now);
 | 
			
		||||
 | 
			
		||||
        const defaultPresets = [
 | 
			
		||||
            ['school', 'School', 'You are a school and lecture assistant. Your goal is to help the user, a student, understand academic material and answer questions.\n\nWhenever a question appears on the user\'s screen or is asked aloud, you provide a direct, step-by-step answer, showing all necessary reasoning or calculations.\n\nIf the user is watching a lecture or working through new material, you offer concise explanations of key concepts and clarify definitions as they come up.', 1],
 | 
			
		||||
@ -189,27 +139,18 @@ class SQLiteClient {
 | 
			
		||||
            stmt.run(preset[0], this.defaultUserId, preset[1], preset[2], preset[3], now);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
                stmt.finalize((err) => {
 | 
			
		||||
                            if (err) {
 | 
			
		||||
                        console.error('Failed to finalize preset statement:', err);
 | 
			
		||||
                        return reject(err);
 | 
			
		||||
                    }
 | 
			
		||||
        console.log('Default data initialized.');
 | 
			
		||||
                    resolve();
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async markPermissionsAsCompleted() {
 | 
			
		||||
    markPermissionsAsCompleted() {
 | 
			
		||||
        return this.query(
 | 
			
		||||
            'INSERT OR REPLACE INTO system_settings (key, value) VALUES (?, ?)',
 | 
			
		||||
            ['permissions_completed', 'true']
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async checkPermissionsCompleted() {
 | 
			
		||||
        const result = await this.query(
 | 
			
		||||
    checkPermissionsCompleted() {
 | 
			
		||||
        const result = this.query(
 | 
			
		||||
            'SELECT value FROM system_settings WHERE key = ?',
 | 
			
		||||
            ['permissions_completed']
 | 
			
		||||
        );
 | 
			
		||||
@ -218,43 +159,32 @@ class SQLiteClient {
 | 
			
		||||
 | 
			
		||||
    close() {
 | 
			
		||||
        if (this.db) {
 | 
			
		||||
            this.db.close((err) => {
 | 
			
		||||
                if (err) {
 | 
			
		||||
                    console.error('SQLite connection close failed:', err);
 | 
			
		||||
                } else {
 | 
			
		||||
            try {
 | 
			
		||||
                this.db.close();
 | 
			
		||||
                console.log('SQLite connection closed.');
 | 
			
		||||
            } catch (err) {
 | 
			
		||||
                console.error('SQLite connection close failed:', err);
 | 
			
		||||
            }
 | 
			
		||||
            });
 | 
			
		||||
            this.db = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async query(sql, params = []) {
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
    query(sql, params = []) {
 | 
			
		||||
        if (!this.db) {
 | 
			
		||||
                return reject(new Error('Database not connected'));
 | 
			
		||||
            throw new Error('Database not connected');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            if (sql.toUpperCase().startsWith('SELECT')) {
 | 
			
		||||
                this.db.all(sql, params, (err, rows) => {
 | 
			
		||||
                    if (err) {
 | 
			
		||||
                return this.db.prepare(sql).all(params);
 | 
			
		||||
            } else {
 | 
			
		||||
                const result = this.db.prepare(sql).run(params);
 | 
			
		||||
                return { changes: result.changes, lastID: result.lastID };
 | 
			
		||||
            }
 | 
			
		||||
        } catch (err) {
 | 
			
		||||
            console.error('Query error:', err);
 | 
			
		||||
                        reject(err);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        resolve(rows);
 | 
			
		||||
            throw err;
 | 
			
		||||
        }
 | 
			
		||||
                });
 | 
			
		||||
            } else {
 | 
			
		||||
                this.db.run(sql, params, function(err) {
 | 
			
		||||
                    if (err) {
 | 
			
		||||
                        console.error('Query error:', err);
 | 
			
		||||
                        reject(err);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        resolve({ changes: this.changes, lastID: this.lastID });
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
const { BrowserWindow, globalShortcut, ipcMain, screen, app, shell, desktopCapturer } = require('electron');
 | 
			
		||||
const WindowLayoutManager = require('./windowLayoutManager');
 | 
			
		||||
const SmoothMovementManager = require('./smoothMovementManager');
 | 
			
		||||
const liquidGlass = require('electron-liquid-glass');
 | 
			
		||||
const path = require('node:path');
 | 
			
		||||
const fs = require('node:fs');
 | 
			
		||||
const os = require('os');
 | 
			
		||||
@ -15,6 +14,7 @@ const fetch = require('node-fetch');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ────────────────[ GLASS BYPASS ]─────────────── */
 | 
			
		||||
let liquidGlass;
 | 
			
		||||
const isLiquidGlassSupported = () => {
 | 
			
		||||
    if (process.platform !== 'darwin') {
 | 
			
		||||
        return false;
 | 
			
		||||
@ -23,7 +23,15 @@ const isLiquidGlassSupported = () => {
 | 
			
		||||
    // return majorVersion >= 25; // macOS 26+ (Darwin 25+)
 | 
			
		||||
    return majorVersion >= 26; // See you soon!
 | 
			
		||||
};
 | 
			
		||||
const shouldUseLiquidGlass = isLiquidGlassSupported();
 | 
			
		||||
let shouldUseLiquidGlass = isLiquidGlassSupported();
 | 
			
		||||
if (shouldUseLiquidGlass) {
 | 
			
		||||
    try {
 | 
			
		||||
        liquidGlass = require('electron-liquid-glass');
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        console.warn('Could not load optional dependency "electron-liquid-glass". The feature will be disabled.');
 | 
			
		||||
        shouldUseLiquidGlass = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/* ────────────────[ GLASS BYPASS ]─────────────── */
 | 
			
		||||
 | 
			
		||||
let isContentProtectionOn = true;
 | 
			
		||||
 | 
			
		||||
@ -2,31 +2,23 @@ const sqliteClient = require('../../../common/services/sqliteClient');
 | 
			
		||||
 | 
			
		||||
function addAiMessage({ sessionId, role, content, model = 'gpt-4.1' }) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const messageId = require('crypto').randomUUID();
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `INSERT INTO ai_messages (id, session_id, sent_at, role, content, model, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`;
 | 
			
		||||
        db.run(query, [messageId, sessionId, now, role, content, model, now], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        db.prepare(query).run(messageId, sessionId, now, role, content, model, now);
 | 
			
		||||
        return { id: messageId };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to add AI message:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
            else {
 | 
			
		||||
                resolve({ id: messageId });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getAllAiMessagesBySessionId(sessionId) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = "SELECT * FROM ai_messages WHERE session_id = ? ORDER BY sent_at ASC";
 | 
			
		||||
        db.all(query, [sessionId], (err, rows) => {
 | 
			
		||||
            if (err) reject(err);
 | 
			
		||||
            else resolve(rows);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    return db.prepare(query).all(sessionId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 | 
			
		||||
@ -2,33 +2,23 @@ const sqliteClient = require('../../../../common/services/sqliteClient');
 | 
			
		||||
 | 
			
		||||
function addTranscript({ sessionId, speaker, text }) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const transcriptId = require('crypto').randomUUID();
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `INSERT INTO transcripts (id, session_id, start_at, speaker, text, created_at) VALUES (?, ?, ?, ?, ?, ?)`;
 | 
			
		||||
        db.run(query, [transcriptId, sessionId, now, speaker, text, now], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        db.prepare(query).run(transcriptId, sessionId, now, speaker, text, now);
 | 
			
		||||
        return { id: transcriptId };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('Error adding transcript:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve({ id: transcriptId });
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getAllTranscriptsBySessionId(sessionId) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = "SELECT * FROM transcripts WHERE session_id = ? ORDER BY start_at ASC";
 | 
			
		||||
        db.all(query, [sessionId], (err, rows) => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve(rows);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    return db.prepare(query).all(sessionId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,6 @@ const sqliteClient = require('../../../../common/services/sqliteClient');
 | 
			
		||||
 | 
			
		||||
function saveSummary({ sessionId, tldr, text, bullet_json, action_json, model = 'gpt-4.1' }) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `
 | 
			
		||||
        INSERT INTO summaries (session_id, generated_at, model, text, tldr, bullet_json, action_json, updated_at) 
 | 
			
		||||
@ -16,29 +15,20 @@ function saveSummary({ sessionId, tldr, text, bullet_json, action_json, model =
 | 
			
		||||
            action_json=excluded.action_json,
 | 
			
		||||
            updated_at=excluded.updated_at
 | 
			
		||||
    `;
 | 
			
		||||
        db.run(query, [sessionId, now, model, text, tldr, bullet_json, action_json, now], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        const result = db.prepare(query).run(sessionId, now, model, text, tldr, bullet_json, action_json, now);
 | 
			
		||||
        return { changes: result.changes };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('Error saving summary:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve({ changes: this.changes });
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getSummaryBySessionId(sessionId) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = "SELECT * FROM summaries WHERE session_id = ?";
 | 
			
		||||
        db.get(query, [sessionId], (err, row) => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve(row || null);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    return db.prepare(query).get(sessionId) || null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 | 
			
		||||
@ -2,102 +2,92 @@ const sqliteClient = require('../../../common/services/sqliteClient');
 | 
			
		||||
 | 
			
		||||
function getPresets(uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = `
 | 
			
		||||
        SELECT * FROM prompt_presets 
 | 
			
		||||
        WHERE uid = ? OR is_default = 1 
 | 
			
		||||
        ORDER BY is_default DESC, title ASC
 | 
			
		||||
    `;
 | 
			
		||||
        db.all(query, [uid], (err, rows) => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        return db.prepare(query).all(uid) || [];
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to get presets:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve(rows || []);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getPresetTemplates() {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = `
 | 
			
		||||
        SELECT * FROM prompt_presets 
 | 
			
		||||
        WHERE is_default = 1 
 | 
			
		||||
        ORDER BY title ASC
 | 
			
		||||
    `;
 | 
			
		||||
        db.all(query, [], (err, rows) => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        return db.prepare(query).all() || [];
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to get preset templates:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve(rows || []);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createPreset({ uid, title, prompt }) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const id = require('crypto').randomUUID();
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `
 | 
			
		||||
        INSERT INTO prompt_presets (id, uid, title, prompt, is_default, created_at, sync_state)
 | 
			
		||||
        VALUES (?, ?, ?, ?, 0, ?, 'dirty')
 | 
			
		||||
    `;
 | 
			
		||||
        db.run(query, [id, uid, title, prompt, now], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        db.prepare(query).run(id, uid, title, prompt, now);
 | 
			
		||||
        return { id };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to create preset:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve({ id });
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updatePreset(id, { title, prompt }, uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    const query = `
 | 
			
		||||
        UPDATE prompt_presets 
 | 
			
		||||
        SET title = ?, prompt = ?, sync_state = 'dirty', updated_at = ?
 | 
			
		||||
        WHERE id = ? AND uid = ? AND is_default = 0
 | 
			
		||||
    `;
 | 
			
		||||
        db.run(query, [title, prompt, now, id, uid], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                console.error('SQLite: Failed to update preset:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else if (this.changes === 0) {
 | 
			
		||||
                reject(new Error('Preset not found, is default, or permission denied'));
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve({ changes: this.changes });
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        const result = db.prepare(query).run(title, prompt, now, id, uid);
 | 
			
		||||
        if (result.changes === 0) {
 | 
			
		||||
            throw new Error('Preset not found, is default, or permission denied');
 | 
			
		||||
        }
 | 
			
		||||
        return { changes: result.changes };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to update preset:', err);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function deletePreset(id, uid) {
 | 
			
		||||
    const db = sqliteClient.getDb();
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
    const query = `
 | 
			
		||||
        DELETE FROM prompt_presets 
 | 
			
		||||
        WHERE id = ? AND uid = ? AND is_default = 0
 | 
			
		||||
    `;
 | 
			
		||||
        db.run(query, [id, uid], function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                console.error('SQLite: Failed to delete preset:', err);
 | 
			
		||||
                reject(err);
 | 
			
		||||
            } else if (this.changes === 0) {
 | 
			
		||||
                reject(new Error('Preset not found, is default, or permission denied'));
 | 
			
		||||
            } else {
 | 
			
		||||
                resolve({ changes: this.changes });
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
        const result = db.prepare(query).run(id, uid);
 | 
			
		||||
        if (result.changes === 0) {
 | 
			
		||||
            throw new Error('Preset not found, is default, or permission denied');
 | 
			
		||||
        }
 | 
			
		||||
        return { changes: result.changes };
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        console.error('SQLite: Failed to delete preset:', err);
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										203
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								src/index.js
									
									
									
									
									
								
							@ -18,7 +18,6 @@ const { initializeFirebase } = require('./common/services/firebaseClient');
 | 
			
		||||
const databaseInitializer = require('./common/services/databaseInitializer');
 | 
			
		||||
const authService = require('./common/services/authService');
 | 
			
		||||
const path = require('node:path');
 | 
			
		||||
const { Deeplink } = require('electron-deeplink');
 | 
			
		||||
const express = require('express');
 | 
			
		||||
const fetch = require('node-fetch');
 | 
			
		||||
const { autoUpdater } = require('electron-updater');
 | 
			
		||||
@ -33,72 +32,86 @@ let WEB_PORT = 3000;
 | 
			
		||||
const listenService = new ListenService();
 | 
			
		||||
// Make listenService globally accessible so other modules (e.g., windowManager, askService) can reuse the same instance
 | 
			
		||||
global.listenService = listenService;
 | 
			
		||||
let deeplink = null; // Initialize as null
 | 
			
		||||
let pendingDeepLinkUrl = null; // Store any deep link that arrives before initialization
 | 
			
		||||
 | 
			
		||||
function createMainWindows() {
 | 
			
		||||
    createWindows();
 | 
			
		||||
// Native deep link handling - cross-platform compatible
 | 
			
		||||
let pendingDeepLinkUrl = null;
 | 
			
		||||
 | 
			
		||||
    const { windowPool } = require('./electron/windowManager');
 | 
			
		||||
    const headerWindow = windowPool.get('header');
 | 
			
		||||
function setupProtocolHandling() {
 | 
			
		||||
    // Protocol registration - must be done before app is ready
 | 
			
		||||
    if (!app.isDefaultProtocolClient('pickleglass')) {
 | 
			
		||||
        app.setAsDefaultProtocolClient('pickleglass');
 | 
			
		||||
        console.log('[Protocol] Set as default protocol client for pickleglass://');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Initialize deeplink after windows are created
 | 
			
		||||
    if (!deeplink && headerWindow) {
 | 
			
		||||
        try {
 | 
			
		||||
            deeplink = new Deeplink({
 | 
			
		||||
                app,
 | 
			
		||||
                mainWindow: headerWindow,     
 | 
			
		||||
                protocol: 'pickleglass',
 | 
			
		||||
                isDev: !app.isPackaged,
 | 
			
		||||
                debugLogging: true
 | 
			
		||||
    // Handle protocol URLs on Windows/Linux
 | 
			
		||||
    app.on('second-instance', (event, commandLine, workingDirectory) => {
 | 
			
		||||
        // Focus existing window first
 | 
			
		||||
        focusMainWindow();
 | 
			
		||||
        
 | 
			
		||||
        // Look for protocol URL in command line arguments
 | 
			
		||||
        const protocolUrl = commandLine.find(arg => arg.startsWith('pickleglass://'));
 | 
			
		||||
        if (protocolUrl) {
 | 
			
		||||
            console.log('[Protocol] Received URL from second instance:', protocolUrl);
 | 
			
		||||
            handleCustomUrl(protocolUrl);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
            deeplink.on('received', (url) => {
 | 
			
		||||
                console.log('[deeplink] received:', url);
 | 
			
		||||
    // Handle protocol URLs on macOS
 | 
			
		||||
    app.on('open-url', (event, url) => {
 | 
			
		||||
        event.preventDefault();
 | 
			
		||||
        console.log('[Protocol] Received URL via open-url:', url);
 | 
			
		||||
        
 | 
			
		||||
        if (!url || !url.startsWith('pickleglass://')) {
 | 
			
		||||
            console.warn('[Protocol] Invalid URL format:', url);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (app.isReady()) {
 | 
			
		||||
            handleCustomUrl(url);
 | 
			
		||||
        } else {
 | 
			
		||||
            pendingDeepLinkUrl = url;
 | 
			
		||||
            console.log('[Protocol] App not ready, storing URL for later');
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
            
 | 
			
		||||
            console.log('[deeplink] Initialized with main window');
 | 
			
		||||
            
 | 
			
		||||
            // Handle any pending deep link
 | 
			
		||||
            if (pendingDeepLinkUrl) {
 | 
			
		||||
                console.log('[deeplink] Processing pending deep link:', pendingDeepLinkUrl);
 | 
			
		||||
                handleCustomUrl(pendingDeepLinkUrl);
 | 
			
		||||
                pendingDeepLinkUrl = null;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.error('[deeplink] Failed to initialize deep link:', error);
 | 
			
		||||
            deeplink = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function focusMainWindow() {
 | 
			
		||||
    const { windowPool } = require('./electron/windowManager');
 | 
			
		||||
    if (windowPool) {
 | 
			
		||||
        const header = windowPool.get('header');
 | 
			
		||||
        if (header && !header.isDestroyed()) {
 | 
			
		||||
            if (header.isMinimized()) header.restore();
 | 
			
		||||
            header.focus();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Fallback: focus any available window
 | 
			
		||||
    const windows = BrowserWindow.getAllWindows();
 | 
			
		||||
    if (windows.length > 0) {
 | 
			
		||||
        const mainWindow = windows[0];
 | 
			
		||||
        if (!mainWindow.isDestroyed()) {
 | 
			
		||||
            if (mainWindow.isMinimized()) mainWindow.restore();
 | 
			
		||||
            mainWindow.focus();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Setup protocol handling before app.whenReady()
 | 
			
		||||
setupProtocolHandling();
 | 
			
		||||
 | 
			
		||||
app.whenReady().then(async () => {
 | 
			
		||||
    // Single instance lock - must be first
 | 
			
		||||
    const gotTheLock = app.requestSingleInstanceLock();
 | 
			
		||||
    if (!gotTheLock) {
 | 
			
		||||
        app.quit();
 | 
			
		||||
        return;
 | 
			
		||||
    } else {
 | 
			
		||||
        app.on('second-instance', (event, commandLine, workingDirectory) => {
 | 
			
		||||
            const { windowPool } = require('./electron/windowManager');
 | 
			
		||||
            if (windowPool) {
 | 
			
		||||
                const header = windowPool.get('header');
 | 
			
		||||
                if (header) {
 | 
			
		||||
                    if (header.isMinimized()) header.restore();
 | 
			
		||||
                    header.focus();
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            const windows = BrowserWindow.getAllWindows();
 | 
			
		||||
            if (windows.length > 0) {
 | 
			
		||||
                const mainWindow = windows[0];
 | 
			
		||||
                if (mainWindow.isMinimized()) mainWindow.restore();
 | 
			
		||||
                mainWindow.focus();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Initialize core services
 | 
			
		||||
    initializeFirebase();
 | 
			
		||||
    
 | 
			
		||||
    databaseInitializer.initialize()
 | 
			
		||||
@ -121,9 +134,16 @@ app.whenReady().then(async () => {
 | 
			
		||||
    WEB_PORT = await startWebStack();
 | 
			
		||||
    console.log('Web front-end listening on', WEB_PORT);
 | 
			
		||||
    
 | 
			
		||||
    createMainWindows();
 | 
			
		||||
    createWindows();
 | 
			
		||||
 | 
			
		||||
    initAutoUpdater();
 | 
			
		||||
 | 
			
		||||
    // Process any pending deep link after everything is initialized
 | 
			
		||||
    if (pendingDeepLinkUrl) {
 | 
			
		||||
        console.log('[Protocol] Processing pending URL:', pendingDeepLinkUrl);
 | 
			
		||||
        handleCustomUrl(pendingDeepLinkUrl);
 | 
			
		||||
        pendingDeepLinkUrl = null;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.on('window-all-closed', () => {
 | 
			
		||||
@ -142,34 +162,17 @@ app.on('before-quit', async () => {
 | 
			
		||||
 | 
			
		||||
app.on('activate', () => {
 | 
			
		||||
    if (BrowserWindow.getAllWindows().length === 0) {
 | 
			
		||||
        createMainWindows();
 | 
			
		||||
        createWindows();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Add macOS native deep link handling as fallback
 | 
			
		||||
app.on('open-url', (event, url) => {
 | 
			
		||||
    event.preventDefault();
 | 
			
		||||
    console.log('[app] open-url received:', url);
 | 
			
		||||
    
 | 
			
		||||
    if (!deeplink) {
 | 
			
		||||
        // Store the URL if deeplink isn't ready yet
 | 
			
		||||
        pendingDeepLinkUrl = url;
 | 
			
		||||
        console.log('[app] Deep link stored for later processing');
 | 
			
		||||
    } else {
 | 
			
		||||
        handleCustomUrl(url);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Ensure app can handle the protocol
 | 
			
		||||
app.setAsDefaultProtocolClient('pickleglass');
 | 
			
		||||
 | 
			
		||||
function setupGeneralIpcHandlers() {
 | 
			
		||||
    const userRepository = require('./common/repositories/user');
 | 
			
		||||
    const presetRepository = require('./common/repositories/preset');
 | 
			
		||||
 | 
			
		||||
    ipcMain.handle('save-api-key', async (event, apiKey) => {
 | 
			
		||||
    ipcMain.handle('save-api-key', (event, apiKey) => {
 | 
			
		||||
        try {
 | 
			
		||||
            await userRepository.saveApiKey(apiKey, authService.getCurrentUserId());
 | 
			
		||||
            userRepository.saveApiKey(apiKey, authService.getCurrentUserId());
 | 
			
		||||
            BrowserWindow.getAllWindows().forEach(win => {
 | 
			
		||||
                win.webContents.send('api-key-updated');
 | 
			
		||||
            });
 | 
			
		||||
@ -180,12 +183,12 @@ function setupGeneralIpcHandlers() {
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    ipcMain.handle('get-user-presets', async () => {
 | 
			
		||||
        return await presetRepository.getPresets(authService.getCurrentUserId());
 | 
			
		||||
    ipcMain.handle('get-user-presets', () => {
 | 
			
		||||
        return presetRepository.getPresets(authService.getCurrentUserId());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    ipcMain.handle('get-preset-templates', async () => {
 | 
			
		||||
        return await presetRepository.getPresetTemplates();
 | 
			
		||||
    ipcMain.handle('get-preset-templates', () => {
 | 
			
		||||
        return presetRepository.getPresetTemplates();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    ipcMain.handle('start-firebase-auth', async () => {
 | 
			
		||||
@ -204,7 +207,7 @@ function setupGeneralIpcHandlers() {
 | 
			
		||||
        return process.env.pickleglass_WEB_URL || 'http://localhost:3000';
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    ipcMain.handle('get-current-user', async () => {
 | 
			
		||||
    ipcMain.handle('get-current-user', () => {
 | 
			
		||||
        return authService.getCurrentUser();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@ -220,72 +223,72 @@ function setupWebDataHandlers() {
 | 
			
		||||
    const userRepository = require('./common/repositories/user');
 | 
			
		||||
    const presetRepository = require('./common/repositories/preset');
 | 
			
		||||
 | 
			
		||||
    const handleRequest = async (channel, responseChannel, payload) => {
 | 
			
		||||
    const handleRequest = (channel, responseChannel, payload) => {
 | 
			
		||||
        let result;
 | 
			
		||||
        const currentUserId = authService.getCurrentUserId();
 | 
			
		||||
        try {
 | 
			
		||||
            switch (channel) {
 | 
			
		||||
                // SESSION
 | 
			
		||||
                case 'get-sessions':
 | 
			
		||||
                    result = await sessionRepository.getAllByUserId(currentUserId);
 | 
			
		||||
                    result = sessionRepository.getAllByUserId(currentUserId);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'get-session-details':
 | 
			
		||||
                    const session = await sessionRepository.getById(payload);
 | 
			
		||||
                    const session = sessionRepository.getById(payload);
 | 
			
		||||
                    if (!session) {
 | 
			
		||||
                        result = null;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    const transcripts = await sttRepository.getAllTranscriptsBySessionId(payload);
 | 
			
		||||
                    const ai_messages = await askRepository.getAllAiMessagesBySessionId(payload);
 | 
			
		||||
                    const summary = await summaryRepository.getSummaryBySessionId(payload);
 | 
			
		||||
                    const transcripts = sttRepository.getAllTranscriptsBySessionId(payload);
 | 
			
		||||
                    const ai_messages = askRepository.getAllAiMessagesBySessionId(payload);
 | 
			
		||||
                    const summary = summaryRepository.getSummaryBySessionId(payload);
 | 
			
		||||
                    result = { session, transcripts, ai_messages, summary };
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'delete-session':
 | 
			
		||||
                    result = await sessionRepository.deleteWithRelatedData(payload);
 | 
			
		||||
                    result = sessionRepository.deleteWithRelatedData(payload);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'create-session':
 | 
			
		||||
                    const id = await sessionRepository.create(currentUserId, 'ask');
 | 
			
		||||
                    const id = sessionRepository.create(currentUserId, 'ask');
 | 
			
		||||
                    if (payload.title) {
 | 
			
		||||
                        await sessionRepository.updateTitle(id, payload.title);
 | 
			
		||||
                        sessionRepository.updateTitle(id, payload.title);
 | 
			
		||||
                    }
 | 
			
		||||
                    result = { id };
 | 
			
		||||
                    break;
 | 
			
		||||
                
 | 
			
		||||
                // USER
 | 
			
		||||
                case 'get-user-profile':
 | 
			
		||||
                    result = await userRepository.getById(currentUserId);
 | 
			
		||||
                    result = userRepository.getById(currentUserId);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'update-user-profile':
 | 
			
		||||
                    result = await userRepository.update({ uid: currentUserId, ...payload });
 | 
			
		||||
                    result = userRepository.update({ uid: currentUserId, ...payload });
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'find-or-create-user':
 | 
			
		||||
                    result = await userRepository.findOrCreate(payload);
 | 
			
		||||
                    result = userRepository.findOrCreate(payload);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'save-api-key':
 | 
			
		||||
                    result = await userRepository.saveApiKey(payload, currentUserId);
 | 
			
		||||
                    result = userRepository.saveApiKey(payload, currentUserId);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'check-api-key-status':
 | 
			
		||||
                    const user = await userRepository.getById(currentUserId);
 | 
			
		||||
                    const user = userRepository.getById(currentUserId);
 | 
			
		||||
                    result = { hasApiKey: !!user?.api_key && user.api_key.length > 0 };
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'delete-account':
 | 
			
		||||
                    result = await userRepository.deleteById(currentUserId);
 | 
			
		||||
                    result = userRepository.deleteById(currentUserId);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                // PRESET
 | 
			
		||||
                case 'get-presets':
 | 
			
		||||
                    result = await presetRepository.getPresets(currentUserId);
 | 
			
		||||
                    result = presetRepository.getPresets(currentUserId);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'create-preset':
 | 
			
		||||
                    result = await presetRepository.create({ ...payload, uid: currentUserId });
 | 
			
		||||
                    result = presetRepository.create({ ...payload, uid: currentUserId });
 | 
			
		||||
                    settingsService.notifyPresetUpdate('created', result.id, payload.title);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'update-preset':
 | 
			
		||||
                    result = await presetRepository.update(payload.id, payload.data, currentUserId);
 | 
			
		||||
                    result = presetRepository.update(payload.id, payload.data, currentUserId);
 | 
			
		||||
                    settingsService.notifyPresetUpdate('updated', payload.id, payload.data.title);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'delete-preset':
 | 
			
		||||
                    result = await presetRepository.delete(payload, currentUserId);
 | 
			
		||||
                    result = presetRepository.delete(payload, currentUserId);
 | 
			
		||||
                    settingsService.notifyPresetUpdate('deleted', payload);
 | 
			
		||||
                    break;
 | 
			
		||||
                
 | 
			
		||||
@ -295,13 +298,13 @@ function setupWebDataHandlers() {
 | 
			
		||||
                    const batchResult = {};
 | 
			
		||||
            
 | 
			
		||||
                    if (includes.includes('profile')) {
 | 
			
		||||
                        batchResult.profile = await userRepository.getById(currentUserId);
 | 
			
		||||
                        batchResult.profile = userRepository.getById(currentUserId);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (includes.includes('presets')) {
 | 
			
		||||
                        batchResult.presets = await presetRepository.getPresets(currentUserId);
 | 
			
		||||
                        batchResult.presets = presetRepository.getPresets(currentUserId);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (includes.includes('sessions')) {
 | 
			
		||||
                        batchResult.sessions = await sessionRepository.getAllByUserId(currentUserId);
 | 
			
		||||
                        batchResult.sessions = sessionRepository.getAllByUserId(currentUserId);
 | 
			
		||||
                    }
 | 
			
		||||
                    result = batchResult;
 | 
			
		||||
                    break;
 | 
			
		||||
@ -392,7 +395,7 @@ async function handleFirebaseAuthCallback(params) {
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // 1. Sync user data to local DB
 | 
			
		||||
        await userRepository.findOrCreate(firebaseUser);
 | 
			
		||||
        userRepository.findOrCreate(firebaseUser);
 | 
			
		||||
        console.log('[Auth] User data synced with local DB.');
 | 
			
		||||
 | 
			
		||||
        // 2. Sign in using the authService in the main process
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user