~pistos/remoteku

ref: 5d29064489613351dac63d4c7351dec4cf56133a remoteku/frontend/src/views/Home.vue -rw-r--r-- 4.1 KiB
5d290644 — Pistos Add keyboard shortcuts 1 year, 7 months ago
                                                                                
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<template>
<div>
  <div>
    <div v-if="discoveringRokus">
      Finding Roku devices...
    </div>
    <div v-else>
      <div v-if="noRokus">
        No Roku devices found.
      </div>
      <div v-else>
        <div v-if="! rokuHost">
          Choose a Roku device:
        </div>
        <div v-for="(host, index) in rokuHosts" :key="host">
          <input type="radio" :id="`roku-${index}`" :value="host" v-model="rokuHost" />
          <label for="`roku-${index}`">{{host}}</label>
        </div>
      </div>
    </div>
  </div>
  <div v-if="rokuHost">
    <div>
      <img src="/roku-remote.png" alt="Roku remote" usemap="#rokumap"/>
      <map name="rokumap">
        <area shape="rect" coords="124,34,175,86" title="Power" @click="apiPress('power')"/>
        <area shape="rect" coords="40,138,139,187" title="Back" @click="apiPress('back')"/>
        <area shape="rect" coords="161,138,260,187" title="Home" @click="apiPress('home')"/>
        <area shape="rect" coords="112,286,186,356" title="OK" @click="apiPress('select')"/>
        <area shape="rect" coords="49,286,111,356" title="Left" @click="apiPress('left')"/>
        <area shape="rect" coords="187,286,254,356" title="Right" @click="apiPress('right')"/>
        <area shape="rect" coords="112,219,186,285" title="Up" @click="apiPress('up')"/>
        <area shape="rect" coords="112,357,186,425" title="Down" @click="apiPress('down')"/>
        <area shape="rect" coords="36,519,82,588" title="Reverse" @click="apiPress('reverse')"/>
        <area shape="rect" coords="101,519,200,588" title="Play/Pause" @click="apiPress('play')"/>
        <area shape="rect" coords="218,519,260,588" title="Forward" @click="apiPress('forward')"/>
        <area shape="rect" coords="39,460,110,502" title="Replay" @click="apiPress('replay')"/>
        <area shape="rect" coords="125,460,176,502" title="Search/Voice" @click="apiPress('search')"/>
        <area shape="rect" coords="196,460,260,502" title="Info" @click="apiPress('info')"/>
        <area shape="rect" coords="284,409,306,457" title="Mute" @click="apiPress('mute')"/>
      </map>
    </div>
    <div>
      <label>
        Type text:
        <input
          @blur="textFieldFocused = false"
          @focus="textFieldFocused = true"
          @keyup.enter="sendLiteral"
          type="text"
          v-model="literalText"
        />
      </label>
      <button @click="sendLiteral">Enter</button>
      <button @click="apiPress('backspace')">Backspace</button>
    </div>
  </div>
</div>
</template>

<script>
const axios = require('axios')

export default {
  computed: {
    noRokus () {
      return this.rokuHosts.length == 0
    },
  },
  async created () {
    this.discoveringRokus = true
    const res = await axios.get('/api/discover')
    this.rokuHosts = res.data
    this.discoveringRokus = false

    const self = this
    window.addEventListener('keydown', function (e) {
      if (! self.textFieldFocused) {
        if (e.key === 'ArrowRight') { e.preventDefault(); self.apiPress('right') }
        if (e.key === 'ArrowLeft') { e.preventDefault(); self.apiPress('left') }
        if (e.key === 'ArrowUp') { e.preventDefault(); self.apiPress('up') }
        if (e.key === 'ArrowDown') { e.preventDefault(); self.apiPress('down') }
        if (e.key === 'Enter') { e.preventDefault(); self.apiPress('select') }
        if (e.key === 'Escape') { e.preventDefault(); self.apiPress('back') }
        if (e.key === 'Backspace') { e.preventDefault(); self.apiPress('back') }
      }
    });
  },
  data: function () {
    return {
      discoveringRokus: false,
      literalText: '',
      rokuHost: null,
      rokuHosts: [],
      textFieldFocused: false,
    }
  },
  methods: {
    async apiPress (button) {
      await axios.get(`/api/press/${button}`)
    },
    async sendLiteral () {
      await axios.post(
        '/api/literal',
        {string: this.literalText}
      )
      this.literalText = ''
    },
  },
  name: 'Home',
  watch: {
    async rokuHost (newHost) {
      await axios.put(
        '/api/choose-roku',
        {host: newHost}
      )
    },
  },
}
</script>

<style lang="scss">
img {
  margin: 2rem;
}
map {
  area {
    cursor: pointer;
  }
}
</style>