summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/track-element-update.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/timeline/track-element-update.ts')
-rw-r--r--apps/web/src/timeline/track-element-update.ts147
1 files changed, 147 insertions, 0 deletions
diff --git a/apps/web/src/timeline/track-element-update.ts b/apps/web/src/timeline/track-element-update.ts
new file mode 100644
index 00000000..7d86a4e8
--- /dev/null
+++ b/apps/web/src/timeline/track-element-update.ts
@@ -0,0 +1,147 @@
+import type { SceneTracks, TimelineElement, TimelineTrack } from "@/timeline";
+
+export function findTrackInSceneTracks({
+ tracks,
+ trackId,
+}: {
+ tracks: SceneTracks;
+ trackId: string;
+}): TimelineTrack | null {
+ if (tracks.main.id === trackId) {
+ return tracks.main;
+ }
+
+ return (
+ tracks.overlay.find((track) => track.id === trackId) ??
+ tracks.audio.find((track) => track.id === trackId) ??
+ null
+ );
+}
+
+export function updateTrackInSceneTracks({
+ tracks,
+ trackId,
+ update,
+}: {
+ tracks: SceneTracks;
+ trackId: string;
+ update: <TTrack extends TimelineTrack>(track: TTrack) => TTrack;
+}): SceneTracks {
+ if (tracks.main.id === trackId) {
+ return {
+ ...tracks,
+ main: update(tracks.main),
+ };
+ }
+
+ const overlayTrackIndex = tracks.overlay.findIndex((track) => track.id === trackId);
+ if (overlayTrackIndex >= 0) {
+ return {
+ ...tracks,
+ overlay: tracks.overlay.map((track, index) =>
+ index === overlayTrackIndex ? update(track) : track,
+ ),
+ };
+ }
+
+ const audioTrackIndex = tracks.audio.findIndex((track) => track.id === trackId);
+ if (audioTrackIndex >= 0) {
+ return {
+ ...tracks,
+ audio: tracks.audio.map((track, index) =>
+ index === audioTrackIndex ? update(track) : track,
+ ),
+ };
+ }
+
+ return tracks;
+}
+
+function updateElementInTrack<TTrack extends TimelineTrack>({
+ track,
+ elementId,
+ update,
+ elementPredicate,
+}: {
+ track: TTrack;
+ elementId: string;
+ update: (element: TimelineElement) => TimelineElement;
+ elementPredicate?: (element: TimelineElement) => boolean;
+}): TTrack {
+ const nextElements = track.elements.map((element) => {
+ if (element.id !== elementId) {
+ return element;
+ }
+ if (elementPredicate && !elementPredicate(element)) {
+ return element;
+ }
+ return update(element);
+ });
+
+ return {
+ ...track,
+ elements: nextElements,
+ } as TTrack;
+}
+
+export function updateElementInSceneTracks({
+ tracks,
+ trackId,
+ elementId,
+ update,
+ elementPredicate,
+}: {
+ tracks: SceneTracks;
+ trackId: string;
+ elementId: string;
+ update: (element: TimelineElement) => TimelineElement;
+ elementPredicate?: (element: TimelineElement) => boolean;
+}): SceneTracks {
+ if (tracks.main.id === trackId) {
+ return {
+ ...tracks,
+ main: updateElementInTrack({
+ track: tracks.main,
+ elementId,
+ update,
+ elementPredicate,
+ }),
+ };
+ }
+
+ const overlayTrackIndex = tracks.overlay.findIndex((track) => track.id === trackId);
+ if (overlayTrackIndex >= 0) {
+ return {
+ ...tracks,
+ overlay: tracks.overlay.map((track, index) =>
+ index === overlayTrackIndex
+ ? updateElementInTrack({
+ track,
+ elementId,
+ update,
+ elementPredicate,
+ })
+ : track,
+ ),
+ };
+ }
+
+ const audioTrackIndex = tracks.audio.findIndex((track) => track.id === trackId);
+ if (audioTrackIndex >= 0) {
+ return {
+ ...tracks,
+ audio: tracks.audio.map((track, index) =>
+ index === audioTrackIndex
+ ? updateElementInTrack({
+ track,
+ elementId,
+ update,
+ elementPredicate,
+ })
+ : track,
+ ),
+ };
+ }
+
+ return tracks;
+}