11import fs from "node:fs/promises" ;
22import path from "node:path" ;
3+ import { fileURLToPath , pathToFileURL } from "node:url" ;
34import { app , BrowserWindow , desktopCapturer , dialog , ipcMain , screen , shell } from "electron" ;
45import { RECORDINGS_DIR } from "../main" ;
56
@@ -18,6 +19,27 @@ function normalizePath(filePath: string) {
1819 return path . resolve ( filePath ) ;
1920}
2021
22+ function normalizeVideoSourcePath ( videoPath ?: string | null ) : string | null {
23+ if ( typeof videoPath !== "string" ) {
24+ return null ;
25+ }
26+
27+ const trimmed = videoPath . trim ( ) ;
28+ if ( ! trimmed ) {
29+ return null ;
30+ }
31+
32+ if ( / ^ f i l e : \/ \/ / i. test ( trimmed ) ) {
33+ try {
34+ return fileURLToPath ( trimmed ) ;
35+ } catch {
36+ // Fall through and keep best-effort string path below.
37+ }
38+ }
39+
40+ return trimmed ;
41+ }
42+
2143function isTrustedProjectPath ( filePath ?: string | null ) {
2244 if ( ! filePath || ! currentProjectPath ) {
2345 return false ;
@@ -199,7 +221,7 @@ export function registerIpcHandlers(
199221 } ) ;
200222
201223 ipcMain . handle ( "get-cursor-telemetry" , async ( _ , videoPath ?: string ) => {
202- const targetVideoPath = videoPath ?? currentVideoPath ;
224+ const targetVideoPath = normalizeVideoSourcePath ( videoPath ?? currentVideoPath ) ;
203225 if ( ! targetVideoPath ) {
204226 return { success : true , samples : [ ] } ;
205227 }
@@ -265,9 +287,11 @@ export function registerIpcHandlers(
265287 ipcMain . handle ( "get-asset-base-path" , ( ) => {
266288 try {
267289 if ( app . isPackaged ) {
268- return path . join ( process . resourcesPath , "assets" ) ;
290+ const assetPath = path . join ( process . resourcesPath , "assets" ) ;
291+ return pathToFileURL ( `${ assetPath } ${ path . sep } ` ) . toString ( ) ;
269292 }
270- return path . join ( app . getAppPath ( ) , "public" , "assets" ) ;
293+ const assetPath = path . join ( app . getAppPath ( ) , "public" , "assets" ) ;
294+ return pathToFileURL ( `${ assetPath } ${ path . sep } ` ) . toString ( ) ;
271295 } catch ( err ) {
272296 console . error ( "Failed to resolve asset base path:" , err ) ;
273297 return null ;
@@ -456,7 +480,7 @@ export function registerIpcHandlers(
456480 const project = JSON . parse ( content ) ;
457481 currentProjectPath = filePath ;
458482 if ( project && typeof project === "object" && typeof project . videoPath === "string" ) {
459- currentVideoPath = project . videoPath ;
483+ currentVideoPath = normalizeVideoSourcePath ( project . videoPath ) ?? project . videoPath ;
460484 }
461485
462486 return {
@@ -483,7 +507,7 @@ export function registerIpcHandlers(
483507 const content = await fs . readFile ( currentProjectPath , "utf-8" ) ;
484508 const project = JSON . parse ( content ) ;
485509 if ( project && typeof project === "object" && typeof project . videoPath === "string" ) {
486- currentVideoPath = project . videoPath ;
510+ currentVideoPath = normalizeVideoSourcePath ( project . videoPath ) ?? project . videoPath ;
487511 }
488512 return {
489513 success : true ,
@@ -500,7 +524,7 @@ export function registerIpcHandlers(
500524 }
501525 } ) ;
502526 ipcMain . handle ( "set-current-video-path" , ( _ , path : string ) => {
503- currentVideoPath = path ;
527+ currentVideoPath = normalizeVideoSourcePath ( path ) ?? path ;
504528 currentProjectPath = null ;
505529 return { success : true } ;
506530 } ) ;
0 commit comments