feat: add version history and AI diff highlighting in editor
This commit is contained in:
@@ -1,6 +1,22 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { shallowRef, ref, computed, triggerRef } from 'vue'
|
||||
import type { GameData, SceneNode, Choice } from '@engine/types'
|
||||
import { putVersion, getVersions } from '../db/editorDB'
|
||||
|
||||
export interface AIDiff {
|
||||
added: string[]
|
||||
modified: string[]
|
||||
deleted: string[]
|
||||
globalFields: string[]
|
||||
}
|
||||
|
||||
interface EditorVersion {
|
||||
id?: number
|
||||
sourcePath: string
|
||||
timestamp: number
|
||||
label: string
|
||||
gameData: GameData
|
||||
}
|
||||
|
||||
export const useEditorStore = defineStore('editor', () => {
|
||||
const gameData = shallowRef<GameData>({ scenes: {}, startScene: '', variables: {} })
|
||||
@@ -11,6 +27,8 @@ export const useEditorStore = defineStore('editor', () => {
|
||||
const deepseekKey = ref(localStorage.getItem('deepseek_key') || '')
|
||||
const showAIPanel = ref(false)
|
||||
const aiSessionId = ref('')
|
||||
const aiChanges = ref<AIDiff | null>(null)
|
||||
const versions = ref<EditorVersion[]>([])
|
||||
|
||||
const selectedScene = computed(() => {
|
||||
if (!selectedNodeId.value) return null
|
||||
@@ -151,11 +169,64 @@ export const useEditorStore = defineStore('editor', () => {
|
||||
} catch { /* dev server not running */ }
|
||||
}
|
||||
|
||||
async function reloadFromDisk() {
|
||||
async function saveVersion(label: string) {
|
||||
try {
|
||||
await putVersion({
|
||||
sourcePath: sourcePath.value,
|
||||
timestamp: Date.now(),
|
||||
label,
|
||||
gameData: JSON.parse(JSON.stringify(gameData.value)),
|
||||
})
|
||||
await loadVersions()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
async function restoreVersion(idx: number) {
|
||||
const v = versions.value[idx]
|
||||
if (!v) return
|
||||
gameData.value = v.gameData
|
||||
startSceneId.value = v.gameData.startScene || ''
|
||||
selectedNodeId.value = null
|
||||
aiChanges.value = null
|
||||
dirty.value = false
|
||||
autoSave()
|
||||
}
|
||||
|
||||
async function loadVersions() {
|
||||
try {
|
||||
versions.value = await getVersions(sourcePath.value)
|
||||
} catch {
|
||||
versions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
function clearAIMarkers() {
|
||||
aiChanges.value = null
|
||||
}
|
||||
|
||||
async function reloadFromDisk(oldGameData?: GameData) {
|
||||
try {
|
||||
const resp = await fetch(sourcePath.value)
|
||||
const data = await resp.json()
|
||||
gameData.value = data
|
||||
const newData = await resp.json()
|
||||
if (oldGameData) {
|
||||
const { scenes: newScenes, ...newGlobal } = newData
|
||||
const { scenes: oldScenes, ...oldGlobal } = oldGameData
|
||||
const diff: AIDiff = { added: [], modified: [], deleted: [], globalFields: [] }
|
||||
for (const id of Object.keys(newScenes)) {
|
||||
if (!oldScenes[id]) diff.added.push(id)
|
||||
else if (JSON.stringify(oldScenes[id]) !== JSON.stringify(newScenes[id])) diff.modified.push(id)
|
||||
}
|
||||
for (const id of Object.keys(oldScenes)) {
|
||||
if (!newScenes[id]) diff.deleted.push(id)
|
||||
}
|
||||
for (const key of Object.keys({ ...(oldGlobal as any), ...(newGlobal as any) })) {
|
||||
if (JSON.stringify((oldGlobal as any)[key]) !== JSON.stringify((newGlobal as any)[key])) {
|
||||
diff.globalFields.push(key)
|
||||
}
|
||||
}
|
||||
aiChanges.value = diff
|
||||
}
|
||||
gameData.value = newData
|
||||
selectedNodeId.value = null
|
||||
clearAISession()
|
||||
} catch { /* failed to reload */ }
|
||||
@@ -163,9 +234,10 @@ export const useEditorStore = defineStore('editor', () => {
|
||||
|
||||
return {
|
||||
gameData, selectedNodeId, selectedScene, startSceneId, dirty, sourcePath,
|
||||
deepseekKey, showAIPanel, aiSessionId,
|
||||
deepseekKey, showAIPanel, aiSessionId, aiChanges, versions,
|
||||
markDirty, loadJSON, exportJSON, addScene, deleteScene,
|
||||
updateScene, addChoice, updateChoice, deleteChoice, generateId,
|
||||
setSourcePath, setDeepseekKey, setAISessionId, clearAISession, autoSave, reloadFromDisk,
|
||||
saveVersion, restoreVersion, loadVersions, clearAIMarkers,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user