mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
refactor: better error handling
This commit is contained in:
@@ -157,16 +157,16 @@ export function TimelineElement({
|
|||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const success = await replaceElementMedia(track.id, element.id, file);
|
const result = await replaceElementMedia(track.id, element.id, file);
|
||||||
if (success) {
|
if (result.success) {
|
||||||
toast.success("Clip replaced successfully");
|
toast.success("Clip replaced successfully");
|
||||||
} else {
|
} else {
|
||||||
toast.error("Failed to replace clip");
|
toast.error(result.error || "Failed to replace clip");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error("Failed to replace clip");
|
console.error("Unexpected error replacing clip:", error);
|
||||||
console.log(
|
toast.error(
|
||||||
JSON.stringify({ error: "Failed to replace clip", details: error })
|
`Unexpected error: ${error instanceof Error ? error.message : "Unknown error"}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ interface TimelineStore {
|
|||||||
trackId: string,
|
trackId: string,
|
||||||
elementId: string,
|
elementId: string,
|
||||||
newFile: File
|
newFile: File
|
||||||
) => Promise<boolean>;
|
) => Promise<{ success: boolean; error?: string }>;
|
||||||
|
|
||||||
// Ripple editing functions
|
// Ripple editing functions
|
||||||
updateElementStartTimeWithRipple: (
|
updateElementStartTimeWithRipple: (
|
||||||
@@ -1077,18 +1077,33 @@ export const useTimelineStore = create<TimelineStore>((set, get) => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Replace media for an element
|
// Replace media for an element
|
||||||
replaceElementMedia: async (trackId, elementId, newFile) => {
|
replaceElementMedia: async (
|
||||||
|
trackId: string,
|
||||||
|
elementId: string,
|
||||||
|
newFile: File
|
||||||
|
): Promise<{ success: boolean; error?: string }> => {
|
||||||
const { _tracks } = get();
|
const { _tracks } = get();
|
||||||
const track = _tracks.find((t) => t.id === trackId);
|
const track = _tracks.find((t) => t.id === trackId);
|
||||||
const element = track?.elements.find((c) => c.id === elementId);
|
const element = track?.elements.find((c) => c.id === elementId);
|
||||||
|
|
||||||
if (!element || element.type !== "media") return false;
|
if (!element) {
|
||||||
|
return { success: false, error: "Timeline element not found" };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.type !== "media") {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "Replace is only available for media clips",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const mediaStore = useMediaStore.getState();
|
const mediaStore = useMediaStore.getState();
|
||||||
const projectStore = useProjectStore.getState();
|
const projectStore = useProjectStore.getState();
|
||||||
|
|
||||||
if (!projectStore.activeProject) return false;
|
if (!projectStore.activeProject) {
|
||||||
|
return { success: false, error: "No active project found" };
|
||||||
|
}
|
||||||
|
|
||||||
// Import required media processing functions
|
// Import required media processing functions
|
||||||
const {
|
const {
|
||||||
@@ -1099,7 +1114,13 @@ export const useTimelineStore = create<TimelineStore>((set, get) => {
|
|||||||
} = await import("./media-store");
|
} = await import("./media-store");
|
||||||
|
|
||||||
const fileType = getFileType(newFile);
|
const fileType = getFileType(newFile);
|
||||||
if (!fileType) return false;
|
if (!fileType) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error:
|
||||||
|
"Unsupported file type. Please select a video, audio, or image file.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Process the new media file
|
// Process the new media file
|
||||||
const mediaData: any = {
|
const mediaData: any = {
|
||||||
@@ -1109,15 +1130,18 @@ export const useTimelineStore = create<TimelineStore>((set, get) => {
|
|||||||
url: URL.createObjectURL(newFile),
|
url: URL.createObjectURL(newFile),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
// Get media-specific metadata
|
// Get media-specific metadata
|
||||||
if (fileType === "image") {
|
if (fileType === "image") {
|
||||||
const { width, height } = await getImageDimensions(newFile);
|
const { width, height } = await getImageDimensions(newFile);
|
||||||
mediaData.width = width;
|
mediaData.width = width;
|
||||||
mediaData.height = height;
|
mediaData.height = height;
|
||||||
} else if (fileType === "video") {
|
} else if (fileType === "video") {
|
||||||
const [duration, { thumbnailUrl, width, height }] = await Promise.all(
|
const [duration, { thumbnailUrl, width, height }] =
|
||||||
[getMediaDuration(newFile), generateVideoThumbnail(newFile)]
|
await Promise.all([
|
||||||
);
|
getMediaDuration(newFile),
|
||||||
|
generateVideoThumbnail(newFile),
|
||||||
|
]);
|
||||||
mediaData.duration = duration;
|
mediaData.duration = duration;
|
||||||
mediaData.thumbnailUrl = thumbnailUrl;
|
mediaData.thumbnailUrl = thumbnailUrl;
|
||||||
mediaData.width = width;
|
mediaData.width = width;
|
||||||
@@ -1125,16 +1149,37 @@ export const useTimelineStore = create<TimelineStore>((set, get) => {
|
|||||||
} else if (fileType === "audio") {
|
} else if (fileType === "audio") {
|
||||||
mediaData.duration = await getMediaDuration(newFile);
|
mediaData.duration = await getMediaDuration(newFile);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: `Failed to process ${fileType} file: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Add new media item to store
|
// Add new media item to store
|
||||||
await mediaStore.addMediaItem(projectStore.activeProject.id, mediaData);
|
try {
|
||||||
|
await mediaStore.addMediaItem(
|
||||||
|
projectStore.activeProject.id,
|
||||||
|
mediaData
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: `Failed to add media to project: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Find the newly created media item
|
// Find the newly created media item
|
||||||
const newMediaItem = mediaStore.mediaItems.find(
|
const newMediaItem = mediaStore.mediaItems.find(
|
||||||
(item) => item.file === newFile
|
(item) => item.file === newFile
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!newMediaItem) return false;
|
if (!newMediaItem) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "Failed to create media item in project. Please try again.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
get().pushHistory();
|
get().pushHistory();
|
||||||
|
|
||||||
@@ -1160,15 +1205,13 @@ export const useTimelineStore = create<TimelineStore>((set, get) => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(
|
console.error("Failed to replace element media:", error);
|
||||||
JSON.stringify({
|
return {
|
||||||
error: "Failed to replace element media",
|
success: false,
|
||||||
details: error,
|
error: `Unexpected error: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
})
|
};
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user