@@ -80,6 +80,12 @@ function normalizeProjectSaveName(projectName?: string | null) {
8080 return sanitizedName || null ;
8181}
8282
83+ type NamedProjectSaveMode = "rename" | "copy" ;
84+
85+ function normalizeNamedProjectSaveMode ( value : unknown ) : NamedProjectSaveMode {
86+ return value === "copy" ? "copy" : "rename" ;
87+ }
88+
8389/**
8490 * Extracts the persisted source video path from a saved project payload.
8591 */
@@ -292,8 +298,10 @@ export function registerProjectHandlers() {
292298 try {
293299 const projectsDir = await getProjectsDir ( )
294300 const preparedProject = ensureProjectDataHasProjectId ( projectData )
295- const trustedExistingProjectPath = isTrustedProjectPath ( existingProjectPath )
296- ? existingProjectPath
301+ const trustedExistingProjectPath = existingProjectPath &&
302+ path . extname ( existingProjectPath ) . toLowerCase ( ) === `.${ PROJECT_FILE_EXTENSION } ` &&
303+ ( isTrustedProjectPath ( existingProjectPath ) || isPathInsideDirectory ( existingProjectPath , projectsDir ) )
304+ ? path . resolve ( existingProjectPath )
297305 : null
298306
299307 if ( trustedExistingProjectPath ) {
@@ -309,6 +317,13 @@ export function registerProjectHandlers() {
309317 }
310318 }
311319
320+ if ( existingProjectPath ) {
321+ return {
322+ success : false ,
323+ message : 'Project path is no longer trusted. Use Save As to choose a project file.' ,
324+ }
325+ }
326+
312327 const safeName = normalizeProjectSaveName ( suggestedName ) || `project-${ Date . now ( ) } `
313328 const defaultName = `${ safeName } .${ PROJECT_FILE_EXTENSION } `
314329
@@ -351,7 +366,7 @@ export function registerProjectHandlers() {
351366 }
352367 } )
353368
354- ipcMain . handle ( 'save-project-file-named' , async ( _ , projectData : unknown , projectName : string , thumbnailDataUrl ?: string | null ) => {
369+ ipcMain . handle ( 'save-project-file-named' , async ( _ , projectData : unknown , projectName : string , thumbnailDataUrl ?: string | null , mode ?: unknown ) => {
355370 try {
356371 const normalizedProjectName = normalizeProjectSaveName ( projectName )
357372 if ( ! normalizedProjectName ) {
@@ -362,14 +377,30 @@ export function registerProjectHandlers() {
362377 }
363378
364379 const projectsDir = await getProjectsDir ( )
365- const preparedProject = ensureProjectDataHasProjectId ( projectData )
380+ const namedSaveMode = normalizeNamedProjectSaveMode ( mode )
366381 const activeProjectPath = isTrustedProjectPath ( currentProjectPath )
367382 ? currentProjectPath
368383 : null
369384 const targetProjectPath = path . join (
370385 projectsDir ,
371386 `${ normalizedProjectName } .${ PROJECT_FILE_EXTENSION } ` ,
372387 )
388+ const [ activeResolvedPath , targetResolvedPath ] = await Promise . all ( [
389+ activeProjectPath ? resolveComparablePath ( activeProjectPath ) : Promise . resolve ( null ) ,
390+ resolveComparablePath ( targetProjectPath ) ,
391+ ] )
392+ const isSavingToDifferentPath =
393+ ! activeResolvedPath || activeResolvedPath !== targetResolvedPath
394+ const preparedProject =
395+ namedSaveMode === "copy" && isSavingToDifferentPath
396+ ? ( ( ) => {
397+ const projectId = randomUUID ( )
398+ return {
399+ projectId,
400+ projectData : withProjectId ( projectData , projectId ) ,
401+ }
402+ } ) ( )
403+ : ensureProjectDataHasProjectId ( projectData )
373404
374405 const overwriteCheck = await ensureNamedProjectSaveDoesNotOverwriteDifferentProject (
375406 targetProjectPath ,
@@ -384,13 +415,7 @@ export function registerProjectHandlers() {
384415 await saveProjectThumbnail ( targetProjectPath , thumbnailDataUrl )
385416 await rememberRecentProject ( targetProjectPath )
386417
387- if ( activeProjectPath ) {
388- const [ activeResolvedPath , targetResolvedPath ] = await Promise . all ( [
389- resolveComparablePath ( activeProjectPath ) ,
390- resolveComparablePath ( targetProjectPath ) ,
391- ] )
392-
393- if ( activeResolvedPath !== targetResolvedPath ) {
418+ if ( namedSaveMode === "rename" && activeProjectPath && isSavingToDifferentPath ) {
394419 await fs . unlink ( activeProjectPath ) . catch ( ( unlinkError : NodeJS . ErrnoException ) => {
395420 if ( unlinkError . code !== 'ENOENT' ) {
396421 throw unlinkError
@@ -407,7 +432,6 @@ export function registerProjectHandlers() {
407432 }
408433 }
409434 await saveRecentProjectPaths ( filteredRecentProjectPaths )
410- }
411435 }
412436
413437 setCurrentProjectPath ( targetProjectPath )
0 commit comments