« get me outta code hell

ui.js - mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
path: root/ui.js
blob: 26aa12e9b1c4ce4d34cd5b959bdf01e9dd426077 (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
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
const ansi = require('./tui-lib/util/ansi')
const Button = require('./tui-lib/ui/form/Button')
const FocusElement = require('./tui-lib/ui/form/FocusElement')
const ListScrollForm = require('./tui-lib/ui/form/ListScrollForm')
const Pane = require('./tui-lib/ui/Pane')
const RecordStore = require('./record-store')

class AppElement extends FocusElement {
  constructor(internalApp) {
    super()

    this.internalApp = internalApp
    this.recordStore = new RecordStore()

    this.pane = new Pane()
    this.addChild(this.pane)

    this.grouplikeListingElement = new GrouplikeListingElement(this.recordStore)
    this.pane.addChild(this.grouplikeListingElement)
  }

  fixLayout() {
    this.w = this.parent.contentW
    this.h = this.parent.contentH

    this.pane.w = this.contentW
    this.pane.h = this.contentH

    this.grouplikeListingElement.w = this.pane.contentW
    this.grouplikeListingElement.h = this.pane.contentH
  }

  keyPressed(keyBuf) {
    if (keyBuf[0] === 0x03) { // ^C
      this.emit('quitRequested')
      return
    }

    super.keyPressed(keyBuf)
  }
}

class GrouplikeListingElement extends ListScrollForm {
  constructor(recordStore) {
    super('vertical')

    this.grouplike = null
    this.recordStore = recordStore
  }

  loadGrouplike(grouplike) {
    this.grouplike = grouplike
    this.buildItems()
  }

  buildItems() {
    if (!this.grouplike) {
      throw new Error('Attempted to call buildItems before a grouplike was loaded')
    }

    for (const item of this.grouplike.items) {
      this.addInput(new GrouplikeItemElement(item, this.recordStore))
    }

    this.fixLayout()
  }
}

class GrouplikeItemElement extends Button {
  constructor(item, recordStore) {
    super()

    this.item = item
    this.recordStore = recordStore
  }

  fixLayout() {
    this.w = this.parent.contentW
    this.h = 1
  }

  drawTo(writable) {
    if (this.isFocused) {
      writable.write(ansi.invert())
    }

    writable.write(ansi.moveCursor(this.absTop, this.absLeft))
    this.drawX = this.x
    this.writeStatus(writable)
    this.drawX += this.item.name.length
    writable.write(this.item.name)
    writable.write(' '.repeat(this.w - this.drawX))

    writable.write(ansi.resetAttributes())
  }

  writeStatus(writable) {
    this.drawX += 3

    const braille = '⠈⠐⠠⠄⠂⠁'
    const brailleChar = braille[Math.floor(Date.now() / 250) % 6]

    writable.write(' ')
    if (this.recordStore.getRecord(this.item).downloading) {
      writable.write(braille[Math.floor(Date.now() / 250) % 6])
    } else {
      writable.write(' ')
    }
    writable.write(' ')
  }
}

module.exports.AppElement = AppElement