fix rendering issue from v1 to current

This commit is contained in:
Maze Winther
2026-02-05 14:44:31 +01:00
parent d0b4b1a5fc
commit 464a6e83b9
5 changed files with 62 additions and 42 deletions
+1 -1
View File
@@ -862,7 +862,7 @@ function ProjectsSkeleton() {
); );
return ( return (
<div className="xs:grid-cols-2 grid grid-cols-1 gap-6 sm:grid-cols-3 lg:grid-cols-4"> <div className="px-4 xs:grid-cols-2 grid grid-cols-1 gap-6 sm:grid-cols-3 lg:grid-cols-4">
{skeletonIds.map((skeletonId) => ( {skeletonIds.map((skeletonId) => (
<Card <Card
key={skeletonId} key={skeletonId}
@@ -29,10 +29,9 @@ export function buildScene(params: BuildSceneParams) {
(track) => !("hidden" in track && track.hidden), (track) => !("hidden" in track && track.hidden),
); );
const mainTrack = visibleTracks.find((track) => isMainTrack(track)) ?? null;
const orderedTracksTopToBottom = [ const orderedTracksTopToBottom = [
...visibleTracks.filter((track) => !isMainTrack(track)), ...visibleTracks.filter((track) => !isMainTrack(track)),
...(mainTrack ? [mainTrack] : []), ...visibleTracks.filter((track) => isMainTrack(track)),
]; ];
const orderedTracksBottomToTop = orderedTracksTopToBottom.slice().reverse(); const orderedTracksBottomToTop = orderedTracksTopToBottom.slice().reverse();
@@ -19,6 +19,8 @@ export interface MigrationProgress {
let hasCleanedUpMetaDb = false; let hasCleanedUpMetaDb = false;
const MIN_MIGRATION_DISPLAY_MS = 1000;
export async function runStorageMigrations({ export async function runStorageMigrations({
migrations, migrations,
onProgress, onProgress,
@@ -45,6 +47,7 @@ export async function runStorageMigrations({
const orderedMigrations = [...migrations].sort((a, b) => a.from - b.from); const orderedMigrations = [...migrations].sort((a, b) => a.from - b.from);
let migratedCount = 0; let migratedCount = 0;
let migrationStartTime: number | null = null;
for (const project of projects) { for (const project of projects) {
if (typeof project !== "object" || project === null) { if (typeof project !== "object" || project === null) {
@@ -59,6 +62,11 @@ export async function runStorageMigrations({
continue; continue;
} }
// Track when we first showed the migration dialog
if (migrationStartTime === null) {
migrationStartTime = Date.now();
}
const projectName = getProjectName({ project: projectRecord }); const projectName = getProjectName({ project: projectRecord });
onProgress?.({ onProgress?.({
isMigrating: true, isMigrating: true,
@@ -90,6 +98,16 @@ export async function runStorageMigrations({
} }
} }
// Ensure dialog is visible for minimum time so users can see it
if (migrationStartTime !== null) {
const elapsed = Date.now() - migrationStartTime;
if (elapsed < MIN_MIGRATION_DISPLAY_MS) {
await new Promise((resolve) =>
setTimeout(resolve, MIN_MIGRATION_DISPLAY_MS - elapsed),
);
}
}
onProgress?.({ onProgress?.({
isMigrating: false, isMigrating: false,
fromVersion: null, fromVersion: null,
@@ -26,7 +26,7 @@ interface LegacyMediaElement {
type: "media"; type: "media";
mediaId: string; mediaId: string;
muted?: boolean; muted?: boolean;
[id: string]: unknown; [key: string]: unknown;
} }
interface LegacyTextElement { interface LegacyTextElement {
@@ -35,19 +35,19 @@ interface LegacyTextElement {
y: number; y: number;
rotation: number; rotation: number;
opacity: number; opacity: number;
[id: string]: unknown; [key: string]: unknown;
} }
interface LegacyAudioElement { interface LegacyAudioElement {
type: "audio"; type: "audio";
mediaId: string; mediaId: string;
[id: string]: unknown; [key: string]: unknown;
} }
interface LegacyMediaTrack { interface LegacyMediaTrack {
type: "media"; type: "media";
elements: unknown[]; elements: unknown[];
[id: string]: unknown; [key: string]: unknown;
} }
export interface TransformV1ToV2Options { export interface TransformV1ToV2Options {
@@ -265,35 +265,38 @@ async function transformTracks({
} }
let isFirstVideoTrackFound = false; let isFirstVideoTrackFound = false;
const transformedTracks: (TimelineTrack | null)[] = [];
const transformedTracks = await Promise.all( for (const track of tracks) {
tracks.map(async (track) => { if (!isRecord(track)) {
if (!isRecord(track)) { transformedTracks.push(null);
return null; continue;
} }
const trackType = track.type; const trackType = track.type;
if (trackType === "media") { if (trackType === "media") {
const videoTrack = await transformMediaTrack({ const videoTrack = await transformMediaTrack({
track: track as LegacyMediaTrack, track: track as LegacyMediaTrack,
loadMediaAsset, loadMediaAsset,
isMain: !isFirstVideoTrackFound, isMain: !isFirstVideoTrackFound,
}); });
isFirstVideoTrackFound = true; isFirstVideoTrackFound = true;
return videoTrack; transformedTracks.push(videoTrack);
} continue;
}
if (trackType === "text") { if (trackType === "text") {
return transformTextTrack({ track }); transformedTracks.push(transformTextTrack({ track }));
} continue;
}
if (trackType === "audio") { if (trackType === "audio") {
return transformAudioTrack({ track }); transformedTracks.push(transformAudioTrack({ track }));
} continue;
}
return null; transformedTracks.push(null);
}), }
);
return transformedTracks.filter( return transformedTracks.filter(
(track): track is TimelineTrack => track !== null, (track): track is TimelineTrack => track !== null,
@@ -33,8 +33,7 @@ export class V1toV2Migration extends StorageMigration {
}); });
if (!result.skipped) { if (!result.skipped) {
// cleanup legacy timeline DBs after successful transformation void cleanupLegacyTimelineDBs({
await cleanupLegacyTimelineDBs({
projectId, projectId,
project: result.project, project: result.project,
}); });
@@ -60,13 +59,13 @@ function createMediaAssetLoader({
}; };
} }
async function cleanupLegacyTimelineDBs({ function cleanupLegacyTimelineDBs({
projectId, projectId,
project, project,
}: { }: {
projectId: string; projectId: string;
project: ProjectRecord; project: ProjectRecord;
}): Promise<void> { }): void {
const scenes = project.scenes; const scenes = project.scenes;
if (!Array.isArray(scenes)) { if (!Array.isArray(scenes)) {
return; return;
@@ -89,11 +88,12 @@ async function cleanupLegacyTimelineDBs({
const projectDbName = `video-editor-timelines-${projectId}`; const projectDbName = `video-editor-timelines-${projectId}`;
dbNamesToDelete.push(projectDbName); dbNamesToDelete.push(projectDbName);
for (const dbName of dbNamesToDelete) { // Fire-and-forget: delete in parallel, don't block migration
try { void Promise.all(
await deleteDatabase({ dbName }); dbNamesToDelete.map((dbName) =>
} catch { deleteDatabase({ dbName }).catch(() => {
// ignore errors, DB might not exist or already deleted // ignore errors, DB might not exist or already deleted
} }),
} ),
);
} }