diff --git a/dist-electron/main.js b/dist-electron/main.js index c9c27ca..8ae5b38 100644 --- a/dist-electron/main.js +++ b/dist-electron/main.js @@ -1,11 +1,10 @@ -import { BrowserWindow as P, screen as O, ipcMain as c, desktopCapturer as M, shell as W, app as p, nativeImage as L, Tray as V, Menu as U } from "electron"; -import { fileURLToPath as E } from "node:url"; +import { BrowserWindow as v, screen as j, ipcMain as c, desktopCapturer as x, shell as D, app as l, nativeImage as F, Tray as W, Menu as O } from "electron"; +import { fileURLToPath as P } from "node:url"; import t from "node:path"; -import m from "node:fs/promises"; -import { uIOhook as w } from "uiohook-napi"; -const S = t.dirname(E(import.meta.url)), A = t.join(S, ".."), y = process.env.VITE_DEV_SERVER_URL, x = t.join(A, "dist"); -function C() { - const e = new P({ +import p from "node:fs/promises"; +const _ = t.dirname(P(import.meta.url)), V = t.join(_, ".."), f = process.env.VITE_DEV_SERVER_URL, T = t.join(V, "dist"); +function L() { + const e = new v({ width: 250, height: 80, minWidth: 250, @@ -19,7 +18,7 @@ function C() { skipTaskbar: !0, hasShadow: !1, webPreferences: { - preload: t.join(S, "preload.mjs"), + preload: t.join(_, "preload.mjs"), nodeIntegration: !1, contextIsolation: !0, backgroundThrottling: !1 @@ -27,12 +26,12 @@ function C() { }); return e.webContents.on("did-finish-load", () => { e == null || e.webContents.send("main-process-message", (/* @__PURE__ */ new Date()).toLocaleString()); - }), y ? e.loadURL(y + "?windowType=hud-overlay") : e.loadFile(t.join(x, "index.html"), { + }), f ? e.loadURL(f + "?windowType=hud-overlay") : e.loadFile(t.join(T, "index.html"), { query: { windowType: "hud-overlay" } }), e; } -function N() { - const e = new P({ +function k() { + const e = new v({ width: 1200, height: 800, minWidth: 800, @@ -46,7 +45,7 @@ function N() { title: "OpenScreen", backgroundColor: "#000000", webPreferences: { - preload: t.join(S, "preload.mjs"), + preload: t.join(_, "preload.mjs"), nodeIntegration: !1, contextIsolation: !0, webSecurity: !1 @@ -54,146 +53,59 @@ function N() { }); return e.maximize(), e.webContents.on("did-finish-load", () => { e == null || e.webContents.send("main-process-message", (/* @__PURE__ */ new Date()).toLocaleString()); - }), y ? e.loadURL(y + "?windowType=editor") : e.loadFile(t.join(x, "index.html"), { + }), f ? e.loadURL(f + "?windowType=editor") : e.loadFile(t.join(T, "index.html"), { query: { windowType: "editor" } }), e; } -function H() { - const { width: e, height: n } = O.getPrimaryDisplay().workAreaSize, i = new P({ +function U() { + const { width: e, height: s } = j.getPrimaryDisplay().workAreaSize, u = new v({ width: 620, height: 420, minHeight: 350, maxHeight: 500, x: Math.round((e - 620) / 2), - y: Math.round((n - 420) / 2), + y: Math.round((s - 420) / 2), frame: !1, resizable: !1, alwaysOnTop: !0, transparent: !0, backgroundColor: "#00000000", webPreferences: { - preload: t.join(S, "preload.mjs"), + preload: t.join(_, "preload.mjs"), nodeIntegration: !1, contextIsolation: !0 } }); - return y ? i.loadURL(y + "?windowType=source-selector") : i.loadFile(t.join(x, "index.html"), { + return f ? u.loadURL(f + "?windowType=source-selector") : u.loadFile(t.join(T, "index.html"), { query: { windowType: "source-selector" } - }), i; + }), u; } -let u = !1, _ = !1, d = 0, f = []; -function z() { - if (u) - return { success: !1, message: "Already tracking" }; - if (u = !0, d = performance.now(), f = [], _) - return { success: !0, message: "Mouse tracking resumed", startTime: d }; - q(); - try { - return w.start(), _ = !0, { success: !0, message: "Mouse tracking started", startTime: d }; - } catch (e) { - return console.error("Failed to start mouse tracking:", e), u = !1, { success: !1, message: "Failed to start hook", error: e }; - } -} -function B() { - if (!u) - return { success: !1, message: "Not currently tracking" }; - u = !1; - const e = performance.now() - d; - return { - success: !0, - message: "Mouse tracking stopped", - data: { - startTime: d, - events: f, - duration: e - } - }; -} -function q() { - w.on("mousemove", (e) => { - if (u) { - const i = { - type: "move", - timestamp: performance.now() - d, - x: e.x, - y: e.y - }; - f.push(i); - } - }), w.on("mousedown", (e) => { - if (u) { - const i = { - type: "down", - timestamp: performance.now() - d, - x: e.x, - y: e.y, - button: e.button, - clicks: e.clicks - }; - f.push(i); - } - }), w.on("mouseup", (e) => { - if (u) { - const i = { - type: "up", - timestamp: performance.now() - d, - x: e.x, - y: e.y, - button: e.button - }; - f.push(i); - } - }), w.on("click", (e) => { - if (u) { - const i = { - type: "click", - timestamp: performance.now() - d, - x: e.x, - y: e.y, - button: e.button, - clicks: e.clicks - }; - f.push(i); - } - }); -} -function $() { - return [...f]; -} -function G() { - if (_) - try { - w.stop(), _ = !1, u = !1, f = []; - } catch (e) { - console.error("Error cleaning up mouse tracking:", e); - } -} -let b = null; -function J(e, n, i, v, T) { - c.handle("get-sources", async (o, a) => (await M.getSources(a)).map((r) => ({ +let R = null; +function C(e, s, u, m, w) { + c.handle("get-sources", async (o, n) => (await x.getSources(n)).map((r) => ({ id: r.id, name: r.name, display_id: r.display_id, thumbnail: r.thumbnail ? r.thumbnail.toDataURL() : null, appIcon: r.appIcon ? r.appIcon.toDataURL() : null - }))), c.handle("select-source", (o, a) => { - b = a; - const s = v(); - return s && s.close(), b; - }), c.handle("get-selected-source", () => b), c.handle("open-source-selector", () => { - const o = v(); + }))), c.handle("select-source", (o, n) => { + R = n; + const i = m(); + return i && i.close(), R; + }), c.handle("get-selected-source", () => R), c.handle("open-source-selector", () => { + const o = m(); if (o) { o.focus(); return; } - n(); + s(); }), c.handle("switch-to-editor", () => { - const o = i(); + const o = u(); o && o.close(), e(); - }), c.handle("start-mouse-tracking", () => z()), c.handle("stop-mouse-tracking", () => B()), c.handle("store-recorded-video", async (o, a, s) => { + }), c.handle("store-recorded-video", async (o, n, i) => { try { - const r = t.join(h, s); - return await m.writeFile(r, Buffer.from(a)), { + const r = t.join(h, i); + return await p.writeFile(r, Buffer.from(n)), { success: !0, path: r, message: "Video stored successfully" @@ -205,55 +117,36 @@ function J(e, n, i, v, T) { error: String(r) }; } - }), c.handle("store-mouse-tracking-data", async (o, a) => { - try { - const s = $(); - if (s.length === 0) - return { success: !1, message: "No tracking data to save" }; - const r = t.join(h, a); - return await m.writeFile(r, JSON.stringify(s, null, 2), "utf-8"), { - success: !0, - path: r, - eventCount: s.length, - message: "Mouse tracking data stored successfully" - }; - } catch (s) { - return console.error("Failed to store mouse tracking data:", s), { - success: !1, - message: "Failed to store mouse tracking data", - error: String(s) - }; - } }), c.handle("get-recorded-video-path", async () => { try { - const a = (await m.readdir(h)).filter((R) => R.endsWith(".webm")); - if (a.length === 0) + const n = (await p.readdir(h)).filter((y) => y.endsWith(".webm")); + if (n.length === 0) return { success: !1, message: "No recorded video found" }; - const s = a.sort().reverse()[0]; - return { success: !0, path: t.join(h, s) }; + const i = n.sort().reverse()[0]; + return { success: !0, path: t.join(h, i) }; } catch (o) { return console.error("Failed to get video path:", o), { success: !1, message: "Failed to get video path", error: String(o) }; } - }), c.handle("set-recording-state", (o, a) => { - T && T(a, (b || { name: "Screen" }).name); - }), c.handle("open-external-url", async (o, a) => { + }), c.handle("set-recording-state", (o, n) => { + w && w(n, (R || { name: "Screen" }).name); + }), c.handle("open-external-url", async (o, n) => { try { - return await W.openExternal(a), { success: !0 }; - } catch (s) { - return console.error("Failed to open URL:", s), { success: !1, error: String(s) }; + return await D.openExternal(n), { success: !0 }; + } catch (i) { + return console.error("Failed to open URL:", i), { success: !1, error: String(i) }; } }), c.handle("get-asset-base-path", () => { try { - return p.isPackaged ? t.join(process.resourcesPath, "assets") : t.join(p.getAppPath(), "public", "assets"); + return l.isPackaged ? t.join(process.resourcesPath, "assets") : t.join(l.getAppPath(), "public", "assets"); } catch (o) { return console.error("Failed to resolve asset base path:", o), null; } - }), c.handle("save-exported-video", async (o, a, s) => { + }), c.handle("save-exported-video", async (o, n, i) => { try { - const r = p.getPath("downloads"), R = t.join(r, s); - return await m.writeFile(R, Buffer.from(a)), { + const r = l.getPath("downloads"), y = t.join(r, i); + return await p.writeFile(y, Buffer.from(n)), { success: !0, - path: R, + path: y, message: "Video exported successfully" }; } catch (r) { @@ -265,79 +158,79 @@ function J(e, n, i, v, T) { } }); } -const K = t.dirname(E(import.meta.url)), h = t.join(p.getPath("userData"), "recordings"); -async function Q() { +const A = t.dirname(P(import.meta.url)), h = t.join(l.getPath("userData"), "recordings"); +async function M() { try { - const e = await m.readdir(h), n = Date.now(), i = 1 * 24 * 60 * 60 * 1e3; - for (const v of e) { - const T = t.join(h, v), o = await m.stat(T); - n - o.mtimeMs > i && (await m.unlink(T), console.log(`Deleted old recording: ${v}`)); + const e = await p.readdir(h), s = Date.now(), u = 1 * 24 * 60 * 60 * 1e3; + for (const m of e) { + const w = t.join(h, m), o = await p.stat(w); + s - o.mtimeMs > u && (await p.unlink(w), console.log(`Deleted old recording: ${m}`)); } } catch (e) { console.error("Failed to cleanup old recordings:", e); } } -async function X() { +async function z() { try { - await m.mkdir(h, { recursive: !0 }), console.log("Recordings directory ready:", h); + await p.mkdir(h, { recursive: !0 }), console.log("Recordings directory ready:", h); } catch (e) { console.error("Failed to create recordings directory:", e); } } -process.env.APP_ROOT = t.join(K, ".."); -const Y = process.env.VITE_DEV_SERVER_URL, ie = t.join(process.env.APP_ROOT, "dist-electron"), I = t.join(process.env.APP_ROOT, "dist"); -process.env.VITE_PUBLIC = Y ? t.join(process.env.APP_ROOT, "public") : I; -let l = null, k = null, g = null, j = ""; -function D() { - l = C(); +process.env.APP_ROOT = t.join(A, ".."); +const H = process.env.VITE_DEV_SERVER_URL, Q = t.join(process.env.APP_ROOT, "dist-electron"), b = t.join(process.env.APP_ROOT, "dist"); +process.env.VITE_PUBLIC = H ? t.join(process.env.APP_ROOT, "public") : b; +let a = null, g = null, d = null, E = ""; +function S() { + a = L(); } -function Z() { - const e = t.join(process.env.VITE_PUBLIC || I, "rec-button.png"); - let n = L.createFromPath(e); - n = n.resize({ width: 24, height: 24, quality: "best" }), g = new V(n), F(); +function B() { + const e = t.join(process.env.VITE_PUBLIC || b, "rec-button.png"); + let s = F.createFromPath(e); + s = s.resize({ width: 24, height: 24, quality: "best" }), d = new W(s), I(); } -function F() { - if (!g) return; +function I() { + if (!d) return; const e = [ { label: "Stop Recording", click: () => { - l && !l.isDestroyed() && l.webContents.send("stop-recording-from-tray"); + a && !a.isDestroyed() && a.webContents.send("stop-recording-from-tray"); } } - ], n = U.buildFromTemplate(e); - g.setContextMenu(n), g.setToolTip(`Recording: ${j}`); + ], s = O.buildFromTemplate(e); + d.setContextMenu(s), d.setToolTip(`Recording: ${E}`); } -function ee() { - l && (l.close(), l = null), l = N(); +function N() { + a && (a.close(), a = null), a = k(); } -function te() { - return k = H(), k.on("closed", () => { - k = null; - }), k; +function q() { + return g = U(), g.on("closed", () => { + g = null; + }), g; } -p.on("window-all-closed", () => { +l.on("window-all-closed", () => { }); -p.on("activate", () => { - P.getAllWindows().length === 0 && D(); +l.on("activate", () => { + v.getAllWindows().length === 0 && S(); }); -p.on("before-quit", async (e) => { - e.preventDefault(), G(), await Q(), p.exit(0); +l.on("before-quit", async (e) => { + e.preventDefault(), await M(), l.exit(0); }); -p.whenReady().then(async () => { - await X(), J( - ee, - te, - () => l, - () => k, - (e, n) => { - j = n, e ? (g || Z(), F(), l && l.minimize()) : (g && (g.destroy(), g = null), l && l.restore()); +l.whenReady().then(async () => { + await z(), C( + N, + q, + () => a, + () => g, + (e, s) => { + E = s, e ? (d || B(), I(), a && a.minimize()) : (d && (d.destroy(), d = null), a && a.restore()); } - ), D(); + ), S(); }); export { - ie as MAIN_DIST, + Q as MAIN_DIST, h as RECORDINGS_DIR, - I as RENDERER_DIST, - Y as VITE_DEV_SERVER_URL + b as RENDERER_DIST, + H as VITE_DEV_SERVER_URL }; diff --git a/dist-electron/preload.mjs b/dist-electron/preload.mjs index 92d0779..a08f981 100644 --- a/dist-electron/preload.mjs +++ b/dist-electron/preload.mjs @@ -1 +1 @@ -"use strict";const e=require("electron");e.contextBridge.exposeInMainWorld("electronAPI",{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"),startMouseTracking:()=>e.ipcRenderer.invoke("start-mouse-tracking"),stopMouseTracking:()=>e.ipcRenderer.invoke("stop-mouse-tracking"),storeRecordedVideo:(r,t)=>e.ipcRenderer.invoke("store-recorded-video",r,t),storeMouseTrackingData:r=>e.ipcRenderer.invoke("store-mouse-tracking-data",r),getRecordedVideoPath:()=>e.ipcRenderer.invoke("get-recorded-video-path"),setRecordingState:r=>e.ipcRenderer.invoke("set-recording-state",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)}); +"use strict";const e=require("electron");e.contextBridge.exposeInMainWorld("electronAPI",{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),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)}); diff --git a/electron-builder.json5 b/electron-builder.json5 index 192026d..4bc5150 100644 --- a/electron-builder.json5 +++ b/electron-builder.json5 @@ -26,9 +26,7 @@ "to": "assets/wallpapers" } ], - "asarUnpack": [ - "**/node_modules/uiohook-napi/**/*" - ], + "mac": { "target": [ "dmg" diff --git a/electron/electron-env.d.ts b/electron/electron-env.d.ts index 0853fc1..c2d40ea 100644 --- a/electron/electron-env.d.ts +++ b/electron/electron-env.d.ts @@ -29,10 +29,8 @@ interface Window { openSourceSelector: () => Promise selectSource: (source: any) => Promise getSelectedSource: () => Promise - startMouseTracking: () => Promise - stopMouseTracking: () => Promise storeRecordedVideo: (videoData: ArrayBuffer, fileName: string) => Promise<{ success: boolean; path?: string; message?: string }> - storeMouseTrackingData: (fileName: string) => Promise<{ success: boolean; path?: string; eventCount?: number; message?: string }> + getRecordedVideoPath: () => Promise<{ success: boolean; path?: string; message?: string }> setRecordingState: (recording: boolean) => Promise onStopRecordingFromTray: (callback: () => void) => () => void diff --git a/electron/ipc/handlers.ts b/electron/ipc/handlers.ts index 81e8af5..2d74ebc 100644 --- a/electron/ipc/handlers.ts +++ b/electron/ipc/handlers.ts @@ -1,5 +1,5 @@ import { ipcMain, desktopCapturer, BrowserWindow, shell, app } from 'electron' -import { startMouseTracking, stopMouseTracking, getTrackingData } from './mouseTracking' + import fs from 'node:fs/promises' import path from 'node:path' import { RECORDINGS_DIR } from '../main' @@ -54,13 +54,7 @@ export function registerIpcHandlers( createEditorWindow() }) - ipcMain.handle('start-mouse-tracking', () => { - return startMouseTracking() - }) - ipcMain.handle('stop-mouse-tracking', () => { - return stopMouseTracking() - }) ipcMain.handle('store-recorded-video', async (_, videoData: ArrayBuffer, fileName: string) => { try { @@ -82,32 +76,7 @@ export function registerIpcHandlers( } }) - ipcMain.handle('store-mouse-tracking-data', async (_, fileName: string) => { - try { - const data = getTrackingData() - - if (data.length === 0) { - return { success: false, message: 'No tracking data to save' } - } - const trackingPath = path.join(RECORDINGS_DIR, fileName) - await fs.writeFile(trackingPath, JSON.stringify(data, null, 2), 'utf-8') - - return { - success: true, - path: trackingPath, - eventCount: data.length, - message: 'Mouse tracking data stored successfully' - } - } catch (error) { - console.error('Failed to store mouse tracking data:', error) - return { - success: false, - message: 'Failed to store mouse tracking data', - error: String(error) - } - } - }) ipcMain.handle('get-recorded-video-path', async () => { try { diff --git a/electron/ipc/mouseTracking.ts b/electron/ipc/mouseTracking.ts deleted file mode 100644 index 47d3171..0000000 --- a/electron/ipc/mouseTracking.ts +++ /dev/null @@ -1,155 +0,0 @@ -// uiohook-napi [WIP: scoping out mouse tracking with cross platform support for potential auto zoom/ post processing cursor effects] -// not currently being used. - -import { uIOhook } from 'uiohook-napi' - -let isMouseTrackingActive = false -let isHookStarted = false -let recordingStartTime: number = 0 -let mouseEventData: MouseEvent[] = [] - -export interface MouseEvent { - type: 'move' | 'down' | 'up' | 'click' - timestamp: number // milliseconds since recording started - x: number - y: number - button?: unknown - clicks?: number -} - -export interface MouseTrackingSession { - startTime: number - events: MouseEvent[] - duration: number -} - -export function startMouseTracking() { - if (isMouseTrackingActive) { - return { success: false, message: 'Already tracking' } - } - - isMouseTrackingActive = true - - // Reset data for new recording session - recordingStartTime = performance.now() - mouseEventData = [] - - // Only start the hook once - if (!isHookStarted) { - setupMouseEventListeners() - - try { - uIOhook.start() - isHookStarted = true - return { success: true, message: 'Mouse tracking started', startTime: recordingStartTime } - } catch (error) { - console.error('Failed to start mouse tracking:', error) - isMouseTrackingActive = false - return { success: false, message: 'Failed to start hook', error } - } - } else { - return { success: true, message: 'Mouse tracking resumed', startTime: recordingStartTime } - } -} - -export function stopMouseTracking(): { success: boolean; message: string; data?: MouseTrackingSession } { - if (!isMouseTrackingActive) { - return { success: false, message: 'Not currently tracking' } - } - - isMouseTrackingActive = false - - const duration = performance.now() - recordingStartTime - - const session: MouseTrackingSession = { - startTime: recordingStartTime, - events: mouseEventData, - duration: duration - } - - return { - success: true, - message: 'Mouse tracking stopped', - data: session - } -} - -function setupMouseEventListeners() { - // Track mouse movement - uIOhook.on('mousemove', (e) => { - if (isMouseTrackingActive) { - const timestamp = performance.now() - recordingStartTime - const event: MouseEvent = { - type: 'move', - timestamp, - x: e.x, - y: e.y - } - mouseEventData.push(event) - } - }) - - // Track mouse button press - uIOhook.on('mousedown', (e) => { - if (isMouseTrackingActive) { - const timestamp = performance.now() - recordingStartTime - const event: MouseEvent = { - type: 'down', - timestamp, - x: e.x, - y: e.y, - button: e.button, - clicks: e.clicks - } - mouseEventData.push(event) - } - }) - - // Track mouse button release - uIOhook.on('mouseup', (e) => { - if (isMouseTrackingActive) { - const timestamp = performance.now() - recordingStartTime - const event: MouseEvent = { - type: 'up', - timestamp, - x: e.x, - y: e.y, - button: e.button - } - mouseEventData.push(event) - } - }) - - // Track complete click events - uIOhook.on('click', (e) => { - if (isMouseTrackingActive) { - const timestamp = performance.now() - recordingStartTime - const event: MouseEvent = { - type: 'click', - timestamp, - x: e.x, - y: e.y, - button: e.button, - clicks: e.clicks - } - mouseEventData.push(event) - } - }) -} - -export function getTrackingData(): MouseEvent[] { - return [...mouseEventData] -} - -export function cleanupMouseTracking() { - if (isHookStarted) { - try { - uIOhook.stop() - isHookStarted = false - isMouseTrackingActive = false - mouseEventData = [] - } catch (error) { - console.error('Error cleaning up mouse tracking:', error) - } - } -} diff --git a/electron/main.ts b/electron/main.ts index 2051eb8..c126494 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -4,7 +4,7 @@ import path from 'node:path' import fs from 'node:fs/promises' import { createHudOverlayWindow, createEditorWindow, createSourceSelectorWindow } from './windows' import { registerIpcHandlers } from './ipc/handlers' -import { cleanupMouseTracking } from './ipc/mouseTracking' + const __dirname = path.dirname(fileURLToPath(import.meta.url)) @@ -126,7 +126,7 @@ app.on('activate', () => { // Cleanup old recordings on quit (both macOS and other platforms) app.on('before-quit', async (event) => { event.preventDefault() - cleanupMouseTracking() + await cleanupOldRecordings() app.exit(0) }) diff --git a/electron/preload.ts b/electron/preload.ts index 2b94f79..192cc45 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -20,18 +20,11 @@ contextBridge.exposeInMainWorld('electronAPI', { getSelectedSource: () => { return ipcRenderer.invoke('get-selected-source') }, - startMouseTracking: () => { - return ipcRenderer.invoke('start-mouse-tracking') - }, - stopMouseTracking: () => { - return ipcRenderer.invoke('stop-mouse-tracking') - }, + storeRecordedVideo: (videoData: ArrayBuffer, fileName: string) => { return ipcRenderer.invoke('store-recorded-video', videoData, fileName) }, - storeMouseTrackingData: (fileName: string) => { - return ipcRenderer.invoke('store-mouse-tracking-data', fileName) - }, + getRecordedVideoPath: () => { return ipcRenderer.invoke('get-recorded-video-path') }, diff --git a/package-lock.json b/package-lock.json index 633a32a..f87cfe3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,8 +29,7 @@ "react-icons": "^5.5.0", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", - "tailwindcss-animate": "^1.0.7", - "uiohook-napi": "^1.5.4" + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@types/react": "^18.2.64", @@ -9384,6 +9383,7 @@ "version": "4.8.4", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "dev": true, "license": "MIT", "bin": { "node-gyp-build": "bin.js", @@ -12262,19 +12262,6 @@ "node": ">=14.17" } }, - "node_modules/uiohook-napi": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/uiohook-napi/-/uiohook-napi-1.5.4.tgz", - "integrity": "sha512-7vPVDNwgb6MwTgviA/dnF2MrW0X5xm76fAqaOAC3cEKkswqAZOPw1USu14Sr6383s5qhXegcJaR63CpJOPCNAg==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-gyp-build": "4.x.x" - }, - "engines": { - "node": ">= 16" - } - }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", diff --git a/package.json b/package.json index c2a8b9b..84dc6fc 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,7 @@ "react-icons": "^5.5.0", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", - "tailwindcss-animate": "^1.0.7", - "uiohook-napi": "^1.5.4" + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@types/react": "^18.2.64", diff --git a/src/hooks/useScreenRecorder.ts b/src/hooks/useScreenRecorder.ts index f38a804..f8477d8 100644 --- a/src/hooks/useScreenRecorder.ts +++ b/src/hooks/useScreenRecorder.ts @@ -20,7 +20,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn { } mediaRecorder.current.stop(); setRecording(false); - window.electronAPI.stopMouseTracking(); + window.electronAPI?.setRecordingState(false); } }); @@ -54,7 +54,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn { alert("Please select a source to record"); return; } - await window.electronAPI.startMouseTracking(); + // Capture screen at source resolution without constraints const mediaStream = await (navigator.mediaDevices as any).getUserMedia({ audio: false, @@ -109,7 +109,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn { chunks.current = []; const timestamp = Date.now(); const videoFileName = `recording-${timestamp}.webm`; - const trackingFileName = `recording-${timestamp}_tracking.json`; + try { const videoBlob = await fixWebmDuration(buggyBlob, duration); const arrayBuffer = await videoBlob.arrayBuffer(); @@ -118,10 +118,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn { console.error('Failed to store video:', videoResult.message); return; } - const trackingResult = await window.electronAPI.storeMouseTrackingData(trackingFileName); - if (!trackingResult.success) { - console.warn('Failed to store mouse tracking:', trackingResult.message); - } + await window.electronAPI.switchToEditor(); } catch (error) { console.error('Error saving recording:', error); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index c5ec8ec..257c1e3 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -16,21 +16,12 @@ interface Window { openSourceSelector: () => Promise selectSource: (source: any) => Promise getSelectedSource: () => Promise - startMouseTracking: () => Promise<{ success: boolean; startTime?: number }> - stopMouseTracking: () => Promise<{ success: boolean; data?: any }> storeRecordedVideo: (videoData: ArrayBuffer, fileName: string) => Promise<{ success: boolean path?: string message: string error?: string }> - storeMouseTrackingData: (fileName: string) => Promise<{ - success: boolean - path?: string - eventCount?: number - message: string - error?: string - }> getRecordedVideoPath: () => Promise<{ success: boolean path?: string diff --git a/vite.config.ts b/vite.config.ts index 589d3f7..e6b6840 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -14,9 +14,7 @@ export default defineConfig({ entry: 'electron/main.ts', vite: { build: { - rollupOptions: { - external: ['uiohook-napi'] - } + } } },