Fix Shopify video preview propagation on save

Updates logic to detect processing state (including READY-but-no-sources race condition) and propagates contentUrl updates to the frontend immediately.
This commit is contained in:
Ben Miller
2025-12-31 01:08:12 -07:00
parent 772957058d
commit 64ab548593
4 changed files with 46 additions and 1 deletions

View File

@ -464,7 +464,7 @@
style="display:none; background-color:#fffbeb; color:#92400e; padding:12px; border-radius:8px; margin: 0 16px 12px 16px; font-size:13px; border:1px solid #fcd34d; align-items:flex-start; gap:8px;">
<span style="font-size:16px; line-height:1;"></span>
<div>
Some videos are still being transcoded by Drive. The video preview might not work yet, but they can still be saved,
Some videos are still being processed. The video preview might not work yet, but they can still be saved,
reordered, or deleted.
</div>
</div>
@ -1516,6 +1516,8 @@
console.log("[MediaManager] Processing complete for " + item.filename);
item.isProcessing = false;
item.thumbnail = newItem.thumbnail;
item.contentUrl = newItem.contentUrl; // Propagate URL
item.source = newItem.source; // Propagate source update (synced)
changed = true;
}
}

View File

@ -304,4 +304,29 @@ describe("MediaService Robust Sync", () => {
expect(item.isProcessing).toBe(true)
expect(item.thumbnail).toContain("data:image/svg+xml;base64")
})
test("Processing: Marks item as processing if Shopify status is PROCESSING", () => {
const folder = driveService.getOrCreateFolder("SKU_SHOP_PROCESS", "root")
// Drive File
const blob = { getName: () => "vid.mp4", getBytes: () => [], getMimeType: () => "video/mp4", getThumbnail: () => ({ getBytes: () => [] }) } as any
const f = driveService.saveFile(blob, folder.getId())
driveService.updateFileProperties(f.getId(), { shopify_media_id: "gid://shopify/Media/Proc1" })
// Shopify Media (Processing)
shopifyService.getProductMedia = jest.fn().mockReturnValue([
{
id: "gid://shopify/Media/Proc1",
filename: "vid.mp4",
mediaContentType: "VIDEO",
status: "PROCESSING",
preview: { image: { originalSrc: null } } // Preview might be missing during processing
}
])
const state = mediaService.getUnifiedMediaState("SKU_SHOP_PROCESS", "pid")
const item = state.find(s => s.id === f.getId())
expect(item.isProcessing).toBe(true)
})
})

View File

@ -106,6 +106,8 @@ export class MediaService {
if (props['custom_thumbnail_id']) customThumbnailId = props['custom_thumbnail_id'];
if (props['parent_video_id']) parentVideoId = props['parent_video_id'];
console.log(`[DEBUG] File ${f.getName()} Props:`, JSON.stringify(props));
} catch (e) {
console.warn(`Failed to get properties for ${f.getName()}`)
}
@ -239,6 +241,21 @@ export class MediaService {
console.log(`[MediaService] Using Sidecar Thumbnail for ${d.file.getName()}`);
thumbnail = sidecarThumbMap.get(d.file.getId()) || "";
isProcessing = true; // SHOW HOURGLASS (Request #3)
} else if (match && (
match.status === 'PROCESSING' ||
match.status === 'UPLOADED' ||
(match.mediaContentType === 'VIDEO' && (!match.sources || match.sources.length === 0) && match.status !== 'FAILED')
)) {
// Shopify Processing (Explicit Status OR Ready-but-missing-sources)
console.log(`[MediaService] Shopify Media is Processing: ${d.file.getName()} (Status: ${match.status}, Sources: ${match.sources ? match.sources.length : 0})`);
isProcessing = true;
// Use Drive thumb as fallback if Shopify preview not ready
if (!thumbnail) {
try {
const nativeThumb = `data:image/jpeg;base64,${Utilities.base64Encode(d.file.getThumbnail().getBytes())}`;
if (nativeThumb.length > 100) thumbnail = nativeThumb;
} catch(e) {}
}
} else {
// 2. Native / Fallback
try {

View File

@ -73,6 +73,7 @@ export class ShopifyMediaService implements IShopifyMediaService {
id
alt
mediaContentType
status
preview {
image {
originalSrc