From fb459ad61f21b400d454c160b9a1162c4605833c Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 30 Jan 2026 20:45:07 +0200 Subject: [PATCH] feat(drafts): add restore_video_to_post action to avoid dirty flag Add restore_video_to_post action that updates post state without setting isDirty: true. This prevents drafts with videos from being marked as modified immediately after restoration. Also update embed_add_video action to accept optional localRefPath parameter for preserving video identity across draft saves. Co-Authored-By: Claude Opus 4.5 --- src/view/com/composer/state/composer.ts | 38 ++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) 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 {