fix(tiktok): tile-level compliance is lenient when media has another viable variant

Reverts the previous reactive watcher approach. Replaces it with two
small, declarative changes:

1. platformIssues for TikTok now checks whether ANY variant
   (tiktok_video / tiktok_photo) accepts the current media. The tile
   only stays blocked when neither variant fits (e.g. a GIF, mixed
   media). This matches the platform's real capability — TikTok does
   accept both videos and photos — and stops disabling the tile based
   on the post-platform's stale default content_type.

2. togglePlatform, when SELECTING TikTok, switches the post-platform's
   content_type to the variant that matches the first attached media
   (tiktok_video for video, tiktok_photo for image). Runs only on
   selection, not as a watcher — no implicit reactivity, no side
   effects on subsequent media changes. The variant picker inside
   TikTokSettings remains the user's manual override.

Reproducer fixed: new post → attach image → TikTok tile is now
clickable instead of greyed out with 'Only videos are allowed for
this format'. After clicking, content_type is tiktok_photo.
This commit is contained in:
Paulo Castellano 2026-05-09 14:22:15 -03:00
parent 28e368796a
commit 967c1481d3

View file

@ -223,6 +223,18 @@ const platformIssues = computed<Record<string, string>>(() => {
continue;
}
// TikTok has two content types (video / photo) that the user toggles
// inside TikTokSettings. The tile-level check is lenient: a tile is
// only blocked when neither variant accepts the current media. If the
// current variant doesn't fit but the other one does, togglePlatform
// auto-corrects on selection.
if (pp.platform === Platform.TikTok) {
const videoReason = getMediaIncompatibilityReason('tiktok_video', media.value);
const photoReason = getMediaIncompatibilityReason('tiktok_photo', media.value);
if (videoReason && photoReason) issues[pp.id] = videoReason;
continue;
}
const reason = getMediaIncompatibilityReason(contentType, media.value);
if (reason) issues[pp.id] = reason;
}
@ -331,12 +343,30 @@ const togglePlatform = (platformId: string) => {
if (isReadOnly.value) return;
const index = selectedPlatformIds.value.indexOf(platformId);
if (index === -1) {
adjustTikTokContentTypeForMedia(platformId);
selectedPlatformIds.value.push(platformId);
} else {
selectedPlatformIds.value.splice(index, 1);
}
};
// TikTok has two content types (video, photo) backed by different API endpoints.
// When the user picks the TikTok tile while media is already attached, switch
// to the matching variant so they don't land on tiktok_video with images and
// see a compliance error. The variant picker in TikTokSettings can still override.
const adjustTikTokContentTypeForMedia = (platformId: string) => {
const pp = post.value.post_platforms.find((p) => p.id === platformId);
if (!pp || pp.platform !== Platform.TikTok || media.value.length === 0) return;
const first = media.value[0];
const isImage = first.type === 'image' || first.mime_type?.startsWith('image/');
const isVideo = first.type === 'video' || first.mime_type?.startsWith('video/');
const target = isImage ? 'tiktok_photo' : isVideo ? 'tiktok_video' : null;
if (!target || platformContentTypes.value[platformId] === target) return;
platformContentTypes.value = { ...platformContentTypes.value, [platformId]: target };
};
// Save logic
const getSubmitData = () => {
const platforms = post.value.post_platforms
@ -392,28 +422,6 @@ const triggerAutosave = () => {
}
};
// Auto-switch TikTok content_type to match the attached media. Without this,
// a fresh post defaults TikTok to tiktok_video, so attaching images first
// disables the TikTok tile (compliance check rejects images for video posts).
// User can still override via the variant picker in TikTokSettings.
watch(media, () => {
if (media.value.length === 0) return;
const first = media.value[0];
const isVideo = first.type === 'video' || first.mime_type?.startsWith('video/');
const isImage = first.type === 'image' || first.mime_type?.startsWith('image/');
const target = isVideo ? 'tiktok_video' : isImage ? 'tiktok_photo' : null;
if (!target) return;
for (const pp of post.value.post_platforms) {
if (pp.platform !== Platform.TikTok) continue;
const current = platformContentTypes.value[pp.id];
if (current && current !== target && (current === 'tiktok_video' || current === 'tiktok_photo')) {
platformContentTypes.value = { ...platformContentTypes.value, [pp.id]: target };
}
}
}, { deep: true });
watch([content, media, selectedPlatformIds, scheduledDateTime, selectedLabelIds, platformMeta, platformContentTypes], triggerAutosave, { deep: true });
onUnmounted(() => {