diff --git a/src/view/com/composer/state/composer.ts b/src/view/com/composer/state/composer.ts index 75ea8153cf..080d860012 100644 --- a/src/view/com/composer/state/composer.ts +++ b/src/view/com/composer/state/composer.ts @@ -82,6 +82,8 @@ export type PostAction = type: 'embed_add_video' asset: ImagePickerAsset abortController: AbortController + /** Optional localRefPath for draft restoration */ + localRefPath?: string } | {type: 'embed_remove_video'} | {type: 'embed_update_video'; videoAction: VideoAction} @@ -120,6 +122,13 @@ export type ComposerAction = postId: string postAction: PostAction } + | { + /** Like update_post but doesn't mark the composer as dirty. + * Used when restoring video from draft to avoid triggering "unsaved changes" prompt. */ + type: 'restore_video_to_post' + postId: string + postAction: PostAction + } | { type: 'add_post' } @@ -202,6 +211,29 @@ export function composerReducer( }, } } + case 'restore_video_to_post': { + // Same as update_post but WITHOUT setting isDirty: true + // Used when restoring video from draft to avoid triggering "unsaved changes" prompt + let nextPosts = state.thread.posts + const postIndex = state.thread.posts.findIndex( + p => p.id === action.postId, + ) + if (postIndex !== -1) { + nextPosts = state.thread.posts.slice() + nextPosts[postIndex] = postReducer( + state.thread.posts[postIndex], + action.postAction, + ) + } + return { + ...state, + // isDirty intentionally NOT set to true + thread: { + ...state.thread, + posts: nextPosts, + }, + } + } case 'add_post': { const activePostIndex = state.activePostIndex const nextPosts = [...state.thread.posts] @@ -413,7 +445,11 @@ function postReducer(state: PostDraft, action: PostAction): PostDraft { if (!prevMedia) { nextMedia = { type: 'video', - video: createVideoState(action.asset, action.abortController), + video: createVideoState( + action.asset, + action.abortController, + action.localRefPath, + ), } } return {