diff --git a/dist-electron/main.js b/dist-electron/main.js deleted file mode 100644 index 03ef7ad..0000000 --- a/dist-electron/main.js +++ /dev/null @@ -1,517 +0,0 @@ -import { ipcMain as i, screen as R, BrowserWindow as x, app as f, desktopCapturer as ee, shell as te, dialog as I, nativeImage as re, Tray as oe, Menu as V } from "electron"; -import { fileURLToPath as B } from "node:url"; -import a from "node:path"; -import p from "node:fs/promises"; -const N = a.dirname(B(import.meta.url)), se = a.join(N, ".."), T = process.env.VITE_DEV_SERVER_URL, W = a.join(se, "dist"); -let O = null; -i.on("hud-overlay-hide", () => { - O && !O.isDestroyed() && O.minimize(); -}); -function ne() { - const o = R.getPrimaryDisplay(), { workArea: r } = o, c = 500, g = 100, y = Math.floor(r.x + (r.width - c) / 2), t = Math.floor(r.y + r.height - g - 5), e = new x({ - width: c, - height: g, - minWidth: 500, - maxWidth: 500, - minHeight: 100, - maxHeight: 100, - x: y, - y: t, - frame: !1, - transparent: !0, - resizable: !1, - alwaysOnTop: !0, - skipTaskbar: !0, - hasShadow: !1, - webPreferences: { - preload: a.join(N, "preload.mjs"), - nodeIntegration: !1, - contextIsolation: !0, - backgroundThrottling: !1 - } - }); - return e.webContents.on("did-finish-load", () => { - e == null || e.webContents.send("main-process-message", (/* @__PURE__ */ new Date()).toLocaleString()); - }), O = e, e.on("closed", () => { - O === e && (O = null); - }), T ? e.loadURL(T + "?windowType=hud-overlay") : e.loadFile(a.join(W, "index.html"), { - query: { windowType: "hud-overlay" } - }), e; -} -function ae() { - const o = process.platform === "darwin", r = new x({ - width: 1200, - height: 800, - minWidth: 800, - minHeight: 600, - ...o && { - titleBarStyle: "hiddenInset", - trafficLightPosition: { x: 12, y: 12 } - }, - transparent: !1, - resizable: !0, - alwaysOnTop: !1, - skipTaskbar: !1, - title: "OpenScreen", - backgroundColor: "#000000", - webPreferences: { - preload: a.join(N, "preload.mjs"), - nodeIntegration: !1, - contextIsolation: !0, - webSecurity: !1, - backgroundThrottling: !1 - } - }); - return r.maximize(), r.webContents.on("did-finish-load", () => { - r == null || r.webContents.send("main-process-message", (/* @__PURE__ */ new Date()).toLocaleString()); - }), T ? r.loadURL(T + "?windowType=editor") : r.loadFile(a.join(W, "index.html"), { - query: { windowType: "editor" } - }), r; -} -function ie() { - const { width: o, height: r } = R.getPrimaryDisplay().workAreaSize, c = new x({ - width: 620, - height: 420, - minHeight: 350, - maxHeight: 500, - x: Math.round((o - 620) / 2), - y: Math.round((r - 420) / 2), - frame: !1, - resizable: !1, - alwaysOnTop: !0, - transparent: !0, - backgroundColor: "#00000000", - webPreferences: { - preload: a.join(N, "preload.mjs"), - nodeIntegration: !1, - contextIsolation: !0 - } - }); - return T ? c.loadURL(T + "?windowType=source-selector") : c.loadFile(a.join(W, "index.html"), { - query: { windowType: "source-selector" } - }), c; -} -const D = "openscreen", U = a.join(f.getPath("userData"), "shortcuts.json"); -let v = null, w = null, m = null; -function z(o) { - return a.resolve(o); -} -function le(o) { - return !o || !m ? !1 : z(o) === z(m); -} -const ce = 1, ue = 100, de = 60 * 60 * 10; -let C = null, G = 0, F = [], _ = []; -function M(o, r, c) { - return Math.min(c, Math.max(r, o)); -} -function J() { - C && (clearInterval(C), C = null); -} -function $() { - const o = R.getCursorScreenPoint(), r = Number(v == null ? void 0 : v.display_id), y = ((Number.isFinite(r) ? R.getAllDisplays().find((l) => l.id === r) ?? null : null) ?? R.getDisplayNearestPoint(o)).bounds, t = Math.max(1, y.width), e = Math.max(1, y.height), n = M((o.x - y.x) / t, 0, 1), s = M((o.y - y.y) / e, 0, 1); - F.push({ - timeMs: Math.max(0, Date.now() - G), - cx: n, - cy: s - }), F.length > de && F.shift(); -} -function pe(o, r, c, g, y) { - i.handle("get-sources", async (t, e) => (await ee.getSources(e)).map((s) => ({ - id: s.id, - name: s.name, - display_id: s.display_id, - thumbnail: s.thumbnail ? s.thumbnail.toDataURL() : null, - appIcon: s.appIcon ? s.appIcon.toDataURL() : null - }))), i.handle("select-source", (t, e) => { - v = e; - const n = g(); - return n && n.close(), v; - }), i.handle("get-selected-source", () => v), i.handle("open-source-selector", () => { - const t = g(); - if (t) { - t.focus(); - return; - } - r(); - }), i.handle("switch-to-editor", () => { - const t = c(); - t && t.close(), o(); - }), i.handle("store-recorded-video", async (t, e, n) => { - try { - const s = a.join(S, n); - await p.writeFile(s, Buffer.from(e)), w = s, m = null; - const l = `${s}.cursor.json`; - return _.length > 0 && await p.writeFile( - l, - JSON.stringify({ version: ce, samples: _ }, null, 2), - "utf-8" - ), _ = [], { - success: !0, - path: s, - message: "Video stored successfully" - }; - } catch (s) { - return console.error("Failed to store video:", s), { - success: !1, - message: "Failed to store video", - error: String(s) - }; - } - }), i.handle("get-recorded-video-path", async () => { - try { - const e = (await p.readdir(S)).filter((l) => l.endsWith(".webm")); - if (e.length === 0) - return { success: !1, message: "No recorded video found" }; - const n = e.sort().reverse()[0]; - return { success: !0, path: a.join(S, n) }; - } catch (t) { - return console.error("Failed to get video path:", t), { success: !1, message: "Failed to get video path", error: String(t) }; - } - }), i.handle("set-recording-state", (t, e) => { - e ? (J(), F = [], _ = [], G = Date.now(), $(), C = setInterval($, ue)) : (J(), _ = [...F], F = []), y && y(e, (v || { name: "Screen" }).name); - }), i.handle("get-cursor-telemetry", async (t, e) => { - const n = e ?? w; - if (!n) - return { success: !0, samples: [] }; - const s = `${n}.cursor.json`; - try { - const l = await p.readFile(s, "utf-8"), d = JSON.parse(l); - return { success: !0, samples: (Array.isArray(d) ? d : Array.isArray(d == null ? void 0 : d.samples) ? d.samples : []).filter((b) => !!(b && typeof b == "object")).map((b) => { - const h = b; - return { - timeMs: typeof h.timeMs == "number" && Number.isFinite(h.timeMs) ? Math.max(0, h.timeMs) : 0, - cx: typeof h.cx == "number" && Number.isFinite(h.cx) ? M(h.cx, 0, 1) : 0.5, - cy: typeof h.cy == "number" && Number.isFinite(h.cy) ? M(h.cy, 0, 1) : 0.5 - }; - }).sort((b, h) => b.timeMs - h.timeMs) }; - } catch (l) { - return l.code === "ENOENT" ? { success: !0, samples: [] } : (console.error("Failed to load cursor telemetry:", l), { success: !1, message: "Failed to load cursor telemetry", error: String(l), samples: [] }); - } - }), i.handle("open-external-url", async (t, e) => { - try { - return await te.openExternal(e), { success: !0 }; - } catch (n) { - return console.error("Failed to open URL:", n), { success: !1, error: String(n) }; - } - }), i.handle("get-asset-base-path", () => { - try { - return f.isPackaged ? a.join(process.resourcesPath, "assets") : a.join(f.getAppPath(), "public", "assets"); - } catch (t) { - return console.error("Failed to resolve asset base path:", t), null; - } - }), i.handle("save-exported-video", async (t, e, n) => { - try { - const s = n.toLowerCase().endsWith(".gif"), l = s ? [{ name: "GIF Image", extensions: ["gif"] }] : [{ name: "MP4 Video", extensions: ["mp4"] }], d = await I.showSaveDialog({ - title: s ? "Save Exported GIF" : "Save Exported Video", - defaultPath: a.join(f.getPath("downloads"), n), - filters: l, - properties: ["createDirectory", "showOverwriteConfirmation"] - }); - return d.canceled || !d.filePath ? { - success: !1, - canceled: !0, - message: "Export canceled" - } : (await p.writeFile(d.filePath, Buffer.from(e)), { - success: !0, - path: d.filePath, - message: "Video exported successfully" - }); - } catch (s) { - return console.error("Failed to save exported video:", s), { - success: !1, - message: "Failed to save exported video", - error: String(s) - }; - } - }), i.handle("open-video-file-picker", async () => { - try { - const t = await I.showOpenDialog({ - title: "Select Video File", - defaultPath: S, - filters: [ - { name: "Video Files", extensions: ["webm", "mp4", "mov", "avi", "mkv"] }, - { name: "All Files", extensions: ["*"] } - ], - properties: ["openFile"] - }); - return t.canceled || t.filePaths.length === 0 ? { success: !1, canceled: !0 } : (m = null, { - success: !0, - path: t.filePaths[0] - }); - } catch (t) { - return console.error("Failed to open file picker:", t), { - success: !1, - message: "Failed to open file picker", - error: String(t) - }; - } - }), i.handle("save-project-file", async (t, e, n, s) => { - try { - const l = le(s) ? s : null; - if (l) - return await p.writeFile(l, JSON.stringify(e, null, 2), "utf-8"), m = l, { - success: !0, - path: l, - message: "Project saved successfully" - }; - const d = (n || `project-${Date.now()}`).replace(/[^a-zA-Z0-9-_]/g, "_"), k = d.endsWith(`.${D}`) ? d : `${d}.${D}`, P = await I.showSaveDialog({ - title: "Save OpenScreen Project", - defaultPath: a.join(S, k), - filters: [ - { name: "OpenScreen Project", extensions: [D] }, - { name: "JSON", extensions: ["json"] } - ], - properties: ["createDirectory", "showOverwriteConfirmation"] - }); - return P.canceled || !P.filePath ? { - success: !1, - canceled: !0, - message: "Save project canceled" - } : (await p.writeFile(P.filePath, JSON.stringify(e, null, 2), "utf-8"), m = P.filePath, { - success: !0, - path: P.filePath, - message: "Project saved successfully" - }); - } catch (l) { - return console.error("Failed to save project file:", l), { - success: !1, - message: "Failed to save project file", - error: String(l) - }; - } - }), i.handle("load-project-file", async () => { - try { - const t = await I.showOpenDialog({ - title: "Open OpenScreen Project", - defaultPath: S, - filters: [ - { name: "OpenScreen Project", extensions: [D] }, - { name: "JSON", extensions: ["json"] }, - { name: "All Files", extensions: ["*"] } - ], - properties: ["openFile"] - }); - if (t.canceled || t.filePaths.length === 0) - return { success: !1, canceled: !0, message: "Open project canceled" }; - const e = t.filePaths[0], n = await p.readFile(e, "utf-8"), s = JSON.parse(n); - return m = e, s && typeof s == "object" && typeof s.videoPath == "string" && (w = s.videoPath), { - success: !0, - path: e, - project: s - }; - } catch (t) { - return console.error("Failed to load project file:", t), { - success: !1, - message: "Failed to load project file", - error: String(t) - }; - } - }), i.handle("load-current-project-file", async () => { - try { - if (!m) - return { success: !1, message: "No active project" }; - const t = await p.readFile(m, "utf-8"), e = JSON.parse(t); - return e && typeof e == "object" && typeof e.videoPath == "string" && (w = e.videoPath), { - success: !0, - path: m, - project: e - }; - } catch (t) { - return console.error("Failed to load current project file:", t), { - success: !1, - message: "Failed to load current project file", - error: String(t) - }; - } - }), i.handle("set-current-video-path", (t, e) => (w = e, m = null, { success: !0 })), i.handle("get-current-video-path", () => w ? { success: !0, path: w } : { success: !1 }), i.handle("clear-current-video-path", () => (w = null, { success: !0 })), i.handle("get-platform", () => process.platform), i.handle("get-shortcuts", async () => { - try { - const t = await p.readFile(U, "utf-8"); - return JSON.parse(t); - } catch { - return null; - } - }), i.handle("save-shortcuts", async (t, e) => { - try { - return await p.writeFile(U, JSON.stringify(e, null, 2), "utf-8"), { success: !0 }; - } catch (n) { - return console.error("Failed to save shortcuts:", n), { success: !1, error: String(n) }; - } - }); -} -const fe = a.dirname(B(import.meta.url)), S = a.join(f.getPath("userData"), "recordings"); -async function he() { - try { - await p.mkdir(S, { recursive: !0 }), console.log("RECORDINGS_DIR:", S), console.log("User Data Path:", f.getPath("userData")); - } catch (o) { - console.error("Failed to create recordings directory:", o); - } -} -process.env.APP_ROOT = a.join(fe, ".."); -const me = process.env.VITE_DEV_SERVER_URL, Oe = a.join(process.env.APP_ROOT, "dist-electron"), X = a.join(process.env.APP_ROOT, "dist"); -process.env.VITE_PUBLIC = me ? a.join(process.env.APP_ROOT, "public") : X; -let u = null, E = null, j = null, Z = ""; -const Q = Y("openscreen.png"), ye = Y("rec-button.png"); -function L() { - u = ne(); -} -function ge(o) { - return o.webContents.getURL().includes("windowType=editor"); -} -function A(o) { - let r = x.getFocusedWindow() ?? u; - if (!r || r.isDestroyed() || !ge(r)) { - if (K(), r = u, !r || r.isDestroyed()) return; - r.webContents.once("did-finish-load", () => { - !r || r.isDestroyed() || r.webContents.send(o); - }); - return; - } - r.webContents.send(o); -} -function we() { - const o = process.platform === "darwin", r = []; - o && r.push({ - label: f.name, - submenu: [ - { role: "about" }, - { type: "separator" }, - { role: "services" }, - { type: "separator" }, - { role: "hide" }, - { role: "hideOthers" }, - { role: "unhide" }, - { type: "separator" }, - { role: "quit" } - ] - }), r.push( - { - label: "File", - submenu: [ - { - label: "Load Project…", - accelerator: "CmdOrCtrl+O", - click: () => A("menu-load-project") - }, - { - label: "Save Project…", - accelerator: "CmdOrCtrl+S", - click: () => A("menu-save-project") - }, - { - label: "Save Project As…", - accelerator: "CmdOrCtrl+Shift+S", - click: () => A("menu-save-project-as") - }, - ...o ? [] : [{ type: "separator" }, { role: "quit" }] - ] - }, - { - label: "Edit", - submenu: [ - { role: "undo" }, - { role: "redo" }, - { type: "separator" }, - { role: "cut" }, - { role: "copy" }, - { role: "paste" }, - { role: "selectAll" } - ] - }, - { - label: "View", - submenu: [ - { role: "reload" }, - { role: "forceReload" }, - { role: "toggleDevTools" }, - { type: "separator" }, - { role: "resetZoom" }, - { role: "zoomIn" }, - { role: "zoomOut" }, - { type: "separator" }, - { role: "togglefullscreen" } - ] - }, - { - label: "Window", - submenu: o ? [ - { role: "minimize" }, - { role: "zoom" }, - { type: "separator" }, - { role: "front" } - ] : [ - { role: "minimize" }, - { role: "close" } - ] - } - ); - const c = V.buildFromTemplate(r); - V.setApplicationMenu(c); -} -function H() { - j = new oe(Q); -} -function Y(o) { - return re.createFromPath(a.join(process.env.VITE_PUBLIC || X, o)).resize({ - width: 24, - height: 24, - quality: "best" - }); -} -function q(o = !1) { - if (!j) return; - const r = o ? ye : Q, c = o ? `Recording: ${Z}` : "OpenScreen", g = o ? [ - { - label: "Stop Recording", - click: () => { - u && !u.isDestroyed() && u.webContents.send("stop-recording-from-tray"); - } - } - ] : [ - { - label: "Open", - click: () => { - u && !u.isDestroyed() ? u.isMinimized() && u.restore() : L(); - } - }, - { - label: "Quit", - click: () => { - f.quit(); - } - } - ]; - j.setImage(r), j.setToolTip(c), j.setContextMenu(V.buildFromTemplate(g)); -} -function K() { - u && (u.close(), u = null), u = ae(); -} -function Se() { - return E = ie(), E.on("closed", () => { - E = null; - }), E; -} -f.on("window-all-closed", () => { -}); -f.on("activate", () => { - x.getAllWindows().length === 0 && L(); -}); -f.whenReady().then(async () => { - const { ipcMain: o } = await import("electron"); - o.on("hud-overlay-close", () => { - f.quit(); - }), H(), q(), we(), await he(), pe( - K, - Se, - () => u, - () => E, - (r, c) => { - Z = c, j || H(), q(r), r || u && u.restore(); - } - ), L(); -}); -export { - Oe as MAIN_DIST, - S as RECORDINGS_DIR, - X as RENDERER_DIST, - me as VITE_DEV_SERVER_URL -}; diff --git a/dist-electron/preload.mjs b/dist-electron/preload.mjs deleted file mode 100644 index c06f432..0000000 --- a/dist-electron/preload.mjs +++ /dev/null @@ -1 +0,0 @@ -"use strict";const e=require("electron");e.contextBridge.exposeInMainWorld("electronAPI",{hudOverlayHide:()=>{e.ipcRenderer.send("hud-overlay-hide")},hudOverlayClose:()=>{e.ipcRenderer.send("hud-overlay-close")},getAssetBasePath:async()=>await e.ipcRenderer.invoke("get-asset-base-path"),getSources:async r=>await e.ipcRenderer.invoke("get-sources",r),switchToEditor:()=>e.ipcRenderer.invoke("switch-to-editor"),openSourceSelector:()=>e.ipcRenderer.invoke("open-source-selector"),selectSource:r=>e.ipcRenderer.invoke("select-source",r),getSelectedSource:()=>e.ipcRenderer.invoke("get-selected-source"),storeRecordedVideo:(r,t)=>e.ipcRenderer.invoke("store-recorded-video",r,t),getRecordedVideoPath:()=>e.ipcRenderer.invoke("get-recorded-video-path"),setRecordingState:r=>e.ipcRenderer.invoke("set-recording-state",r),getCursorTelemetry:r=>e.ipcRenderer.invoke("get-cursor-telemetry",r),onStopRecordingFromTray:r=>{const t=()=>r();return e.ipcRenderer.on("stop-recording-from-tray",t),()=>e.ipcRenderer.removeListener("stop-recording-from-tray",t)},openExternalUrl:r=>e.ipcRenderer.invoke("open-external-url",r),saveExportedVideo:(r,t)=>e.ipcRenderer.invoke("save-exported-video",r,t),openVideoFilePicker:()=>e.ipcRenderer.invoke("open-video-file-picker"),setCurrentVideoPath:r=>e.ipcRenderer.invoke("set-current-video-path",r),getCurrentVideoPath:()=>e.ipcRenderer.invoke("get-current-video-path"),clearCurrentVideoPath:()=>e.ipcRenderer.invoke("clear-current-video-path"),saveProjectFile:(r,t,n)=>e.ipcRenderer.invoke("save-project-file",r,t,n),loadProjectFile:()=>e.ipcRenderer.invoke("load-project-file"),loadCurrentProjectFile:()=>e.ipcRenderer.invoke("load-current-project-file"),onMenuLoadProject:r=>{const t=()=>r();return e.ipcRenderer.on("menu-load-project",t),()=>e.ipcRenderer.removeListener("menu-load-project",t)},onMenuSaveProject:r=>{const t=()=>r();return e.ipcRenderer.on("menu-save-project",t),()=>e.ipcRenderer.removeListener("menu-save-project",t)},onMenuSaveProjectAs:r=>{const t=()=>r();return e.ipcRenderer.on("menu-save-project-as",t),()=>e.ipcRenderer.removeListener("menu-save-project-as",t)},getPlatform:()=>e.ipcRenderer.invoke("get-platform"),getShortcuts:()=>e.ipcRenderer.invoke("get-shortcuts"),saveShortcuts:r=>e.ipcRenderer.invoke("save-shortcuts",r)});