feat: Add a large collection of emoji and other frontend assets, including a sound file, and a backend package.json.
This commit is contained in:
@@ -15,13 +15,15 @@ function createWindow() {
|
||||
}
|
||||
});
|
||||
|
||||
const startUrl = process.env.ELECTRON_START_URL || `file://${path.join(__dirname, '../dist/index.html')}`;
|
||||
const isDev = process.env.npm_lifecycle_event === 'electron:dev';
|
||||
|
||||
if (process.env.npm_lifecycle_event === 'electron:dev') {
|
||||
if (isDev) {
|
||||
win.loadURL('http://localhost:5173');
|
||||
win.webContents.openDevTools();
|
||||
} else {
|
||||
win.loadURL(startUrl);
|
||||
// Production: Load the built file
|
||||
// dist-react is in the same directory as main.cjs
|
||||
win.loadFile(path.join(__dirname, 'dist-react', 'index.html'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +33,35 @@ app.whenReady().then(() => {
|
||||
// Helper to fetch metadata (Zero-Knowledge: Client fetches previews)
|
||||
ipcMain.handle('fetch-metadata', async (event, url) => {
|
||||
return new Promise((resolve) => {
|
||||
// Check for direct video links to avoid downloading large files
|
||||
const videoExtensions = ['.mp4', '.webm', '.ogg', '.mov'];
|
||||
const imageExtensions = ['.gif', '.png', '.jpg', '.jpeg', '.webp'];
|
||||
const lowerUrl = url.toLowerCase();
|
||||
|
||||
if (videoExtensions.some(ext => lowerUrl.endsWith(ext))) {
|
||||
const filename = url.split('/').pop();
|
||||
resolve({
|
||||
title: filename,
|
||||
siteName: new URL(url).hostname,
|
||||
video: url,
|
||||
image: null, // No thumbnail for now unless we generate one
|
||||
description: 'Video File'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (imageExtensions.some(ext => lowerUrl.endsWith(ext))) {
|
||||
const filename = url.split('/').pop();
|
||||
resolve({
|
||||
title: filename,
|
||||
siteName: new URL(url).hostname,
|
||||
video: null,
|
||||
image: url, // Direct image/gif
|
||||
description: 'Image File'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const client = url.startsWith('https') ? https : http;
|
||||
const req = client.get(url, (res) => {
|
||||
let data = '';
|
||||
@@ -69,6 +100,21 @@ app.whenReady().then(() => {
|
||||
await shell.openExternal(url);
|
||||
});
|
||||
|
||||
ipcMain.handle('get-screen-sources', async () => {
|
||||
const { desktopCapturer } = require('electron');
|
||||
const sources = await desktopCapturer.getSources({
|
||||
types: ['window', 'screen'],
|
||||
thumbnailSize: { width: 450, height: 250, borderRadius: '8px' },
|
||||
fetchWindowIcons: true
|
||||
});
|
||||
return sources.map(source => ({
|
||||
id: source.id,
|
||||
name: source.name,
|
||||
thumbnail: source.thumbnail.toDataURL(),
|
||||
appIcon: source.appIcon ? source.appIcon.toDataURL() : null
|
||||
}));
|
||||
});
|
||||
|
||||
// Crypto Handlers
|
||||
const crypto = require('crypto');
|
||||
|
||||
@@ -132,6 +178,25 @@ app.whenReady().then(() => {
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.handle('public-encrypt', (event, publicKeyPem, data) => {
|
||||
// data can be string or buffer. Returns hex.
|
||||
const buffer = Buffer.from(data);
|
||||
return crypto.publicEncrypt({
|
||||
key: publicKeyPem,
|
||||
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
||||
oaepHash: "sha256",
|
||||
}, buffer).toString('hex');
|
||||
});
|
||||
|
||||
ipcMain.handle('private-decrypt', (event, privateKeyPem, encryptedHex) => {
|
||||
const buffer = Buffer.from(encryptedHex, 'hex');
|
||||
return crypto.privateDecrypt({
|
||||
key: privateKeyPem,
|
||||
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
||||
oaepHash: "sha256",
|
||||
}, buffer).toString(); // Assuming utf8 string output
|
||||
});
|
||||
|
||||
ipcMain.handle('encrypt-data', (event, plaintext, key) => {
|
||||
console.log('encrypt-data called with:', {
|
||||
plaintextType: typeof plaintext,
|
||||
@@ -158,14 +223,27 @@ app.whenReady().then(() => {
|
||||
return { content: encryptedBuffer.toString('hex'), iv: iv.toString('hex'), tag };
|
||||
});
|
||||
|
||||
ipcMain.handle('decrypt-data', (event, ciphertext, key, iv, tag) => {
|
||||
ipcMain.handle('decrypt-data', (event, ciphertext, key, iv, tag, options = {}) => {
|
||||
const keyBuffer = typeof key === 'string' ? Buffer.from(key, 'hex') : key;
|
||||
const ivBuffer = Buffer.from(iv, 'hex');
|
||||
const tagBuffer = Buffer.from(tag, 'hex');
|
||||
const decipher = crypto.createDecipheriv('aes-256-gcm', keyBuffer, ivBuffer);
|
||||
decipher.setAuthTag(tagBuffer);
|
||||
let decrypted = decipher.update(ciphertext, 'hex', 'utf8');
|
||||
decrypted += decipher.final('utf8');
|
||||
|
||||
const outputEncoding = options.encoding || 'utf8';
|
||||
// If encoding is 'buffer', don't pass an encoding to update/final
|
||||
const updateEncoding = outputEncoding === 'buffer' ? undefined : outputEncoding;
|
||||
|
||||
let decrypted;
|
||||
if (outputEncoding === 'buffer') {
|
||||
decrypted = Buffer.concat([
|
||||
decipher.update(ciphertext, 'hex'),
|
||||
decipher.final()
|
||||
]);
|
||||
} else {
|
||||
decrypted = decipher.update(ciphertext, 'hex', outputEncoding);
|
||||
decrypted += decipher.final(outputEncoding);
|
||||
}
|
||||
return decrypted;
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user