Created
May 4, 2021 20:47
-
-
Save holtwick/2ddb3a2347945edba204a5230303b1da to your computer and use it in GitHub Desktop.
yjs-vue3-experiment.vue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="test-sfu"> | |
<div class="prose"> | |
<h1> | |
<router-link to="/test">Test Vue3 + Yjs</router-link> | |
</h1> | |
<p>Experiment to combine Vue3 reactivity and Yjs realtime sync.</p> | |
<p> | |
Play around on the console by changing values of | |
<code>window.realtime</code> | |
object, like <code>window.realtime.left.test = 123</code>. | |
</p> | |
</div> | |
<div class="test-sfu-videos"> | |
<div> | |
Left | |
<tw-debug :data="realtime.left" /> | |
</div> | |
<div> | |
Right | |
<tw-debug :data="realtime.right" /> | |
</div> | |
</div> | |
<tw-debug :data="realtime" level="3" /> | |
</div> | |
</template> | |
<style lang="stylus"> | |
@require "../twindy/index.styl" | |
.test-sfu | |
margin 24 | |
.test-sfu-videos | |
display grid | |
grid-template-columns: repeat(2, minmax(50%, 400px)) | |
gap 24px | |
margin-y 24 | |
</style> | |
<script lang="ts"> | |
import { Logger } from "@/lib/log" | |
import { state } from "@/state" | |
import { cloneObject, deepEqual } from "lib" | |
import { twDebug } from "twindy-headless" | |
import { defineComponent, reactive, watch } from "vue" | |
import * as Y from "yjs" | |
const log = Logger("test-realtime") | |
const doc1 = new Y.Doc() | |
const doc2 = new Y.Doc() | |
doc1.on("update", (update: Uint8Array) => { | |
log("doc left to right apply", update.length) | |
Y.applyUpdate(doc2, update) | |
}) | |
doc2.on("update", (update: Uint8Array) => { | |
log("doc right to left apply", update.length) | |
Y.applyUpdate(doc1, update) | |
}) | |
const realtime = reactive({ | |
left: { | |
left: "left", | |
}, | |
right: { | |
right: "right", | |
}, | |
}) | |
let left = doc1.getMap("demo") | |
left.observe(() => { | |
let value = cloneObject(left.toJSON()) | |
log("left observed change", value) | |
Object.assign(realtime.left, value) // in place | |
}) | |
let right = doc2.getMap("demo") | |
right.observe(() => { | |
let value = cloneObject(right.toJSON()) | |
log("right observed change", value) | |
Object.assign(realtime.right, value) // in place | |
}) | |
function sync(reactiveObj, realtimeObj) { | |
let obj = cloneObject(reactiveObj) | |
let yobj = realtimeObj.toJSON() | |
Object.entries(obj).forEach(([key, value]) => { | |
const eq = deepEqual(value, yobj[key]) | |
log("sync", eq, key, value, yobj[key]) | |
if (!eq) { | |
realtimeObj.set(key, value as any) | |
} | |
}) | |
} | |
watch(realtime.left, (obj) => { | |
log("watched realtime.left", obj) | |
sync(realtime.left, left) | |
}) | |
watch(realtime.right, (obj) => { | |
log("watched realtime.right", obj) | |
sync(realtime.right, right) | |
}) | |
// @ts-ignore | |
window.realtime = realtime | |
export default defineComponent({ | |
components: { | |
twDebug, | |
}, | |
setup() { | |
return { | |
state, | |
realtime, | |
} | |
}, | |
}) | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Online demo https://viidoo.it/test/test-realtime