mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
feat: undo for when an element gets deleted from media item deletion
This commit is contained in:
@@ -207,17 +207,29 @@ export const useMediaStore = create<MediaStore>((set, get) => ({
|
|||||||
removeElementFromTrack,
|
removeElementFromTrack,
|
||||||
removeElementFromTrackWithRipple,
|
removeElementFromTrackWithRipple,
|
||||||
rippleEditingEnabled,
|
rippleEditingEnabled,
|
||||||
|
pushHistory,
|
||||||
} = timeline;
|
} = timeline;
|
||||||
|
|
||||||
// Iterate over a snapshot of tracks and their elements
|
// Find all elements that reference this media
|
||||||
|
const elementsToRemove: Array<{ trackId: string; elementId: string }> = [];
|
||||||
for (const track of tracks) {
|
for (const track of tracks) {
|
||||||
for (const el of track.elements) {
|
for (const el of track.elements) {
|
||||||
if (el.type === "media" && el.mediaId === id) {
|
if (el.type === "media" && el.mediaId === id) {
|
||||||
if (rippleEditingEnabled) {
|
elementsToRemove.push({ trackId: track.id, elementId: el.id });
|
||||||
removeElementFromTrackWithRipple(track.id, el.id);
|
}
|
||||||
} else {
|
}
|
||||||
removeElementFromTrack(track.id, el.id);
|
}
|
||||||
}
|
|
||||||
|
// If there are elements to remove, push history once before batch removal
|
||||||
|
if (elementsToRemove.length > 0) {
|
||||||
|
pushHistory();
|
||||||
|
|
||||||
|
// Remove all elements without pushing additional history entries
|
||||||
|
for (const { trackId, elementId } of elementsToRemove) {
|
||||||
|
if (rippleEditingEnabled) {
|
||||||
|
removeElementFromTrackWithRipple(trackId, elementId, false);
|
||||||
|
} else {
|
||||||
|
removeElementFromTrack(trackId, elementId, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,11 @@ interface TimelineStore {
|
|||||||
removeTrack: (trackId: string) => void;
|
removeTrack: (trackId: string) => void;
|
||||||
removeTrackWithRipple: (trackId: string) => void;
|
removeTrackWithRipple: (trackId: string) => void;
|
||||||
addElementToTrack: (trackId: string, element: CreateTimelineElement) => void;
|
addElementToTrack: (trackId: string, element: CreateTimelineElement) => void;
|
||||||
removeElementFromTrack: (trackId: string, elementId: string) => void;
|
removeElementFromTrack: (
|
||||||
|
trackId: string,
|
||||||
|
elementId: string,
|
||||||
|
pushHistory?: boolean
|
||||||
|
) => void;
|
||||||
moveElementToTrack: (
|
moveElementToTrack: (
|
||||||
fromTrackId: string,
|
fromTrackId: string,
|
||||||
toTrackId: string,
|
toTrackId: string,
|
||||||
@@ -156,7 +160,8 @@ interface TimelineStore {
|
|||||||
) => void;
|
) => void;
|
||||||
removeElementFromTrackWithRipple: (
|
removeElementFromTrackWithRipple: (
|
||||||
trackId: string,
|
trackId: string,
|
||||||
elementId: string
|
elementId: string,
|
||||||
|
pushHistory?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
// Computed values
|
// Computed values
|
||||||
@@ -553,13 +558,13 @@ export const useTimelineStore = create<TimelineStore>((set, get) => {
|
|||||||
get().selectElement(trackId, newElement.id);
|
get().selectElement(trackId, newElement.id);
|
||||||
},
|
},
|
||||||
|
|
||||||
removeElementFromTrack: (trackId, elementId) => {
|
removeElementFromTrack: (trackId, elementId, pushHistory = true) => {
|
||||||
const { rippleEditingEnabled } = get();
|
const { rippleEditingEnabled } = get();
|
||||||
|
|
||||||
if (rippleEditingEnabled) {
|
if (rippleEditingEnabled) {
|
||||||
get().removeElementFromTrackWithRipple(trackId, elementId);
|
get().removeElementFromTrackWithRipple(trackId, elementId, pushHistory);
|
||||||
} else {
|
} else {
|
||||||
get().pushHistory();
|
if (pushHistory) get().pushHistory();
|
||||||
updateTracksAndSave(
|
updateTracksAndSave(
|
||||||
get()
|
get()
|
||||||
._tracks.map((track) =>
|
._tracks.map((track) =>
|
||||||
@@ -577,12 +582,16 @@ export const useTimelineStore = create<TimelineStore>((set, get) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
removeElementFromTrackWithRipple: (trackId, elementId) => {
|
removeElementFromTrackWithRipple: (
|
||||||
|
trackId,
|
||||||
|
elementId,
|
||||||
|
pushHistory = true
|
||||||
|
) => {
|
||||||
const { _tracks, rippleEditingEnabled } = get();
|
const { _tracks, rippleEditingEnabled } = get();
|
||||||
|
|
||||||
if (!rippleEditingEnabled) {
|
if (!rippleEditingEnabled) {
|
||||||
// If ripple editing is disabled, use regular removal
|
// If ripple editing is disabled, use regular removal
|
||||||
get().removeElementFromTrack(trackId, elementId);
|
get().removeElementFromTrack(trackId, elementId, pushHistory);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,7 +600,7 @@ export const useTimelineStore = create<TimelineStore>((set, get) => {
|
|||||||
|
|
||||||
if (!element || !track) return;
|
if (!element || !track) return;
|
||||||
|
|
||||||
get().pushHistory();
|
if (pushHistory) get().pushHistory();
|
||||||
|
|
||||||
const elementStartTime = element.startTime;
|
const elementStartTime = element.startTime;
|
||||||
const elementDuration =
|
const elementDuration =
|
||||||
|
|||||||
Reference in New Issue
Block a user