summaryrefslogtreecommitdiff
path: root/plugins/vue/plugin.js
blob: f7894491377456ae9fa1e0313b81391b08507c12 (plain)
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>'
    })

  }
}