feat: implement replay system with action dispatchers and context switching between main and playback modes

This commit is contained in:
taDuc
2026-05-15 19:39:02 +07:00
parent 3682f25282
commit 4c81862bb4
15 changed files with 595 additions and 59 deletions
+12 -1
View File
@@ -5,7 +5,7 @@ import type { EntitySnapshot } from "@/uhm/types/entities";
import type { EntitySnapshotOperation } from "@/uhm/types/entities";
import type { Feature, FeatureCollection, Geometry, GeometryEntitySnapshot, GeometrySnapshot } from "@/uhm/types/geo";
import type { EditorSnapshot, Project } from "@/uhm/types/projects";
import type { BattleReplay, EditorSnapshot, Project } from "@/uhm/types/projects";
import type { WikiSnapshot } from "@/uhm/types/wiki";
import type { EntityWikiLinkSnapshot } from "@/uhm/types/projects";
@@ -312,6 +312,7 @@ export function normalizeEditorSnapshot(raw: unknown): EditorSnapshot | null {
wikis,
geometry_entity: geometryEntity || migratedGeometryEntity,
entity_wiki: entityWikis,
replays: Array.isArray(snapshot.replays) ? (snapshot.replays as BattleReplay[]) : undefined,
};
}
@@ -322,6 +323,7 @@ export function buildEditorSnapshot(options: {
snapshotEntities: EntitySnapshot[];
snapshotWikis: WikiSnapshot[];
snapshotEntityWikiLinks: EntityWikiLinkSnapshot[];
replays: BattleReplay[];
previousSnapshot: EditorSnapshot | null;
hasPersistedFeature: (id: Feature["properties"]["id"]) => boolean;
}): EditorSnapshot {
@@ -663,6 +665,7 @@ export function buildEditorSnapshot(options: {
}))
.sort((a, b) => a.id.localeCompare(b.id)),
entity_wiki: entityWikis,
replays: options.replays,
};
}
@@ -686,6 +689,14 @@ export function toApiEditorSnapshot(snapshot: EditorSnapshot): EditorSnapshot {
});
}
if (Array.isArray(cloned.replays)) {
cloned.replays = cloned.replays.map((replay) => {
// Strip local-only replay_features before sending to BE
const { replay_features: _, ...rest } = replay;
return rest;
});
}
return cloned;
}