Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1783,7 +1783,12 @@ const messageHandlers: Record<string, (ctx: MessageHandlerContext) => Promise<vo
const oldKind = classifyVideo(oldVideoUrl);
const newKind = classifyVideo(newVideoUrl);
if (oldKind === "local") {
const proceed = await confirmVideoReplacement(oldKind, newKind);
// The metadata modal already runs a robust type-to-confirm step
// before any video removal/replace, so it sets skipVideoConfirm to
// avoid a redundant second prompt. Other callers still confirm.
const proceed = typedEvent.skipVideoConfirm
? true
: await confirmVideoReplacement(oldKind, newKind);
if (!proceed) {
// Revert the webview's optimistic edit by re-sending current
// metadata, and restore the player's URL to the unchanged video.
Expand Down Expand Up @@ -2044,15 +2049,18 @@ const messageHandlers: Record<string, (ctx: MessageHandlerContext) => Promise<vo
}
},

pickVideoFile: async ({ document, webviewPanel, provider }) => {
pickVideoFile: async ({ event, document, webviewPanel, provider }) => {
debug("pickVideoFile message received");
const typedEvent = event as Extract<EditorPostMessages, { command: "pickVideoFile"; }>;

// If a local video already exists, confirm replacement up front so the
// user can back out before choosing a new file (deletion happens after
// the new file is written successfully).
// the new file is written successfully). The metadata modal only reveals
// the picker after its own type-to-confirm removal step, so it sets
// skipVideoConfirm to avoid a redundant prompt.
const existingVideoUrl = document.getNotebookMetadata()?.videoUrl;
const existingKind = classifyVideo(existingVideoUrl);
if (existingKind === "local") {
if (existingKind === "local" && !typedEvent.skipVideoConfirm) {
const proceed = await confirmVideoReplacement("local", "local");
if (!proceed) {
return;
Expand Down
6 changes: 3 additions & 3 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,8 @@ export type EditorPostMessages =
| { command: "updateCellLabel"; content: { cellId: string; cellLabel: string; }; }
| { command: "updateCellIsLocked"; content: { cellId: string; isLocked: boolean; }; }
| { command: "resolveHtmlStructure"; content: { cellId: string; }; }
| { command: "updateNotebookMetadata"; content: CustomNotebookMetadata; }
| { command: "pickVideoFile"; }
| { command: "updateNotebookMetadata"; content: CustomNotebookMetadata; skipVideoConfirm?: boolean; }
| { command: "pickVideoFile"; skipVideoConfirm?: boolean; }
| { command: "deleteVideoFile"; }
| { command: "freeVideoDiskSpace"; }
| { command: "requestVideoStreamUrl"; }
Expand Down Expand Up @@ -470,7 +470,7 @@ export type EditorPostMessages =
| { command: "updateTextDirection"; direction: "ltr" | "rtl"; }
| { command: "openSourceText"; content: { chapterNumber: number; }; }
| { command: "updateCellLabel"; content: { cellId: string; cellLabel: string; }; }
| { command: "pickVideoFile"; }
| { command: "pickVideoFile"; skipVideoConfirm?: boolean; }
| {
command: "exportFile";
content: { subtitleData: string; format: string; includeStyles: boolean; };
Expand Down
12 changes: 11 additions & 1 deletion webviews/codex-webviews/src/CodexCellEditor/CodexCellEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3061,7 +3061,13 @@ const CodexCellEditor: React.FC = () => {
};

const handlePickFile = () => {
vscode.postMessage({ command: "pickVideoFile" } as EditorPostMessages);
// The metadata modal only exposes the file picker once the video field is
// empty, which requires passing its type-to-confirm removal step first.
// So the host's own replace/delete confirmation would be redundant here.
vscode.postMessage({
command: "pickVideoFile",
skipVideoConfirm: true,
} as EditorPostMessages);
};

// Stream-and-save: revert the downloaded local copy back to an LFS pointer to
Expand All @@ -3079,9 +3085,13 @@ const CodexCellEditor: React.FC = () => {
setMetadata(updatedMetadata);
setVideoUrl(updatedMetadata.videoUrl || "");
debug("metadata", "Saving metadata:", updatedMetadata);
// Any video change in the modal already passed its robust type-to-confirm
// removal step, so the host's own replace/delete confirmation would be a
// redundant second prompt — skip it. The host still deletes the old file.
vscode.postMessage({
command: "updateNotebookMetadata",
content: updatedMetadata,
skipVideoConfirm: true,
} as EditorPostMessages);
setIsMetadataModalOpen(false);
};
Expand Down
Loading
Loading