add: the backend server for the app
it is used for communication between Web & Electron.
This commit is contained in:
parent
8cf17838f4
commit
fb70acab00
2
bunfig.toml
Normal file
2
bunfig.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[install.scopes]
|
||||
"@jsr" = "https://npm.jsr.io"
|
@ -17,9 +17,12 @@
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alikia/random-key": "npm:@jsr/alikia__random-key",
|
||||
"@electron/remote": "^2.1.2",
|
||||
"@hono/node-server": "^1.13.7",
|
||||
"@unly/universal-language-detector": "^2.0.3",
|
||||
"better-sqlite3": "^11.6.0",
|
||||
"detect-port": "^2.1.0",
|
||||
"electron-context-menu": "^4.0.4",
|
||||
"electron-reloader": "^1.2.3",
|
||||
"electron-screencapture": "^1.1.0",
|
||||
@ -27,6 +30,7 @@
|
||||
"electron-store": "^10.0.0",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"execa": "^9.5.1",
|
||||
"hono": "^4.6.15",
|
||||
"i18next": "^24.0.2",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"i18next-electron-fs-backend": "^3.0.2",
|
||||
|
@ -76,7 +76,7 @@ export async function deleteEncodedScreenshots(db: Database) {
|
||||
|
||||
// Check and process encoding task
|
||||
export function processEncodingTasks(db: Database) {
|
||||
const tasksPerforming = cache.get("tasksPerforming") as string[] || [];
|
||||
const tasksPerforming = cache.get("backend:encodingTasksPerforming") as string[] || [];
|
||||
if (tasksPerforming.length >= CONCURRENCY) return;
|
||||
|
||||
const stmt = db.prepare(`
|
||||
@ -111,7 +111,7 @@ export function processEncodingTasks(db: Database) {
|
||||
const metaFilePath = path.join(getEncodingTempDir(), `${taskId}_meta.txt`);
|
||||
const metaContent = frames.map(frame => `file '${path.join(getScreenshotsDir(), frame.imgFilename)}'\nduration 0.03333`).join("\n");
|
||||
fs.writeFileSync(metaFilePath, metaContent);
|
||||
cache.put("tasksPerforming", [...tasksPerforming, taskId.toString()]);
|
||||
cache.put("backend:encodingTasksPerforming", [...tasksPerforming, taskId.toString()]);
|
||||
|
||||
const videoPath = path.join(getRecordingsDir(), `${taskId}.mp4`);
|
||||
const ffmpegCommand = `ffmpeg -f concat -safe 0 -i "${metaFilePath}" -c:v libx264 -r 30 -threads 1 "${videoPath}"`;
|
||||
@ -138,7 +138,7 @@ export function processEncodingTasks(db: Database) {
|
||||
db.prepare(`COMMIT;`).run();
|
||||
|
||||
}
|
||||
cache.put("tasksPerforming", tasksPerforming.filter(id => id !== taskId.toString()));
|
||||
cache.put("backend:encodingTasksPerforming", tasksPerforming.filter(id => id !== taskId.toString()));
|
||||
fs.unlinkSync(metaFilePath);
|
||||
});
|
||||
}
|
||||
|
@ -9,6 +9,11 @@ import { startScreenshotLoop } from "./backend/screenshot.js";
|
||||
import { __dirname } from "./dirname.js";
|
||||
import { hideDock } from "./utils/electron.js";
|
||||
import { checkFramesForEncoding, deleteEncodedScreenshots, processEncodingTasks } from "./backend/encoding.js";
|
||||
import honoApp from "./server/index.js";
|
||||
import { serve } from "@hono/node-server";
|
||||
import { findAvailablePort } from "./utils/server.js";
|
||||
import cache from "memory-cache";
|
||||
import { generate } from '@alikia/random-key';
|
||||
|
||||
const i18n = initI18n();
|
||||
|
||||
@ -70,15 +75,26 @@ contextMenu({
|
||||
app.once("ready", () => {
|
||||
hideDock();
|
||||
});
|
||||
app.on("activate", () => {});
|
||||
app.on("activate", () => {
|
||||
});
|
||||
|
||||
app.on("ready", () => {
|
||||
createTray();
|
||||
findAvailablePort(12412).then((port) => {
|
||||
generate().then((key) => {
|
||||
cache.put("server:APIKey",key);
|
||||
cache.put("server:port", port);
|
||||
if (dev)
|
||||
console.log(`API Key: ${key}`);
|
||||
serve({ fetch: honoApp.fetch, port: port });
|
||||
console.log(`App server running on port ${port}`);
|
||||
});
|
||||
})
|
||||
initDatabase().then((db) => {
|
||||
screenshotInterval = startScreenshotLoop(db);
|
||||
setInterval(checkFramesForEncoding, 5000, db);
|
||||
setInterval(processEncodingTasks, 10000, db);
|
||||
setInterval(deleteEncodedScreenshots, 5000, db)
|
||||
setInterval(deleteEncodedScreenshots, 5000, db);
|
||||
dbConnection = db;
|
||||
});
|
||||
mainWindow = createMainWindow(port, () => (mainWindow = null));
|
||||
@ -97,6 +113,6 @@ app.on("will-quit", ()=> {
|
||||
// if (process.platform !== "darwin") app.quit();
|
||||
// });
|
||||
|
||||
ipcMain.on('close-settings', () => {
|
||||
ipcMain.on("close-settings", () => {
|
||||
settingsWindow?.hide();
|
||||
});
|
17
src/electron/server/index.ts
Normal file
17
src/electron/server/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Hono } from 'hono'
|
||||
import cache from "memory-cache";
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
app.use(async (c, next) => {
|
||||
const key = cache.get("server:APIKey");
|
||||
if (key && c.req.header("x-api-key") !== key) {
|
||||
c.res = undefined
|
||||
c.res = c.json({ error: "Invalid API key" }, 401);
|
||||
}
|
||||
await next();
|
||||
})
|
||||
|
||||
app.get('/ping', (c) => c.text('pong'))
|
||||
|
||||
export default app;
|
17
src/electron/utils/server.ts
Normal file
17
src/electron/utils/server.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { detect } from 'detect-port';
|
||||
|
||||
/**
|
||||
* Finds an available port starting from a given port.
|
||||
* @param startingFrom - The port number to start searching from.
|
||||
* @returns A Promise that resolves to the first available port number.
|
||||
*/
|
||||
export async function findAvailablePort(startingFrom: number): Promise<number> {
|
||||
return detect(startingFrom)
|
||||
.then(realPort => {
|
||||
return realPort; // Return the available port
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(`Error detecting port: ${err.message}`);
|
||||
throw err; // Rethrow the error for further handling if needed
|
||||
});
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "bundler",
|
||||
"outDir": "./dist/electron",
|
||||
"rootDir": "./src/electron",
|
||||
"strict": true,
|
||||
|
Loading…
Reference in New Issue
Block a user