enso/app/gui2/stories/MockProjectStoreWrapper.vue
Kaz Wesley e0ba39ed3e
Introduce SourceDocument for text edit support (#8957)
Introduce `SourceDocument`, a reactive source code representation that can be synced from a `MutableModule`. `SourceDocument` replaces various logic for tracking source code and spans--most importantly, `ReactiveModule`. There is no longer any reactively-tracked `Module`, per-se: Changes to the `MutableModule` attached to the synchronized `ydoc` are pushed as Y.Js events to the `SourceDocument` and `GraphDb`, which are reactively tracked. This avoids a problem in the upcoming text-synchronization (next PR) that was caused by a reactive back channel bypassing the `GraphDb` and resulting in observation of inconsistent states.

Stacked on #8956. Part of #8238.
2024-02-06 16:44:24 +00:00

51 lines
1.4 KiB
Vue

<script setup lang="ts">
import { useProjectStore } from '@/stores/project'
import { Ast } from '@/util/ast'
import { SourceDocument } from 'shared/ast/sourceDocument'
import { reactive, watch } from 'vue'
const props = defineProps<{ modelValue: string }>()
const emit = defineEmits<{ 'update:modelValue': [modelValue: string] }>()
const projectStore = useProjectStore()
const mod = projectStore.projectModel.createNewModule('Main.enso')
projectStore.setObservedFileName('Main.enso')
mod.doc.ydoc.emit('load', [])
let syncedCode: string | undefined
watch(
() => projectStore.module,
(mod) => {
if (!mod) return
const syncModule = new Ast.MutableModule(mod.doc.ydoc)
applyEdits(syncModule, props.modelValue)
const moduleSource = reactive(SourceDocument.Empty())
syncModule.observe((update) => moduleSource.applyUpdate(syncModule, update))
watch(
() => moduleSource.text,
(text) => {
if (text !== props.modelValue) {
syncedCode = text
emit('update:modelValue', text)
}
},
)
watch(
() => props.modelValue,
(modelValue) => applyEdits(syncModule, modelValue),
)
},
)
function applyEdits(syncModule: Ast.MutableModule, newText: string) {
if (newText !== syncedCode) {
syncModule.ydoc.transact(() => {
syncModule.syncRoot(Ast.parseBlock(newText, syncModule))
}, 'local')
}
}
</script>
<template>
<slot></slot>
</template>