1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
import { ref, reactive } from 'vue'
import Graffiti from '../../graffiti.js'
export default {
install(app, options) {
const graffitiURL = options && 'url' in options?
options.url : 'https://graffiti.garden'
// Initialize graffiti with reactive entries
const graffiti = new Graffiti(graffitiURL, ()=>reactive({}))
// Create a reactive variable that
// tracks connection state
const connectionState = ref(false)
;(function waitForState(state) {
graffiti.connectionState(state).then(()=> {
connectionState.value = state
waitForState(!state)
})})(true)
Object.defineProperty(app.config.globalProperties, "$graffitiConnected", {
get: ()=> connectionState.value
})
// Latch on to the graffiti ID
// when the connection state first becomes true
let myID = null
Object.defineProperty(app.config.globalProperties, "$graffitiMyID", {
get: ()=> {
if (connectionState.value) myID = graffiti.myID
return myID
}
})
// Add static functions
for (const key of ['toggleLogIn', 'update', 'myTags', 'objectByKey']) {
const vueKey = '$graffiti' + key.charAt(0).toUpperCase() + key.slice(1)
app.config.globalProperties[vueKey] = graffiti[key].bind(graffiti)
}
// A component for subscribing and
// unsubscribing to tags that returns
// a reactive array of the results
app.component('GraffitiObjects', {
props: ['tags'],
watch: {
tags: {
async handler(newTags, oldTags=[]) {
// Subscribe to the new tags
await graffiti.subscribe(...newTags)
// Unsubscribe to the existing tags
await graffiti.unsubscribe(...oldTags)
},
immediate: true,
deep: true
}
},
// Handle unmounting too
unmount() {
graffiti.unsubscribe(this.tags)
},
computed: {
objects() {
return graffiti.objectsByTags(...this.tags)
}
},
template: '<slot :objects="objects"></slot>'
})
}
}
|