diff --git a/dist-electron/main.js b/dist-electron/main.js index d7413f4..7e1a226 100644 --- a/dist-electron/main.js +++ b/dist-electron/main.js @@ -1,19 +1,14 @@ -import { ipcMain, screen, BrowserWindow, desktopCapturer, shell, app, dialog, nativeImage, Tray, Menu } from "electron"; -import { fileURLToPath } from "node:url"; -import path from "node:path"; -import fs from "node:fs/promises"; -const __dirname$2 = path.dirname(fileURLToPath(import.meta.url)); -const APP_ROOT = path.join(__dirname$2, ".."); -const VITE_DEV_SERVER_URL$1 = process.env["VITE_DEV_SERVER_URL"]; -const RENDERER_DIST$1 = path.join(APP_ROOT, "dist"); -let hudOverlayWindow = null; -ipcMain.on("hud-overlay-hide", () => { - if (hudOverlayWindow && !hudOverlayWindow.isDestroyed()) { - hudOverlayWindow.minimize(); - } +import { ipcMain as n, screen as b, BrowserWindow as R, desktopCapturer as V, shell as O, app as d, dialog as S, nativeImage as W, Tray as k, Menu as L } from "electron"; +import { fileURLToPath as E } from "node:url"; +import o from "node:path"; +import P from "node:fs/promises"; +const _ = o.dirname(E(import.meta.url)), U = o.join(_, ".."), m = process.env.VITE_DEV_SERVER_URL, T = o.join(U, "dist"); +let f = null; +n.on("hud-overlay-hide", () => { + f && !f.isDestroyed() && f.minimize(); }); function C() { - const r = b.getPrimaryDisplay(), { workArea: n } = r, c = 500, w = 100, y = Math.floor(n.x + (n.width - c) / 2), h = Math.floor(n.y + n.height - w - 5), e = new R({ + const r = b.getPrimaryDisplay(), { workArea: s } = r, c = 500, w = 100, y = Math.floor(s.x + (s.width - c) / 2), h = Math.floor(s.y + s.height - w - 5), e = new R({ width: c, height: w, minWidth: 500, @@ -29,10 +24,10 @@ function C() { skipTaskbar: !0, hasShadow: !1, webPreferences: { - preload: path.join(__dirname$2, "preload.mjs"), - nodeIntegration: false, - contextIsolation: true, - backgroundThrottling: false + preload: o.join(_, "preload.mjs"), + nodeIntegration: !1, + contextIsolation: !0, + backgroundThrottling: !1 } }); return e.webContents.on("did-finish-load", () => { @@ -58,11 +53,11 @@ function M() { title: "OpenScreen", backgroundColor: "#000000", webPreferences: { - preload: path.join(__dirname$2, "preload.mjs"), - nodeIntegration: false, - contextIsolation: true, - webSecurity: false, - backgroundThrottling: false + preload: o.join(_, "preload.mjs"), + nodeIntegration: !1, + contextIsolation: !0, + webSecurity: !1, + backgroundThrottling: !1 } }); return r.maximize(), r.webContents.on("did-finish-load", () => { @@ -72,22 +67,22 @@ function M() { }), r; } function A() { - const { width: r, height: n } = b.getPrimaryDisplay().workAreaSize, c = new R({ + const { width: r, height: s } = b.getPrimaryDisplay().workAreaSize, c = new R({ width: 620, height: 420, minHeight: 350, maxHeight: 500, x: Math.round((r - 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: path.join(__dirname$2, "preload.mjs"), - nodeIntegration: false, - contextIsolation: true + preload: o.join(_, "preload.mjs"), + nodeIntegration: !1, + contextIsolation: !0 } }); return m ? c.loadURL(m + "?windowType=source-selector") : c.loadFile(o.join(T, "index.html"), { @@ -95,31 +90,31 @@ function A() { }), c; } let v = null; -function H(r, n, c, w, y) { - i.handle("get-sources", async (e, s) => (await V.getSources(s)).map((t) => ({ +function H(r, s, c, w, y) { + n.handle("get-sources", async (e, a) => (await V.getSources(a)).map((t) => ({ id: t.id, name: t.name, display_id: t.display_id, thumbnail: t.thumbnail ? t.thumbnail.toDataURL() : null, appIcon: t.appIcon ? t.appIcon.toDataURL() : null - }))), i.handle("select-source", (e, s) => { - v = s; - const a = w(); - return a && a.close(), v; - }), i.handle("get-selected-source", () => v), i.handle("open-source-selector", () => { + }))), n.handle("select-source", (e, a) => { + v = a; + const i = w(); + return i && i.close(), v; + }), n.handle("get-selected-source", () => v), n.handle("open-source-selector", () => { const e = w(); if (e) { e.focus(); return; } - n(); - }), i.handle("switch-to-editor", () => { + s(); + }), n.handle("switch-to-editor", () => { const e = c(); e && e.close(), r(); - }), i.handle("store-recorded-video", async (e, s, a) => { + }), n.handle("store-recorded-video", async (e, a, i) => { try { - const t = o.join(p, a); - return await P.writeFile(t, Buffer.from(s)), h = t, { + const t = o.join(p, i); + return await P.writeFile(t, Buffer.from(a)), h = t, { success: !0, path: t, message: "Video stored successfully" @@ -131,35 +126,35 @@ function H(r, n, c, w, y) { error: String(t) }; } - }), i.handle("get-recorded-video-path", async () => { + }), n.handle("get-recorded-video-path", async () => { try { - const s = (await P.readdir(p)).filter((j) => j.endsWith(".webm")); - if (s.length === 0) + const a = (await P.readdir(p)).filter((j) => j.endsWith(".webm")); + if (a.length === 0) return { success: !1, message: "No recorded video found" }; - const a = s.sort().reverse()[0]; - return { success: !0, path: o.join(p, a) }; + const i = a.sort().reverse()[0]; + return { success: !0, path: o.join(p, i) }; } catch (e) { return console.error("Failed to get video path:", e), { success: !1, message: "Failed to get video path", error: String(e) }; } - }), i.handle("set-recording-state", (e, s) => { - y && y(s, (v || { name: "Screen" }).name); - }), i.handle("open-external-url", async (e, s) => { + }), n.handle("set-recording-state", (e, a) => { + y && y(a, (v || { name: "Screen" }).name); + }), n.handle("open-external-url", async (e, a) => { try { - return await O.openExternal(s), { success: !0 }; - } catch (a) { - return console.error("Failed to open URL:", a), { success: !1, error: String(a) }; + return await O.openExternal(a), { success: !0 }; + } catch (i) { + return console.error("Failed to open URL:", i), { success: !1, error: String(i) }; } - }), i.handle("get-asset-base-path", () => { + }), n.handle("get-asset-base-path", () => { try { return d.isPackaged ? o.join(process.resourcesPath, "assets") : o.join(d.getAppPath(), "public", "assets"); } catch (e) { return console.error("Failed to resolve asset base path:", e), null; } - }), i.handle("save-exported-video", async (e, s, a) => { + }), n.handle("save-exported-video", async (e, a, i) => { try { const t = await S.showSaveDialog({ title: "Save Exported Video", - defaultPath: o.join(d.getPath("downloads"), a), + defaultPath: o.join(d.getPath("downloads"), i), filters: [ { name: "MP4 Video", extensions: ["mp4"] } ], @@ -169,7 +164,7 @@ function H(r, n, c, w, y) { success: !1, cancelled: !0, message: "Export cancelled" - } : (await P.writeFile(t.filePath, Buffer.from(s)), { + } : (await P.writeFile(t.filePath, Buffer.from(a)), { success: !0, path: t.filePath, message: "Video exported successfully" @@ -181,7 +176,7 @@ function H(r, n, c, w, y) { error: String(t) }; } - }), i.handle("open-video-file-picker", async () => { + }), n.handle("open-video-file-picker", async () => { try { const e = await S.showOpenDialog({ title: "Select Video File", @@ -204,47 +199,28 @@ function H(r, n, c, w, y) { }; } }); - let currentVideoPath = null; - ipcMain.handle("set-current-video-path", (_, path2) => { - currentVideoPath = path2; - return { success: true }; - }); - ipcMain.handle("get-current-video-path", () => { - return currentVideoPath ? { success: true, path: currentVideoPath } : { success: false }; - }); - ipcMain.handle("clear-current-video-path", () => { - currentVideoPath = null; - return { success: true }; - }); - ipcMain.handle("get-platform", () => { - return process.platform; - }); + let h = null; + n.handle("set-current-video-path", (e, a) => (h = a, { success: !0 })), n.handle("get-current-video-path", () => h ? { success: !0, path: h } : { success: !1 }), n.handle("clear-current-video-path", () => (h = null, { success: !0 })), n.handle("get-platform", () => process.platform); } -const __dirname$1 = path.dirname(fileURLToPath(import.meta.url)); -const RECORDINGS_DIR = path.join(app.getPath("userData"), "recordings"); -async function ensureRecordingsDir() { +const z = o.dirname(E(import.meta.url)), p = o.join(d.getPath("userData"), "recordings"); +async function N() { try { await P.mkdir(p, { recursive: !0 }), console.log("RECORDINGS_DIR:", p), console.log("User Data Path:", d.getPath("userData")); } catch (r) { console.error("Failed to create recordings directory:", r); } } -process.env.APP_ROOT = path.join(__dirname$1, ".."); -const VITE_DEV_SERVER_URL = process.env["VITE_DEV_SERVER_URL"]; -const MAIN_DIST = path.join(process.env.APP_ROOT, "dist-electron"); -const RENDERER_DIST = path.join(process.env.APP_ROOT, "dist"); -process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL ? path.join(process.env.APP_ROOT, "public") : RENDERER_DIST; -let mainWindow = null; -let sourceSelectorWindow = null; -let tray = null; -let selectedSourceName = ""; -function createWindow() { - mainWindow = createHudOverlayWindow(); +process.env.APP_ROOT = o.join(z, ".."); +const B = process.env.VITE_DEV_SERVER_URL, Y = o.join(process.env.APP_ROOT, "dist-electron"), D = o.join(process.env.APP_ROOT, "dist"); +process.env.VITE_PUBLIC = B ? o.join(process.env.APP_ROOT, "public") : D; +let l = null, g = null, u = null, x = ""; +function I() { + l = C(); } function q() { const r = o.join(process.env.VITE_PUBLIC || D, "rec-button.png"); - let n = W.createFromPath(r); - n = n.resize({ width: 24, height: 24, quality: "best" }), u = new k(n), F(); + let s = W.createFromPath(r); + s = s.resize({ width: 24, height: 24, quality: "best" }), u = new k(s), F(); } function F() { if (!u) return; @@ -255,8 +231,8 @@ function F() { l && !l.isDestroyed() && l.webContents.send("stop-recording-from-tray"); } } - ], n = L.buildFromTemplate(r); - u.setContextMenu(n), u.setToolTip(`Recording: ${x}`); + ], s = L.buildFromTemplate(r); + u.setContextMenu(s), u.setToolTip(`Recording: ${x}`); } function $() { l && (l.close(), l = null), l = M(); @@ -280,8 +256,8 @@ d.whenReady().then(async () => { G, () => l, () => g, - (n, c) => { - x = c, n ? (u || q(), F()) : (u && (u.destroy(), u = null), l && l.restore()); + (s, c) => { + x = c, s ? (u || q(), F()) : (u && (u.destroy(), u = null), l && l.restore()); } ), I(); }); diff --git a/dist-electron/preload.mjs b/dist-electron/preload.mjs index cb59604..ba75414 100644 --- a/dist-electron/preload.mjs +++ b/dist-electron/preload.mjs @@ -1,63 +1 @@ -"use strict"; -const electron = require("electron"); -electron.contextBridge.exposeInMainWorld("electronAPI", { - hudOverlayHide: () => { - electron.ipcRenderer.send("hud-overlay-hide"); - }, - hudOverlayClose: () => { - electron.ipcRenderer.send("hud-overlay-close"); - }, - getAssetBasePath: async () => { - return await electron.ipcRenderer.invoke("get-asset-base-path"); - }, - getSources: async (opts) => { - return await electron.ipcRenderer.invoke("get-sources", opts); - }, - switchToEditor: () => { - return electron.ipcRenderer.invoke("switch-to-editor"); - }, - openSourceSelector: () => { - return electron.ipcRenderer.invoke("open-source-selector"); - }, - selectSource: (source) => { - return electron.ipcRenderer.invoke("select-source", source); - }, - getSelectedSource: () => { - return electron.ipcRenderer.invoke("get-selected-source"); - }, - storeRecordedVideo: (videoData, fileName) => { - return electron.ipcRenderer.invoke("store-recorded-video", videoData, fileName); - }, - getRecordedVideoPath: () => { - return electron.ipcRenderer.invoke("get-recorded-video-path"); - }, - setRecordingState: (recording) => { - return electron.ipcRenderer.invoke("set-recording-state", recording); - }, - onStopRecordingFromTray: (callback) => { - const listener = () => callback(); - electron.ipcRenderer.on("stop-recording-from-tray", listener); - return () => electron.ipcRenderer.removeListener("stop-recording-from-tray", listener); - }, - openExternalUrl: (url) => { - return electron.ipcRenderer.invoke("open-external-url", url); - }, - saveExportedVideo: (videoData, fileName) => { - return electron.ipcRenderer.invoke("save-exported-video", videoData, fileName); - }, - openVideoFilePicker: () => { - return electron.ipcRenderer.invoke("open-video-file-picker"); - }, - setCurrentVideoPath: (path) => { - return electron.ipcRenderer.invoke("set-current-video-path", path); - }, - getCurrentVideoPath: () => { - return electron.ipcRenderer.invoke("get-current-video-path"); - }, - clearCurrentVideoPath: () => { - return electron.ipcRenderer.invoke("clear-current-video-path"); - }, - getPlatform: () => { - return electron.ipcRenderer.invoke("get-platform"); - } -}); +"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),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"),getPlatform:()=>e.ipcRenderer.invoke("get-platform")}); diff --git a/package-lock.json b/package-lock.json index 8b11eb4..ae1ae23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openscreen", - "version": "0.0.0", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openscreen", - "version": "0.0.0", + "version": "1.0.0", "dependencies": { "@fix-webm-duration/fix": "^1.0.1", "@pixi/filter-drop-shadow": "^5.2.0", @@ -26,6 +26,7 @@ "clsx": "^2.1.1", "dnd-timeline": "^2.2.0", "emoji-picker-react": "^4.16.1", + "fix-webm-duration": "^1.0.6", "gsap": "^3.13.0", "lucide-react": "^0.545.0", "mediabunny": "^1.25.1", @@ -7085,6 +7086,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fix-webm-duration": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fix-webm-duration/-/fix-webm-duration-1.0.6.tgz", + "integrity": "sha512-zVAqi4gE+8ywxJuAyV/rlJVX6CMtvyapEbQx6jyoeX9TMjdqAlt/FdG5d7rXSSkDVzTvS0H7CtwzHcH/vh4FPA==", + "license": "MIT" + }, "node_modules/flairup": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/flairup/-/flairup-1.0.0.tgz", diff --git a/package.json b/package.json index 561806b..1854ca2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "openscreen", "private": true, - "version": "1.0.0", + "version": "1.0.1", "type": "module", "scripts": { "dev": "vite", @@ -30,6 +30,7 @@ "clsx": "^2.1.1", "dnd-timeline": "^2.2.0", "emoji-picker-react": "^4.16.1", + "fix-webm-duration": "^1.0.6", "gsap": "^3.13.0", "lucide-react": "^0.545.0", "mediabunny": "^1.25.1", @@ -70,4 +71,4 @@ "vite-plugin-electron-renderer": "^0.14.5" }, "main": "dist-electron/main.js" -} \ No newline at end of file +} diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index 50dd24d..328d56c 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -30,6 +30,7 @@ import { } from "./types"; import { VideoExporter, type ExportProgress, type ExportQuality } from "@/lib/exporter"; import { type AspectRatio, getAspectRatioValue } from "@/utils/aspectRatioUtils"; +import { getAssetPath } from "@/lib/assetPath"; const WALLPAPER_COUNT = 18; const WALLPAPER_PATHS = Array.from({ length: WALLPAPER_COUNT }, (_, i) => `/wallpapers/wallpaper${i + 1}.jpg`); @@ -104,6 +105,23 @@ export default function VideoEditor() { loadVideo(); }, []); + // Initialize default wallpaper with resolved asset path + useEffect(() => { + let mounted = true; + (async () => { + try { + const resolvedPath = await getAssetPath('wallpapers/wallpaper1.jpg'); + if (mounted) { + setWallpaper(resolvedPath); + } + } catch (err) { + // If resolution fails, keep the fallback + console.warn('Failed to resolve default wallpaper path:', err); + } + })(); + return () => { mounted = false }; + }, []); + function togglePlayPause() { const playback = videoPlaybackRef.current; const video = playback?.video;