Date: Sat, 30 Sep 2017 21:17:38 +0200
Subject: [PATCH 41/86] term_conf refactor, add color pickers
---
.babelrc | 6 +-
.eslintignore | 3 +-
js/index.js | 2 +
js/lib/color_utils.js | 121 ++++++++
js/lib/colortriangle.js | 604 ++++++++++++++++++++++++++++++++++++++++
js/term/themes.js | 13 +-
js/term_conf.js | 105 +++++++
pages/cfg_term.php | 84 +-----
8 files changed, 846 insertions(+), 92 deletions(-)
create mode 100644 js/lib/color_utils.js
create mode 100644 js/lib/colortriangle.js
create mode 100644 js/term_conf.js
diff --git a/.babelrc b/.babelrc
index d8d6229..e087903 100644
--- a/.babelrc
+++ b/.babelrc
@@ -6,13 +6,9 @@
"last 2 versions",
"> 4%",
"ie 11",
- "safari 8",
- "android 4.4"
+ "safari 8"
]
}
- }],
- ["minify", {
- "mergeVars": false
}]
]
}
diff --git a/.eslintignore b/.eslintignore
index 76fd6af..94e5049 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -2,7 +2,8 @@
out/**/*
# libraries
-js/lib/*
+js/lib/chibi.js
+js/lib/polyfills.js
# php generated file
js/lang.js
diff --git a/js/index.js b/js/index.js
index eff520a..dfb22b0 100644
--- a/js/index.js
+++ b/js/index.js
@@ -14,3 +14,5 @@ window.$ = $
window.qs = qs
window.themes = require('./term/themes')
+
+window.TermConf = require('./term_conf')
diff --git a/js/lib/color_utils.js b/js/lib/color_utils.js
new file mode 100644
index 0000000..74cff36
--- /dev/null
+++ b/js/lib/color_utils.js
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010 Tim Baumann
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// NOTE:
+// Extracted from ColorTriangle and
+// Converted to ES6 by MightyPork (2017)
+
+/*******************
+ * Color conversion *
+ *******************/
+
+const M = Math
+const PI = M.PI
+
+exports.hue_to_rgb = function (v1, v2, h) {
+ if (h < 0) h += 1
+ if (h > 1) h -= 1
+
+ if ((6 * h) < 1) return v1 + (v2 - v1) * 6 * h
+ if ((2 * h) < 1) return v2
+ if ((3 * h) < 2) return v1 + (v2 - v1) * ((2 / 3) - h) * 6
+ return v1
+}
+
+exports.hsl_to_rgb = function (h, s, l) {
+ h /= 2 * PI
+ let r, g, b
+
+ if (s === 0) {
+ r = g = b = l
+ } else {
+ let var_1, var_2
+
+ if (l < 0.5) var_2 = l * (1 + s)
+ else var_2 = (l + s) - (s * l)
+
+ var_1 = 2 * l - var_2
+
+ r = exports.hue_to_rgb(var_1, var_2, h + (1 / 3))
+ g = exports.hue_to_rgb(var_1, var_2, h)
+ b = exports.hue_to_rgb(var_1, var_2, h - (1 / 3))
+ }
+ return [r, g, b]
+}
+
+exports.rgb_to_hsl = function (r, g, b) {
+ const min = M.min(r, g, b)
+ const max = M.max(r, g, b)
+ const d = max - min // delta
+
+ let h, s, l
+
+ l = (max + min) / 2
+
+ if (d === 0) {
+ // gray
+ h = s = 0 // HSL results from 0 to 1
+ } else {
+ // chroma
+ if (l < 0.5) s = d / (max + min)
+ else s = d / (2 - max - min)
+
+ const d_r = (((max - r) / 6) + (d / 2)) / d
+ const d_g = (((max - g) / 6) + (d / 2)) / d
+ const d_b = (((max - b) / 6) + (d / 2)) / d // deltas
+
+ if (r === max) h = d_b - d_g
+ else if (g === max) h = (1 / 3) + d_r - d_b
+ else if (b === max) h = (2 / 3) + d_g - d_r
+
+ if (h < 0) h += 1
+ else if (h > 1) h -= 1
+ }
+ h *= 2 * PI
+ return [h, s, l]
+}
+
+exports.hex_to_rgb = function (hex) {
+ const groups = hex.match(/^#([A-Fa-f0-9]+)$/)
+ if (groups && groups[1].length % 3 === 0) {
+ hex = groups[1]
+ const bytes = hex.length / 3
+ const max = Math.pow(16, bytes) - 1
+ const r = parseInt(hex.slice(0 * bytes, 1 * bytes), 16) / max
+ const g = parseInt(hex.slice(1 * bytes, 2 * bytes), 16) / max
+ const b = parseInt(hex.slice(2 * bytes, 3 * bytes), 16) / max
+ return [r, g, b]
+ }
+ return [0, 0, 0]
+}
+
+function pad (n) {
+ if (n.length === 1) n = '0' + n
+ return n
+}
+
+exports.rgb_to_hex = function (r, g, b) {
+ r = Math.round(r * 255).toString(16)
+ g = Math.round(g * 255).toString(16)
+ b = Math.round(b * 255).toString(16)
+ return `#${pad(r)}${pad(g)}${pad(b)}`
+}
diff --git a/js/lib/colortriangle.js b/js/lib/colortriangle.js
new file mode 100644
index 0000000..2c4e60d
--- /dev/null
+++ b/js/lib/colortriangle.js
@@ -0,0 +1,604 @@
+/*
+ * Copyright (c) 2010 Tim Baumann
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// NOTE: Converted to ES6 by MightyPork (2017)
+
+const {
+ rgb_to_hex,
+ hex_to_rgb,
+ hsl_to_rgb,
+ rgb_to_hsl
+} = require('./color_utils')
+
+const win = window
+const doc = document
+const M = Math
+const PI = M.PI
+
+function times (i, fn) {
+ for (let j = 0; j < i; j++) {
+ fn(j)
+ }
+}
+
+function each (obj, fn) {
+ if (obj.length) {
+ times(obj.length, function (i) {
+ fn(obj[i], i)
+ })
+ } else {
+ for (let key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ fn(obj[key], key)
+ }
+ }
+ }
+}
+
+function getOffsets (el) {
+ let left = 0
+ let top = 0
+
+ while (el !== null) {
+ console.log(el)
+ console.log(el.offsetLeft, el.offsetTop)
+ left += el.offsetLeft
+ top += el.offsetTop
+ el = el.offsetParent
+ }
+
+ return [left, top]
+}
+
+module.exports = class ColorTriangle {
+ /****************
+ * ColorTriangle *
+ ****************/
+
+ // Constructor function:
+ constructor (color, options) {
+ this.options = {
+ size: 150,
+ padding: 8,
+ triangleSize: 0.8,
+ wheelPointerColor1: '#444',
+ wheelPointerColor2: '#eee',
+ trianglePointerSize: 16,
+ // wheelPointerSize: 16,
+ trianglePointerColor1: '#eee',
+ trianglePointerColor2: '#444',
+ background: 'transparent'
+ }
+
+ this._setOptions(options)
+ this._calculateProperties()
+
+ this._createContainer()
+ this._createTriangle()
+ this._createWheel()
+ this._createWheelPointer()
+ this._createTrianglePointer()
+ this._attachEvents()
+
+ color = color || '#f00'
+ if (typeof color == 'string') {
+ this.setHEX(color)
+ }
+ }
+
+ _calculateProperties () {
+ let opts = this.options
+
+ this.padding = opts.padding
+ this.innerSize = opts.size - opts.padding * 2
+ this.triangleSize = opts.triangleSize * this.innerSize
+ this.wheelThickness = (this.innerSize - this.triangleSize) / 2
+ this.wheelPointerSize = opts.wheelPointerSize || this.wheelThickness
+
+ this.wheelRadius = (this.innerSize) / 2
+ this.triangleRadius = (this.triangleSize) / 2
+ this.triangleSideLength = M.sqrt(3) * this.triangleRadius
+ }
+
+ _calculatePositions () {
+ const r = this.triangleRadius
+ const hue = this.hue
+ const third = (2 / 3) * PI
+ const s = this.saturation
+ const l = this.lightness
+
+ // Colored point
+ const hx = this.hx = M.cos(hue) * r
+ const hy = this.hy = -M.sin(hue) * r
+ // Black point
+ const sx = this.sx = M.cos(hue - third) * r
+ const sy = this.sy = -M.sin(hue - third) * r
+ // White point
+ const vx = this.vx = M.cos(hue + third) * r
+ const vy = this.vy = -M.sin(hue + third) * r
+ // Current point
+ const mx = (sx + vx) / 2
+ const my = (sy + vy) / 2
+ const a = (1 - 2 * M.abs(l - 0.5)) * s
+ this.x = sx + (vx - sx) * l + (hx - mx) * a
+ this.y = sy + (vy - sy) * l + (hy - my) * a
+ }
+
+ _createContainer () {
+ let c = this.container = doc.createElement('div')
+ c.className = 'color-triangle'
+
+ c.style.display = 'block'
+ c.style.padding = `${this.padding}px`
+ c.style.position = 'relative'
+ c.style.boxShadow = '0 1px 10px black'
+ c.style.borderRadius = '5px'
+ c.style.width = c.style.height = `${this.innerSize + 2 * this.padding}px`
+ c.style.background = this.options.background
+ }
+
+ _createWheel () {
+ let c = this.wheel = doc.createElement('canvas')
+ c.width = c.height = this.innerSize
+ c.style.position = 'absolute'
+ c.style.margin = c.style.padding = '0'
+ c.style.left = c.style.top = `${this.padding}px`
+
+ this._drawWheel(c.getContext('2d'))
+ this.container.appendChild(c)
+ }
+
+ _drawWheel (ctx) {
+ let s, i
+
+ ctx.save()
+ ctx.translate(this.wheelRadius, this.wheelRadius)
+ s = this.wheelRadius - this.triangleRadius
+ // Draw a circle for every color
+ for (i = 0; i < 360; i++) {
+ ctx.rotate(PI / -180) // rotate one degree
+ ctx.beginPath()
+ ctx.fillStyle = 'hsl(' + i + ', 100%, 50%)'
+ ctx.arc(this.wheelRadius - (s / 2), 0, s / 2, 0, PI * 2, true)
+ ctx.fill()
+ }
+ ctx.restore()
+ }
+
+ _createTriangle () {
+ let c = this.triangle = doc.createElement('canvas')
+
+ c.width = c.height = this.innerSize
+ c.style.position = 'absolute'
+ c.style.margin = c.style.padding = '0'
+ c.style.left = c.style.top = this.padding + 'px'
+
+ this.triangleCtx = c.getContext('2d')
+
+ this.container.appendChild(c)
+ }
+
+ _drawTriangle () {
+ const hx = this.hx
+ const hy = this.hy
+ const sx = this.sx
+ const sy = this.sy
+ const vx = this.vx
+ const vy = this.vy
+ const size = this.innerSize
+
+ let ctx = this.triangleCtx
+
+ // clear
+ ctx.clearRect(0, 0, size, size)
+
+ ctx.save()
+ ctx.translate(this.wheelRadius, this.wheelRadius)
+
+ // make a triangle
+ ctx.beginPath()
+ ctx.moveTo(hx, hy)
+ ctx.lineTo(sx, sy)
+ ctx.lineTo(vx, vy)
+ ctx.closePath()
+ ctx.clip()
+
+ ctx.fillStyle = '#000'
+ ctx.fillRect(-this.wheelRadius, -this.wheelRadius, size, size)
+ // => black triangle
+
+ // create gradient from hsl(hue, 1, 1) to transparent
+ let grad0 = ctx.createLinearGradient(hx, hy, (sx + vx) / 2, (sy + vy) / 2)
+ const hsla = 'hsla(' + M.round(this.hue * (180 / PI)) + ', 100%, 50%, '
+ grad0.addColorStop(0, hsla + '1)')
+ grad0.addColorStop(1, hsla + '0)')
+ ctx.fillStyle = grad0
+ ctx.fillRect(-this.wheelRadius, -this.wheelRadius, size, size)
+ // => gradient: one side of the triangle is black, the opponent angle is $color
+
+ // create color gradient from white to transparent
+ let grad1 = ctx.createLinearGradient(vx, vy, (hx + sx) / 2, (hy + sy) / 2)
+ grad1.addColorStop(0, '#fff')
+ grad1.addColorStop(1, 'rgba(255, 255, 255, 0)')
+ ctx.globalCompositeOperation = 'lighter'
+ ctx.fillStyle = grad1
+ ctx.fillRect(-this.wheelRadius, -this.wheelRadius, size, size)
+ // => white angle
+
+ ctx.restore()
+ }
+
+ // The two pointers
+ _createWheelPointer () {
+ let c = this.wheelPointer = doc.createElement('canvas')
+ const size = this.wheelPointerSize
+ c.width = c.height = size
+ c.style.position = 'absolute'
+ c.style.margin = c.style.padding = '0'
+ this._drawPointer(c.getContext('2d'), size / 2, this.options.wheelPointerColor1, this.options.wheelPointerColor2)
+ this.container.appendChild(c)
+ }
+
+ _moveWheelPointer () {
+ const r = this.wheelPointerSize / 2
+ const s = this.wheelPointer.style
+ s.top = this.padding + this.wheelRadius - M.sin(this.hue) * (this.triangleRadius + this.wheelThickness / 2) - r + 'px'
+ s.left = this.padding + this.wheelRadius + M.cos(this.hue) * (this.triangleRadius + this.wheelThickness / 2) - r + 'px'
+ }
+
+ _createTrianglePointer () { // create pointer in the triangle
+ let c = this.trianglePointer = doc.createElement('canvas')
+ const size = this.options.trianglePointerSize
+
+ c.width = c.height = size
+ c.style.position = 'absolute'
+ c.style.margin = c.style.padding = '0'
+ this._drawPointer(c.getContext('2d'), size / 2, this.options.trianglePointerColor1, this.options.trianglePointerColor2)
+ this.container.appendChild(c)
+ }
+
+ _moveTrianglePointer (x, y) {
+ const s = this.trianglePointer.style
+ const r = this.options.trianglePointerSize / 2
+ s.top = (this.y + this.wheelRadius + this.padding - r) + 'px'
+ s.left = (this.x + this.wheelRadius + this.padding - r) + 'px'
+ }
+
+ _drawPointer (ctx, r, color1, color2) {
+ ctx.fillStyle = color2
+ ctx.beginPath()
+ ctx.arc(r, r, r, 0, PI * 2, true)
+ ctx.fill() // => black circle
+ ctx.fillStyle = color1
+ ctx.beginPath()
+ ctx.arc(r, r, r - 2, 0, PI * 2, true)
+ ctx.fill() // => white circle with 1px black border
+ ctx.fillStyle = color2
+ ctx.beginPath()
+ ctx.arc(r, r, r / 4 + 2, 0, PI * 2, true)
+ ctx.fill() // => black circle with big white border and a small black border
+ ctx.globalCompositeOperation = 'destination-out'
+ ctx.beginPath()
+ ctx.arc(r, r, r / 4, 0, PI * 2, true)
+ ctx.fill() // => transparent center
+ }
+
+ // The Element and the DOM
+ inject (parent) {
+ parent.appendChild(this.container)
+
+ // calculate canvas position on page
+ const offsets = getOffsets(this.triangle)
+ this.offset = {
+ x: offsets[0],
+ y: offsets[1]
+ }
+ }
+
+ dispose () {
+ let parent = this.container.parentNode
+ if (parent) {
+ parent.removeChild(this.container)
+ }
+ }
+
+ getElement () {
+ return this.container
+ }
+
+ // Color accessors
+ getCSS () {
+ const h = Math.round(this.hue * (180 / PI))
+ const s = Math.round(this.saturation * 100)
+ const l = Math.round(this.lightness * 100)
+
+ return `hsl(${h}, ${s}%, ${l}%)`
+ }
+
+ getHEX () {
+ return rgb_to_hex(...this.getRGB())
+ }
+
+ setHEX (hex) {
+ this.setRGB(...hex_to_rgb(hex))
+ }
+
+ getRGB () {
+ return hsl_to_rgb(...this.getHSL())
+ }
+
+ setRGB (r, g, b) {
+ this.setHSL(...rgb_to_hsl(r, g, b))
+ }
+
+ getHSL () {
+ return [this.hue, this.saturation, this.lightness]
+ }
+
+ setHSL (h, s, l) {
+ this.hue = h
+ this.saturation = s
+ this.lightness = l
+
+ this._initColor()
+ }
+
+ _initColor () {
+ this._calculatePositions()
+ this._moveWheelPointer()
+ this._drawTriangle()
+ this._moveTrianglePointer()
+ }
+
+ // Mouse event handling
+ _attachEvents () {
+ this.down = null
+
+ let mousedown = (evt) => {
+ evt.stopPropagation()
+ evt.preventDefault()
+
+ doc.body.addEventListener('mousemove', mousemove, false)
+ doc.body.addEventListener('mouseup', mouseup, false)
+ this._map(evt.pageX, evt.pageY)
+ }
+
+ let mousemove = (evt) => {
+ this._move(evt.pageX, evt.pageY)
+ }
+
+ let mouseup = (evt) => {
+ if (this.down) {
+ this.down = null
+ this._fireEvent('dragend')
+ }
+ doc.body.removeEventListener('mousemove', mousemove, false)
+ doc.body.removeEventListener('mouseup', mouseup, false)
+ }
+
+ this.container.addEventListener('mousedown', mousedown, false)
+ this.container.addEventListener('mousemove', mousemove, false)
+ }
+
+ _map (x, y) {
+ const ox = x
+ const oy = y
+
+ x -= this.offset.x + this.wheelRadius
+ y -= this.offset.y + this.wheelRadius
+
+ const r = M.sqrt(x * x + y * y) // Pythagoras
+ if (r > this.triangleRadius && r < this.wheelRadius) {
+ // Wheel
+ this.down = 'wheel'
+ this._fireEvent('dragstart')
+ this._move(ox, oy)
+ } else if (r < this.triangleRadius) {
+ // Inner circle
+ this.down = 'triangle'
+ this._fireEvent('dragstart')
+ this._move(ox, oy)
+ }
+ }
+
+ _move (x, y) {
+ if (!this.down) {
+ return
+ }
+
+ x -= this.offset.x + this.wheelRadius
+ y -= this.offset.y + this.wheelRadius
+
+ let rad = M.atan2(-y, x)
+ if (rad < 0) {
+ rad += 2 * PI
+ }
+
+ if (this.down === 'wheel') {
+ this.hue = rad
+ this._initColor()
+ this._fireEvent('drag')
+ } else if (this.down === 'triangle') {
+ // get radius and max radius
+ let rad0 = (rad + 2 * PI - this.hue) % (2 * PI)
+ let rad1 = rad0 % ((2 / 3) * PI) - (PI / 3)
+ let a = 0.5 * this.triangleRadius
+ let b = M.tan(rad1) * a
+ let r = M.sqrt(x * x + y * y) // Pythagoras
+ let maxR = M.sqrt(a * a + b * b) // Pythagoras
+
+ if (r > maxR) {
+ const dx = M.tan(rad1) * r
+ let rad2 = M.atan(dx / maxR)
+ if (rad2 > PI / 3) {
+ rad2 = PI / 3
+ } else if (rad2 < -PI / 3) {
+ rad2 = -PI / 3
+ }
+ rad += rad2 - rad1
+
+ rad0 = (rad + 2 * PI - this.hue) % (2 * PI)
+ rad1 = rad0 % ((2 / 3) * PI) - (PI / 3)
+ b = M.tan(rad1) * a
+ r = maxR = M.sqrt(a * a + b * b) // Pythagoras
+ }
+
+ x = M.round(M.cos(rad) * r)
+ y = M.round(-M.sin(rad) * r)
+
+ const l = this.lightness = ((M.sin(rad0) * r) / this.triangleSideLength) + 0.5
+
+ const widthShare = 1 - (M.abs(l - 0.5) * 2)
+ let s = this.saturation = (((M.cos(rad0) * r) + (this.triangleRadius / 2)) / (1.5 * this.triangleRadius)) / widthShare
+ s = M.max(0, s) // cannot be lower than 0
+ s = M.min(1, s) // cannot be greater than 1
+
+ this.lightness = l
+ this.saturation = s
+
+ this.x = x
+ this.y = y
+ this._moveTrianglePointer()
+
+ this._fireEvent('drag')
+ }
+ }
+
+ /***************
+ * Init helpers *
+ ***************/
+
+ static initInput (input, options) {
+ options = options || {}
+
+ let ct
+ let openColorTriangle = function () {
+ let hex = input.value
+ if (options.parseColor) hex = options.parseColor(hex)
+ if (!ct) {
+ options.size = options.size || input.offsetWidth
+ options.background = win.getComputedStyle(input, null).backgroundColor
+ options.margin = options.margin || 10
+ options.event = options.event || 'dragend'
+
+ ct = new ColorTriangle(hex, options)
+ ct.addEventListener(options.event, () => {
+ const hex = ct.getHEX()
+ input.value = options.uppercase ? hex.toUpperCase() : hex
+ fireChangeEvent()
+ })
+ } else {
+ ct.setHEX(hex)
+ }
+
+ let top = input.offsetTop
+ if (win.innerHeight - input.getBoundingClientRect().top > input.offsetHeight + options.margin + options.size) {
+ top += input.offsetHeight + options.margin // below
+ } else {
+ top -= options.margin + options.size // above
+ }
+
+ let el = ct.getElement()
+ el.style.position = 'absolute'
+ el.style.left = input.offsetLeft + 'px'
+ el.style.top = top + 'px'
+ el.style.zIndex = '1338' // above everything
+
+ ct.inject(input.parentNode)
+ }
+
+ let closeColorTriangle = () => {
+ if (ct) {
+ ct.dispose()
+ }
+ }
+
+ let fireChangeEvent = () => {
+ let evt = doc.createEvent('HTMLEvents')
+ evt.initEvent('input', true, false) // bubbles = true, cancable = false
+ input.dispatchEvent(evt) // fire event
+ }
+
+ input.addEventListener('focus', openColorTriangle, false)
+ input.addEventListener('blur', closeColorTriangle, false)
+ input.addEventListener('keyup', () => {
+ const val = input.value
+ if (val.match(/^#((?:[0-9A-Fa-f]{3})|(?:[0-9A-Fa-f]{6}))$/)) {
+ openColorTriangle()
+ fireChangeEvent()
+ } else {
+ closeColorTriangle()
+ }
+ }, false)
+ }
+
+ /*******************
+ * Helper functions *
+ *******************/
+
+ _setOptions (opts) {
+ opts = opts || {}
+ let dflt = this.options
+ let options = this.options = {}
+
+ each(dflt, function (val, key) {
+ options[key] = (opts.hasOwnProperty(key))
+ ? opts[key]
+ : val
+ })
+ }
+
+ addEventListener (type, fn) {
+ if (!this.events) {
+ this.events = {}
+ }
+ if (!this.events[type]) {
+ this.events[type] = []
+ }
+ this.events[type].push(fn)
+ }
+
+ removeEventListener (type, fn) {
+ if (this.events) {
+ let fns = this.events[type]
+ const l = fns.length
+ for (let i = 0; i < l; i += 1) {
+ if (fns[i] === fn) {
+ fns.splice(i, 1)
+ break
+ }
+ }
+ }
+ }
+
+ _fireEvent (type) {
+ if (this.events) {
+ let evts = this.events[type]
+ if (evts) {
+ const args = Array.prototype.slice.call(arguments, 1)
+ each(evts, function (evt) {
+ evt(...args)
+ })
+ }
+ }
+ }
+}
diff --git a/js/term/themes.js b/js/term/themes.js
index 699c017..aa93bc1 100644
--- a/js/term/themes.js
+++ b/js/term/themes.js
@@ -1,4 +1,5 @@
const $ = require('../lib/chibi')
+const { rgb_to_hex } = require('../lib/color_utils')
const themes = exports.themes = [
[ // 0 - Tango - terminator
@@ -73,7 +74,7 @@ exports.buildColorTable = function () {
// 256color lookup table
// should not be used to look up 0-15 (will return transparent)
- colorTable256 = new Array(16).fill('rgba(0, 0, 0, 0)')
+ colorTable256 = new Array(16).fill('#000000')
// fill color table
// colors 16-231 are a 6x6x6 color cube
@@ -83,14 +84,14 @@ exports.buildColorTable = function () {
let redValue = red * 40 + (red ? 55 : 0)
let greenValue = green * 40 + (green ? 55 : 0)
let blueValue = blue * 40 + (blue ? 55 : 0)
- colorTable256.push(`rgb(${redValue}, ${greenValue}, ${blueValue})`)
+ colorTable256.push(rgb_to_hex(redValue, greenValue, blueValue))
}
}
}
// colors 232-255 are a grayscale ramp, sans black and white
for (let gray = 0; gray < 24; gray++) {
let value = gray * 10 + 8
- colorTable256.push(`rgb(${value}, ${value}, ${value})`)
+ colorTable256.push(rgb_to_hex(value, value, value))
}
return colorTable256
@@ -102,17 +103,17 @@ exports.SELECTION_BG = '#b2d7fe'
exports.themePreview = function (themeN) {
$('[data-fg]').forEach((elem) => {
let shade = elem.dataset.fg
- if (/^\d+$/.test(shade)) shade = exports.toCss(shade, themeN)
+ if (/^\d+$/.test(shade)) shade = exports.toHex(shade, themeN)
elem.style.color = shade
})
$('[data-bg]').forEach((elem) => {
let shade = elem.dataset.bg
- if (/^\d+$/.test(shade)) shade = exports.toCss(shade, themeN)
+ if (/^\d+$/.test(shade)) shade = exports.toHex(shade, themeN)
elem.style.backgroundColor = shade
})
}
-exports.toCss = function (shade, themeN) {
+exports.toHex = function (shade, themeN) {
if (/^\d+$/.test(shade)) {
shade = +shade
if (shade < 16) shade = themes[themeN][shade]
diff --git a/js/term_conf.js b/js/term_conf.js
new file mode 100644
index 0000000..87d9d70
--- /dev/null
+++ b/js/term_conf.js
@@ -0,0 +1,105 @@
+const ColorTriangle = require('./lib/colortriangle')
+const $ = require('./lib/chibi')
+const themes = require('./term/themes')
+const { qs } = require('./utils')
+
+function selectedTheme () {
+ return +$('#theme').val()
+}
+
+exports.init = function () {
+ $('#theme').on('change', showColor)
+
+ $('#default_fg').on('input', showColor)
+ $('#default_bg').on('input', showColor)
+
+ let opts = {
+ padding: 10,
+ event: 'drag',
+ uppercase: true,
+ trianglePointerSize: 20,
+ // wheelPointerSize: 12,
+ size: 200,
+ parseColor: (color) => {
+ return themes.toHex(color, selectedTheme())
+ }
+ }
+
+ ColorTriangle.initInput(qs('#default_fg'), opts)
+ ColorTriangle.initInput(qs('#default_bg'), opts)
+
+ $('.colorprev.bg span').on('click', function () {
+ const bg = this.dataset.bg
+ if (typeof bg != 'undefined') $('#default_bg').val(bg)
+ showColor()
+ })
+
+ $('.colorprev.fg span').on('click', function () {
+ const fg = this.dataset.fg
+ if (typeof fg != 'undefined') $('#default_fg').val(fg)
+ showColor()
+ })
+
+ let $presets = $('#fgbg_presets')
+ for (let i = 0; i < themes.fgbgThemes.length; i++) {
+ const thm = themes.fgbgThemes[i]
+ const fg = thm[0]
+ const bg = thm[1]
+ const lbl = thm[2]
+ const tit = thm[3]
+ $presets.htmlAppend(
+ ' ' + lbl + ' ')
+
+ if ((i + 1) % 5 === 0) $presets.htmlAppend('
')
+ }
+
+ $('.preset').on('click', function () {
+ $('#default_fg').val(this.dataset.xfg)
+ $('#default_bg').val(this.dataset.xbg)
+ showColor()
+ })
+
+ showColor()
+}
+
+function showColor () {
+ let ex = qs('.color-example')
+ let fg = $('#default_fg').val()
+ let bg = $('#default_bg').val()
+
+ if (/^\d+$/.test(fg)) {
+ fg = +fg
+ } else if (!/^#[\da-f]{6}$/i.test(fg)) {
+ fg = 'black'
+ }
+
+ if (/^\d+$/.test(bg)) {
+ bg = +bg
+ } else if (!/^#[\da-f]{6}$/i.test(bg)) {
+ bg = 'black'
+ }
+
+ const themeN = selectedTheme()
+ ex.dataset.fg = fg
+ ex.dataset.bg = bg
+
+ themes.themePreview(themeN)
+
+ $('.colorprev.fg span').css('background', themes.toHex(bg, themeN))
+}
+
+exports.nextTheme = () => {
+ let sel = qs('#theme')
+ let i = sel.selectedIndex
+ sel.options[++i % sel.options.length].selected = true
+ showColor()
+}
+
+exports.prevTheme = () => {
+ let sel = qs('#theme')
+ let i = sel.selectedIndex
+ sel.options[(sel.options.length + (--i)) % sel.options.length].selected = true
+ showColor()
+}
diff --git a/pages/cfg_term.php b/pages/cfg_term.php
index 51fe377..9db48f2 100644
--- a/pages/cfg_term.php
+++ b/pages/cfg_term.php
@@ -26,8 +26,8 @@
- ◀
- ▶
+ ◀
+ ▶
@@ -300,30 +300,6 @@
From e2c57ac80ab76baaafabdc1946ce57ca3a89662c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sat, 30 Sep 2017 21:20:34 +0200
Subject: [PATCH 42/86] oops broke color table
---
js/lib/color_utils.js | 7 +++++++
js/term/themes.js | 6 +++---
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/js/lib/color_utils.js b/js/lib/color_utils.js
index 74cff36..1ed5a65 100644
--- a/js/lib/color_utils.js
+++ b/js/lib/color_utils.js
@@ -113,6 +113,13 @@ function pad (n) {
return n
}
+exports.rgb255_to_hex = function (r, g, b) {
+ r = r.toString(16)
+ g = g.toString(16)
+ b = b.toString(16)
+ return `#${pad(r)}${pad(g)}${pad(b)}`
+}
+
exports.rgb_to_hex = function (r, g, b) {
r = Math.round(r * 255).toString(16)
g = Math.round(g * 255).toString(16)
diff --git a/js/term/themes.js b/js/term/themes.js
index aa93bc1..a1b84ee 100644
--- a/js/term/themes.js
+++ b/js/term/themes.js
@@ -1,5 +1,5 @@
const $ = require('../lib/chibi')
-const { rgb_to_hex } = require('../lib/color_utils')
+const { rgb255_to_hex } = require('../lib/color_utils')
const themes = exports.themes = [
[ // 0 - Tango - terminator
@@ -84,14 +84,14 @@ exports.buildColorTable = function () {
let redValue = red * 40 + (red ? 55 : 0)
let greenValue = green * 40 + (green ? 55 : 0)
let blueValue = blue * 40 + (blue ? 55 : 0)
- colorTable256.push(rgb_to_hex(redValue, greenValue, blueValue))
+ colorTable256.push(rgb255_to_hex(redValue, greenValue, blueValue))
}
}
}
// colors 232-255 are a grayscale ramp, sans black and white
for (let gray = 0; gray < 24; gray++) {
let value = gray * 10 + 8
- colorTable256.push(rgb_to_hex(value, value, value))
+ colorTable256.push(rgb255_to_hex(value, value, value))
}
return colorTable256
From ffc3a9b3e23cd60ce7e9018b791ad790e7cde379 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sat, 30 Sep 2017 21:27:51 +0200
Subject: [PATCH 43/86] added lang env variable
---
base.php | 2 +-
js/lang.js | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/base.php b/base.php
index 30eeea4..a7dc7f5 100644
--- a/base.php
+++ b/base.php
@@ -59,7 +59,7 @@ APS
);
}
-define('LOCALE', isset($_GET['locale']) ? $_GET['locale'] : 'en');
+define('LOCALE', isset($_GET['locale']) ? $_GET['locale'] : (getenv('ESP_LANG') ?: 'en'));
$_messages = require(__DIR__ . '/lang/' . LOCALE . '.php');
$_pages = require(__DIR__ . '/_pages.php');
diff --git a/js/lang.js b/js/lang.js
index 429f1ac..41e5e9c 100644
--- a/js/lang.js
+++ b/js/lang.js
@@ -1,14 +1,14 @@
// Generated from PHP locale file
let _tr = {
- "wifi.connected_ip_is": "Connected, IP is ",
- "wifi.not_conn": "Not connected.",
- "wifi.enter_passwd": "Enter password for \":ssid:\"",
- "term_nav.fullscreen": "Fullscreen",
- "term_conn.connecting": "Connecting",
- "term_conn.waiting_content": "Waiting for content",
- "term_conn.disconnected": "Disconnected",
- "term_conn.waiting_server": "Waiting for server",
- "term_conn.reconnecting": "Reconnecting"
+ "wifi.connected_ip_is": "Verbunden, IP ist ",
+ "wifi.not_conn": "Nicht verbunden.",
+ "wifi.enter_passwd": "Passwort für \":ssid:\"",
+ "term_nav.fullscreen": "Vollbild",
+ "term_conn.connecting": "Verbinden",
+ "term_conn.waiting_content": "Warten auf Inhalt",
+ "term_conn.disconnected": "Nicht verbunden",
+ "term_conn.waiting_server": "Warten auf Server",
+ "term_conn.reconnecting": "Verbinden"
};
module.exports = function tr (key) { return _tr[key] || '?' + key + '?' }
From b2c14d34e7a771e511ceda206fbc95df57ddb2cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sat, 30 Sep 2017 21:33:28 +0200
Subject: [PATCH 44/86] wrap long lines
---
js/lang.js | 18 +-
lang/de.php | 512 +++++++++++++++++++++++++++-------------------------
lang/en.php | 34 +++-
3 files changed, 300 insertions(+), 264 deletions(-)
diff --git a/js/lang.js b/js/lang.js
index 41e5e9c..429f1ac 100644
--- a/js/lang.js
+++ b/js/lang.js
@@ -1,14 +1,14 @@
// Generated from PHP locale file
let _tr = {
- "wifi.connected_ip_is": "Verbunden, IP ist ",
- "wifi.not_conn": "Nicht verbunden.",
- "wifi.enter_passwd": "Passwort für \":ssid:\"",
- "term_nav.fullscreen": "Vollbild",
- "term_conn.connecting": "Verbinden",
- "term_conn.waiting_content": "Warten auf Inhalt",
- "term_conn.disconnected": "Nicht verbunden",
- "term_conn.waiting_server": "Warten auf Server",
- "term_conn.reconnecting": "Verbinden"
+ "wifi.connected_ip_is": "Connected, IP is ",
+ "wifi.not_conn": "Not connected.",
+ "wifi.enter_passwd": "Enter password for \":ssid:\"",
+ "term_nav.fullscreen": "Fullscreen",
+ "term_conn.connecting": "Connecting",
+ "term_conn.waiting_content": "Waiting for content",
+ "term_conn.disconnected": "Disconnected",
+ "term_conn.waiting_server": "Waiting for server",
+ "term_conn.reconnecting": "Reconnecting"
};
module.exports = function tr (key) { return _tr[key] || '?' + key + '?' }
diff --git a/lang/de.php b/lang/de.php
index e939585..36218b7 100644
--- a/lang/de.php
+++ b/lang/de.php
@@ -1,251 +1,269 @@
'ESPTerm',
- 'appname_demo' => 'ESPTerm DEMO',
-
- 'menu.cfg_wifi' => 'WLAN-Einstellungen',
- 'menu.cfg_network' => 'Netzwerkeinstellungen',
- 'menu.cfg_term' => 'Terminaleinstellungen',
- 'menu.about' => 'Über ESPTerm',
- 'menu.help' => 'Referenz',
- 'menu.term' => 'Zurück zum Terminal',
- 'menu.cfg_system' => 'Systemeinstellungen',
- 'menu.cfg_wifi_conn' => 'Verbinden mit dem Netzwerk',
- 'menu.settings' => 'Einstellungen',
-
- // not used - api etc. Added to suppress warnings
- 'menu.term_set' => '',
- 'menu.wifi_connstatus' => '',
- 'menu.wifi_set' => '',
- 'menu.wifi_scan' => '',
- 'menu.network_set' => '',
- 'menu.system_set' => '',
- 'menu.write_defaults' => '',
- 'menu.restore_defaults' => '',
- 'menu.restore_hard' => '',
- 'menu.reset_screen' => '',
- 'menu.index' => '',
-
- // Terminal page
-
- 'title.term' => 'Terminal', // page title of the terminal page
-
- 'term_nav.fullscreen' => 'Vollbild',
- 'term_nav.config' => 'Konfiguration',
- 'term_nav.wifi' => 'WLAN',
- 'term_nav.help' => 'Hilfe',
- 'term_nav.about' => 'Info',
- 'term_nav.paste' => 'Einfügen',
- 'term_nav.upload' => 'Hochladen',
- 'term_nav.keybd' => 'Tastatur',
- 'term_nav.paste_prompt' => 'Text einfügen zum Versenden:',
-
- 'term_conn.connecting' => 'Verbinden',
- 'term_conn.waiting_content' => 'Warten auf Inhalt',
- 'term_conn.disconnected' => 'Nicht verbunden',
- 'term_conn.waiting_server' => 'Warten auf Server',
- 'term_conn.reconnecting' => 'Verbinden',
-
- // Terminal settings page
-
- 'term.defaults' => 'Anfangseinstellungen',
- 'term.expert' => 'Expertenoptionen',
- 'term.explain_initials' => '
- Dies sind die Anfangseinstellungen, die benutzt werden, nachdem ESPTerm startet, oder wenn der Bildschirm mit dem \ec
-Kommando zurückgesetzt wird. Sie können durch Escape-Sequenzen verändert werden.
- ',
- 'term.explain_expert' => '
- Dies sind erweiterte Konfigurationsoptionen, die meistens nicht verändert werden müssen. Bearbeite sie nur, wenn du weißt, was du tust.',
-
- 'term.example' => 'Standardfarbenvorschau',
-
- 'term.explain_scheme' => '
- Um die Standardtextfarbe und Standardhintergrundfarbe auszuwählen, klicke auf die Vorschaupalette, oder benutze die Zahlen 0-15 für die Themafarben, 16-255 für Standardfarben, oder Hexadezimal (#FFFFFF) für True Color (24-bit).
- ',
-
- 'term.fgbg_presets' => 'Standardvoreinstellungen',
- 'term.color_scheme' => 'Farbschema',
- 'term.reset_screen' => 'Bildschirm & Parser zurücksetzen',
- 'term.term_title' => 'Titeltext',
- 'term.term_width' => 'Breite',
- 'term.term_height' => 'Höhe',
- 'term.buttons' => 'Tastentext',
- 'term.theme' => 'Farbthema',
- 'term.cursor_shape' => 'Cursorstil',
- 'term.parser_tout_ms' => 'Parser-Auszeit',
- 'term.display_tout_ms' => 'Zeichenverzögerung',
- 'term.display_cooldown_ms' => 'Zeichenabkühlzeit',
- 'term.allow_decopt_12' => '\e?12h/l erlauben',
- 'term.fn_alt_mode' => 'SS3 Fn-Tasten',
- 'term.show_config_links' => 'Navigationslinks anzeigen',
- 'term.show_buttons' => 'Tasten anzeigen',
- 'term.loopback' => 'Lokales Echo (SRM)',
- 'term.crlf_mode' => 'Enter = CR+LF (LNM)',
- 'term.want_all_fn' => 'F5, F11, F12 erfassen',
- 'term.button_msgs' => 'Tastencodes
(ASCII, dec, CSV)',
- 'term.color_fg' => 'Standardvordergr.',
- 'term.color_bg' => 'Standardhintergr.',
- 'term.color_fg_prev' => 'Vordergrund',
- 'term.color_bg_prev' => 'Hintergrund',
- 'term.colors_preview' => '',
-
- 'cursor.block_blink' => 'Block, blinkend',
- 'cursor.block_steady' => 'Block, ruhig',
- 'cursor.underline_blink' => 'Unterstrich, blinkend',
- 'cursor.underline_steady' => 'Unterstrich, ruhig',
- 'cursor.bar_blink' => 'Balken, blinkend',
- 'cursor.bar_steady' => 'Balken, ruhig',
-
- // Network config page
-
- 'net.explain_sta' => '
- Schalte Dynamische IP aus um die statische IP-Addresse zu konfigurieren.',
-
- 'net.explain_ap' => '
- Diese Einstellungen beeinflussen den eingebauten DHCP-Server im AP-Modus.',
-
- 'net.ap_dhcp_time' => 'Leasezeit',
- 'net.ap_dhcp_start' => 'Pool Start-IP',
- 'net.ap_dhcp_end' => 'Pool End-IP',
- 'net.ap_addr_ip' => 'Eigene IP-Addresse',
- 'net.ap_addr_mask' => 'Subnet-Maske',
-
- 'net.sta_dhcp_enable' => 'Dynamische IP verwenden',
- 'net.sta_addr_ip' => 'ESPTerm statische IP',
- 'net.sta_addr_mask' => 'Subnet-Mask',
- 'net.sta_addr_gw' => 'Gateway-IP',
-
- 'net.ap' => 'DHCP Server (AP)',
- 'net.sta' => 'DHCP Client (Station)',
- 'net.sta_mac' => 'Station MAC',
- 'net.ap_mac' => 'AP MAC',
- 'net.details' => 'MAC-Addressen',
-
- // Wifi config page
-
- 'wifi.ap' => 'Eingebauter Access Point',
- 'wifi.sta' => 'Bestehendes Netzwerk beitreten',
-
- 'wifi.enable' => 'Aktiviert',
- 'wifi.tpw' => 'Sendeleistung',
- 'wifi.ap_channel' => 'Kanal',
- 'wifi.ap_ssid' => 'AP SSID',
- 'wifi.ap_password' => 'Passwort',
- 'wifi.ap_hidden' => 'SSID verbergen',
- 'wifi.sta_info' => 'Ausgewählt',
-
- 'wifi.not_conn' => 'Nicht verbunden.',
- 'wifi.sta_none' => 'Keine',
- 'wifi.sta_active_pw' => '🔒 Passwort gespeichert',
- 'wifi.sta_active_nopw' => '🔓 Offen',
- 'wifi.connected_ip_is' => 'Verbunden, IP ist ',
- 'wifi.sta_password' => 'Passwort:',
-
- 'wifi.scanning' => 'Scannen',
- 'wifi.scan_now' => 'Klicke hier um zu scannen!',
- 'wifi.cant_scan_no_sta' => 'Klicke hier um Client-Modus zu aktivieren und zu scannen!',
- 'wifi.select_ssid' => 'Verfügbare Netzwerke:',
- 'wifi.enter_passwd' => 'Passwort für ":ssid:"',
- 'wifi.sta_explain' => 'Nach dem Auswählen eines Netzwerks, drücke Bestätigen drücken, um dich zu verbinden.',
-
- // Wifi connecting status page
-
- 'wificonn.status' => 'Status:',
- 'wificonn.back_to_config' => 'Zurück zur WLAN-Konfiguration',
- 'wificonn.telemetry_lost' => 'Telemetrie verloren; etwas lief schief, oder dein Gerät wurde getrennt.',
- 'wificonn.explain_android_sucks' => '
- Wenn du gerade ESPTerm mit einem Handy oder über ein anderes externes Netzwerk konfigurierst, kann dein Gerät die Verbindung verlieren und diese Fortschrittsanzeige wird nicht funktionieren. Bitte warte eine Weile (etwa 15 Sekunden) und prüfe dann, ob die Verbindung gelangen ist.',
-
- 'wificonn.explain_reset' => '
- Um den eingebauten AP zur Aktivierung zu zwingen, halte den BOOT-Knopf gedrückt bis die blaue LED beginnt, zu blinken. Halte ihn länger gedrückt (bis die LED schnell blinkt) um eine "Werksrückstellung" zu vollziehen.',
-
- 'wificonn.disabled' => "Stationsmodus ist deaktiviert.",
- 'wificonn.idle' => "Nicht verbunden und ohne IP.",
- 'wificonn.success' => "Verbunden! Empfangene IP: ",
- 'wificonn.working' => "Verbinden mit dem ausgewählten AP",
- 'wificonn.fail' => "Verbindung fehlgeschlagen; prüfe die Einstellungen und versuche es erneut. Grund: ",
-
- // Access restrictions form
-
- 'pwlock.title' => 'Zugriffsbeschränkungen',
- 'pwlock.explain' => '
- Manche, oder alle Teile des Web-Interface können mit einem Passwort geschützt werden.
- Lass die Passwortfelder leer wenn du es sie verändern möchtest.
- Das voreingestellte Passwort ist "%def_access_pw%".
- ',
- 'pwlock.region' => 'Geschützte Seiten',
- 'pwlock.region.none' => 'Keine, alles offen',
- 'pwlock.region.settings_noterm' => 'WLAN-, Netzwerk- & Systemeinstellungen',
- 'pwlock.region.settings' => 'Alle Einstellungsseiten',
- 'pwlock.region.menus' => 'Dieser ganze Menüabschnitt',
- 'pwlock.region.all' => 'Alles, sogar das Terminal',
- 'pwlock.new_access_pw' => 'Neues Passwort',
- 'pwlock.new_access_pw2' => 'Wiederholen',
- 'pwlock.admin_pw' => 'Administratorpasswort',
- 'pwlock.access_name' => 'Benutzername',
-
- // Setting admin password
-
- 'adminpw.title' => 'Administratorpasswort ändern',
- 'adminpw.explain' =>
- '
- Das "Administratorpasswort" wird benutzt, um die gespeicherten Standardeinstellungen und die Zugriffsbeschränkungen zu verändern. Dieses Passwort wird nicht als Teil der Hauptkonfiguration gespeichert, d.h. Speichern / Wiederherstellen wird das Passwort nicht beeinflussen. Wenn das Administratorpasswort vergessen wird, ist die einfachste Weise, wieder Zugriff zu erhalten, ein Re-flash des Chips.
- Das voreingestellte Administratorpasswort ist "%def_admin_pw%".
- ',
- 'adminpw.new_admin_pw' => 'Neues Administratorpasswort',
- 'adminpw.new_admin_pw2' => 'Wiederholen',
- 'adminpw.old_admin_pw' => 'Altes Administratorpasswort',
-
- // Persist form
-
- 'persist.title' => 'Speichern & Wiederherstellen',
- 'persist.explain' => '
- ESPTerm speichert alle Einstellungen im Flash-Speicher. Die aktiven Einstellungen können in den “Voreinstellungsbereich” kopiert werden und später wiederhergestellt werden mit der Taste unten.
- ',
- 'persist.confirm_restore' => 'Alle Einstellungen zu den Voreinstellungen zurücksetzen?',
- 'persist.confirm_restore_hard' =>
- 'Zurücksetzen zu den Firmware-Voreinstellungen? Dies wird alle aktiven' .
- ' Einstellungen zürucksetzen und den AP-Modus aktivieren mit der Standard-SSID.',
- 'persist.confirm_store_defaults' =>
- 'Administratorpasswort eingeben um Voreinstellungen zu überschreiben',
- 'persist.password' => 'Administratorpasswort:',
- 'persist.restore_defaults' => 'Zu gespeicherten Voreinstellungen zurücksetzen',
- 'persist.write_defaults' => 'Aktive Einstellungen als Voreinstellungen speichern',
- 'persist.restore_hard' => 'Aktive Einstellungen zu Werkseinstellungen zurücksetzen',
- 'persist.restore_hard_explain' => '(Dies löscht die WLAN-Konfiguration! Beeinflusst die gespeicherten Voreinstellungen oder das Administratorpasswort nicht.)',
-
- // UART settings form
-
- 'uart.title' => 'Serienportparameter',
- 'uart.explain' => '
- Dies steuert den Kommunikations-UART. Der Debug-UART ist auf 115.200 baud fest eingestellt mit einem Stop-Bit und keiner Parität.
- ',
- 'uart.baud' => 'Baudrate',
- 'uart.parity' => 'Parität',
- 'uart.parity.none' => 'Keine',
- 'uart.parity.odd' => 'Ungerade',
- 'uart.parity.even' => 'Gerade',
- 'uart.stop_bits' => 'Stop-Bits',
- 'uart.stop_bits.one' => 'Eins',
- 'uart.stop_bits.one_and_half' => 'Eineinhalb',
- 'uart.stop_bits.two' => 'Zwei',
-
- // HW tuning form
-
- 'hwtuning.title' => 'Hardware-Tuning',
- 'hwtuning.explain' => '
- ESP8266 kann overclocked werden von 80 MHz auf 160 MHz.
- Alles wird etwas schneller sein, aber mit höherem Stromverbrauch, und eventuell auch mit höherer Interferenz. Mit Sorgfalt benutzen.
- ',
- 'hwtuning.overclock' => 'Auf 160MHz Overclocken',
-
- // Generic button / dialog labels
-
- 'apply' => 'Bestätigen!',
- 'enabled' => 'Aktiviert',
- 'disabled' => 'Deaktiviert',
- 'yes' => 'Ja',
- 'no' => 'Nein',
- 'confirm' => 'OK',
- 'form_errors' => 'Gültigkeitsfehler für:',
+ 'appname' => 'ESPTerm',
+ 'appname_demo' => 'ESPTerm DEMO',
+
+ 'menu.cfg_wifi' => 'WLAN-Einstellungen',
+ 'menu.cfg_network' => 'Netzwerkeinstellungen',
+ 'menu.cfg_term' => 'Terminaleinstellungen',
+ 'menu.about' => 'Über ESPTerm',
+ 'menu.help' => 'Referenz',
+ 'menu.term' => 'Zurück zum Terminal',
+ 'menu.cfg_system' => 'Systemeinstellungen',
+ 'menu.cfg_wifi_conn' => 'Verbinden mit dem Netzwerk',
+ 'menu.settings' => 'Einstellungen',
+
+ // not used - api etc. Added to suppress warnings
+ 'menu.term_set' => '',
+ 'menu.wifi_connstatus' => '',
+ 'menu.wifi_set' => '',
+ 'menu.wifi_scan' => '',
+ 'menu.network_set' => '',
+ 'menu.system_set' => '',
+ 'menu.write_defaults' => '',
+ 'menu.restore_defaults' => '',
+ 'menu.restore_hard' => '',
+ 'menu.reset_screen' => '',
+ 'menu.index' => '',
+
+ // Terminal page
+
+ 'title.term' => 'Terminal', // page title of the terminal page
+
+ 'term_nav.fullscreen' => 'Vollbild',
+ 'term_nav.config' => 'Konfiguration',
+ 'term_nav.wifi' => 'WLAN',
+ 'term_nav.help' => 'Hilfe',
+ 'term_nav.about' => 'Info',
+ 'term_nav.paste' => 'Einfügen',
+ 'term_nav.upload' => 'Hochladen',
+ 'term_nav.keybd' => 'Tastatur',
+ 'term_nav.paste_prompt' => 'Text einfügen zum Versenden:',
+
+ 'term_conn.connecting' => 'Verbinden',
+ 'term_conn.waiting_content' => 'Warten auf Inhalt',
+ 'term_conn.disconnected' => 'Nicht verbunden',
+ 'term_conn.waiting_server' => 'Warten auf Server',
+ 'term_conn.reconnecting' => 'Verbinden',
+
+ // Terminal settings page
+
+ 'term.defaults' => 'Anfangseinstellungen',
+ 'term.expert' => 'Expertenoptionen',
+ 'term.explain_initials' => '
+ Dies sind die Anfangseinstellungen, die benutzt werden, nachdem ESPTerm startet,
+ oder wenn der Bildschirm mit dem \ec
-Kommando zurückgesetzt wird.
+ Sie können durch Escape-Sequenzen verändert werden.
+ ',
+ 'term.explain_expert' => '
+ Dies sind erweiterte Konfigurationsoptionen, die meistens nicht verändert
+ werden müssen. Bearbeite sie nur, wenn du weißt, was du tust.',
+
+ 'term.example' => 'Standardfarbenvorschau',
+
+ 'term.explain_scheme' => '
+ Um die Standardtextfarbe und Standardhintergrundfarbe auszuwählen, klicke auf
+ die Vorschaupalette, oder benutze die Zahlen 0-15 für die Themafarben, 16-255
+ für Standardfarben, oder Hexadezimal (#FFFFFF) für True Color (24-bit).
+ ',
+
+ 'term.fgbg_presets' => 'Standardvoreinstellungen',
+ 'term.color_scheme' => 'Farbschema',
+ 'term.reset_screen' => 'Bildschirm & Parser zurücksetzen',
+ 'term.term_title' => 'Titeltext',
+ 'term.term_width' => 'Breite',
+ 'term.term_height' => 'Höhe',
+ 'term.buttons' => 'Tastentext',
+ 'term.theme' => 'Farbthema',
+ 'term.cursor_shape' => 'Cursorstil',
+ 'term.parser_tout_ms' => 'Parser-Auszeit',
+ 'term.display_tout_ms' => 'Zeichenverzögerung',
+ 'term.display_cooldown_ms' => 'Zeichenabkühlzeit',
+ 'term.allow_decopt_12' => '\e?12h/l erlauben',
+ 'term.fn_alt_mode' => 'SS3 Fn-Tasten',
+ 'term.show_config_links' => 'Navigationslinks anzeigen',
+ 'term.show_buttons' => 'Tasten anzeigen',
+ 'term.loopback' => 'Lokales Echo (SRM)',
+ 'term.crlf_mode' => 'Enter = CR+LF (LNM)',
+ 'term.want_all_fn' => 'F5, F11, F12 erfassen',
+ 'term.button_msgs' => 'Tastencodes
(ASCII, dec, CSV)',
+ 'term.color_fg' => 'Standardvordergr.',
+ 'term.color_bg' => 'Standardhintergr.',
+ 'term.color_fg_prev' => 'Vordergrund',
+ 'term.color_bg_prev' => 'Hintergrund',
+ 'term.colors_preview' => '',
+
+ 'cursor.block_blink' => 'Block, blinkend',
+ 'cursor.block_steady' => 'Block, ruhig',
+ 'cursor.underline_blink' => 'Unterstrich, blinkend',
+ 'cursor.underline_steady' => 'Unterstrich, ruhig',
+ 'cursor.bar_blink' => 'Balken, blinkend',
+ 'cursor.bar_steady' => 'Balken, ruhig',
+
+ // Network config page
+
+ 'net.explain_sta' => '
+ Schalte Dynamische IP aus um die statische IP-Addresse zu konfigurieren.',
+
+ 'net.explain_ap' => '
+ Diese Einstellungen beeinflussen den eingebauten DHCP-Server im AP-Modus.',
+
+ 'net.ap_dhcp_time' => 'Leasezeit',
+ 'net.ap_dhcp_start' => 'Pool Start-IP',
+ 'net.ap_dhcp_end' => 'Pool End-IP',
+ 'net.ap_addr_ip' => 'Eigene IP-Addresse',
+ 'net.ap_addr_mask' => 'Subnet-Maske',
+
+ 'net.sta_dhcp_enable' => 'Dynamische IP verwenden',
+ 'net.sta_addr_ip' => 'ESPTerm statische IP',
+ 'net.sta_addr_mask' => 'Subnet-Mask',
+ 'net.sta_addr_gw' => 'Gateway-IP',
+
+ 'net.ap' => 'DHCP Server (AP)',
+ 'net.sta' => 'DHCP Client (Station)',
+ 'net.sta_mac' => 'Station MAC',
+ 'net.ap_mac' => 'AP MAC',
+ 'net.details' => 'MAC-Addressen',
+
+ // Wifi config page
+
+ 'wifi.ap' => 'Eingebauter Access Point',
+ 'wifi.sta' => 'Bestehendes Netzwerk beitreten',
+
+ 'wifi.enable' => 'Aktiviert',
+ 'wifi.tpw' => 'Sendeleistung',
+ 'wifi.ap_channel' => 'Kanal',
+ 'wifi.ap_ssid' => 'AP SSID',
+ 'wifi.ap_password' => 'Passwort',
+ 'wifi.ap_hidden' => 'SSID verbergen',
+ 'wifi.sta_info' => 'Ausgewählt',
+
+ 'wifi.not_conn' => 'Nicht verbunden.',
+ 'wifi.sta_none' => 'Keine',
+ 'wifi.sta_active_pw' => '🔒 Passwort gespeichert',
+ 'wifi.sta_active_nopw' => '🔓 Offen',
+ 'wifi.connected_ip_is' => 'Verbunden, IP ist ',
+ 'wifi.sta_password' => 'Passwort:',
+
+ 'wifi.scanning' => 'Scannen',
+ 'wifi.scan_now' => 'Klicke hier um zu scannen!',
+ 'wifi.cant_scan_no_sta' => 'Klicke hier um Client-Modus zu aktivieren und zu scannen!',
+ 'wifi.select_ssid' => 'Verfügbare Netzwerke:',
+ 'wifi.enter_passwd' => 'Passwort für ":ssid:"',
+ 'wifi.sta_explain' =>
+ 'Nach dem Auswählen eines Netzwerks, drücke Bestätigen drücken, um dich zu verbinden.',
+
+ // Wifi connecting status page
+
+ 'wificonn.status' => 'Status:',
+ 'wificonn.back_to_config' => 'Zurück zur WLAN-Konfiguration',
+ 'wificonn.telemetry_lost' => 'Telemetrie verloren; etwas lief schief, oder dein Gerät wurde getrennt.',
+ 'wificonn.explain_android_sucks' => '
+ Wenn du gerade ESPTerm mit einem Handy oder über ein anderes externes Netzwerk
+ konfigurierst, kann dein Gerät die Verbindung verlieren und diese Fortschrittsanzeige
+ wird nicht funktionieren. Bitte warte eine Weile (etwa 15 Sekunden) und prüfe dann,
+ ob die Verbindung gelangen ist.',
+
+ 'wificonn.explain_reset' => '
+ Um den eingebauten AP zur Aktivierung zu zwingen, halte den BOOT-Knopf gedrückt bis die
+ blaue LED beginnt, zu blinken. Halte ihn länger gedrückt (bis die LED schnell blinkt)
+ um eine "Werksrückstellung" zu vollziehen.',
+
+ 'wificonn.disabled' => "Stationsmodus ist deaktiviert.",
+ 'wificonn.idle' => "Nicht verbunden und ohne IP.",
+ 'wificonn.success' => "Verbunden! Empfangene IP: ",
+ 'wificonn.working' => "Verbinden mit dem ausgewählten AP",
+ 'wificonn.fail' => "Verbindung fehlgeschlagen; prüfe die Einstellungen und versuche es erneut. Grund: ",
+
+ // Access restrictions form
+
+ 'pwlock.title' => 'Zugriffsbeschränkungen',
+ 'pwlock.explain' => '
+ Manche, oder alle Teile des Web-Interface können mit einem Passwort geschützt werden.
+ Lass die Passwortfelder leer wenn du es sie verändern möchtest.
+ Das voreingestellte Passwort ist "%def_access_pw%".',
+ 'pwlock.region' => 'Geschützte Seiten',
+ 'pwlock.region.none' => 'Keine, alles offen',
+ 'pwlock.region.settings_noterm' => 'WLAN-, Netzwerk- & Systemeinstellungen',
+ 'pwlock.region.settings' => 'Alle Einstellungsseiten',
+ 'pwlock.region.menus' => 'Dieser ganze Menüabschnitt',
+ 'pwlock.region.all' => 'Alles, sogar das Terminal',
+ 'pwlock.new_access_pw' => 'Neues Passwort',
+ 'pwlock.new_access_pw2' => 'Wiederholen',
+ 'pwlock.admin_pw' => 'Administratorpasswort',
+ 'pwlock.access_name' => 'Benutzername',
+
+ // Setting admin password
+
+ 'adminpw.title' => 'Administratorpasswort ändern',
+ 'adminpw.explain' =>'
+ Das "Administratorpasswort" wird benutzt, um die gespeicherten Standardeinstellungen
+ und die Zugriffsbeschränkungen zu verändern. Dieses Passwort wird nicht als Teil
+ der Hauptkonfiguration gespeichert, d.h. Speichern / Wiederherstellen wird das
+ Passwort nicht beeinflussen. Wenn das Administratorpasswort vergessen wird, ist
+ die einfachste Weise, wieder Zugriff zu erhalten, ein Re-flash des Chips.
+ Das voreingestellte Administratorpasswort ist "%def_admin_pw%".
+ ',
+ 'adminpw.new_admin_pw' => 'Neues Administratorpasswort',
+ 'adminpw.new_admin_pw2' => 'Wiederholen',
+ 'adminpw.old_admin_pw' => 'Altes Administratorpasswort',
+
+ // Persist form
+
+ 'persist.title' => 'Speichern & Wiederherstellen',
+ 'persist.explain' => '
+ ESPTerm speichert alle Einstellungen im Flash-Speicher. Die aktiven Einstellungen
+ können in den “Voreinstellungsbereich” kopiert werden und später wiederhergestellt
+ werden mit der Taste unten.',
+ 'persist.confirm_restore' => 'Alle Einstellungen zu den Voreinstellungen zurücksetzen?',
+ 'persist.confirm_restore_hard' => '
+ Zurücksetzen zu den Firmware-Voreinstellungen? Dies wird alle aktiven
+ Einstellungen zürucksetzen und den AP-Modus aktivieren mit der Standard-SSID.',
+ 'persist.confirm_store_defaults' =>
+ 'Administratorpasswort eingeben um Voreinstellungen zu überschreiben',
+ 'persist.password' => 'Administratorpasswort:',
+ 'persist.restore_defaults' => 'Zu gespeicherten Voreinstellungen zurücksetzen',
+ 'persist.write_defaults' => 'Aktive Einstellungen als Voreinstellungen speichern',
+ 'persist.restore_hard' => 'Aktive Einstellungen zu Werkseinstellungen zurücksetzen',
+ 'persist.restore_hard_explain' => '
+ (Dies löscht die WLAN-Konfiguration! Beeinflusst die gespeicherten Voreinstellungen
+ oder das Administratorpasswort nicht.)',
+
+ // UART settings form
+
+ 'uart.title' => 'Serienportparameter',
+ 'uart.explain' => '
+ Dies steuert den Kommunikations-UART. Der Debug-UART ist auf 115.200 baud fest
+ eingestellt mit einem Stop-Bit und keiner Parität.
+ ',
+ 'uart.baud' => 'Baudrate',
+ 'uart.parity' => 'Parität',
+ 'uart.parity.none' => 'Keine',
+ 'uart.parity.odd' => 'Ungerade',
+ 'uart.parity.even' => 'Gerade',
+ 'uart.stop_bits' => 'Stop-Bits',
+ 'uart.stop_bits.one' => 'Eins',
+ 'uart.stop_bits.one_and_half' => 'Eineinhalb',
+ 'uart.stop_bits.two' => 'Zwei',
+
+ // HW tuning form
+
+ 'hwtuning.title' => 'Hardware-Tuning',
+ 'hwtuning.explain' => '
+ ESP8266 kann overclocked werden von 80 MHz auf 160 MHz.
+ Alles wird etwas schneller sein, aber mit höherem Stromverbrauch,
+ und eventuell auch mit höherer Interferenz. Mit Sorgfalt benutzen.
+ ',
+ 'hwtuning.overclock' => 'Auf 160MHz Overclocken',
+
+ // Generic button / dialog labels
+
+ 'apply' => 'Bestätigen!',
+ 'enabled' => 'Aktiviert',
+ 'disabled' => 'Deaktiviert',
+ 'yes' => 'Ja',
+ 'no' => 'Nein',
+ 'confirm' => 'OK',
+ 'form_errors' => 'Gültigkeitsfehler für:',
];
diff --git a/lang/en.php b/lang/en.php
index 7de63a2..cc69837 100644
--- a/lang/en.php
+++ b/lang/en.php
@@ -52,7 +52,9 @@ return [
'term.defaults' => 'Initial Settings',
'term.expert' => 'Expert Options',
'term.explain_initials' => '
- Those are the initial settings used after ESPTerm powers on, or when the screen reset command is received (\ec
). They can be changed by the terminal application using escape sequences.
+ Those are the initial settings used after ESPTerm powers on,
+ or when the screen reset command is received (\ec
).
+ They can be changed by the terminal application using escape sequences.
',
'term.explain_expert' => '
Those are advanced config options that usually don\'t need to be changed.
@@ -61,7 +63,9 @@ return [
'term.example' => 'Default colors preview',
'term.explain_scheme' => '
- To select default text and background color, click on the preview palette. Alternatively, use numbers 0-15 for theme colors, 16-255 for standard colors and hex (#FFFFFF) for True Color (24-bit).
+ To select default text and background color, click on the
+ preview palette. Alternatively, use numbers 0-15 for theme colors,
+ 16-255 for standard colors and hex (#FFFFFF) for True Color (24-bit).
',
'term.fgbg_presets' => 'Defaults Presets',
@@ -155,10 +159,15 @@ return [
'wificonn.back_to_config' => 'Back to WiFi config',
'wificonn.telemetry_lost' => 'Telemetry lost; something went wrong, or your device disconnected.',
'wificonn.explain_android_sucks' => '
- If you\'re configuring ESPTerm via a smartphone, or were connected from another external network, your device may lose connection and this progress indicator won\'t work. Please wait a while (~ 15 seconds), then check if the connection succeeded.',
+ If you\'re configuring ESPTerm via a smartphone, or were connected
+ from another external network, your device may lose connection and
+ this progress indicator won\'t work. Please wait a while (~ 15 seconds),
+ then check if the connection succeeded.',
'wificonn.explain_reset' => '
- To force enable the built-in AP, hold the BOOT button until the blue LED starts flashing. Hold the button longer (until the LED flashes rapidly) for a "factory reset".',
+ To force enable the built-in AP, hold the BOOT button until the blue LED
+ starts flashing. Hold the button longer (until the LED flashes rapidly)
+ for a "factory reset".',
'wificonn.disabled' =>"Station mode is disabled.",
'wificonn.idle' =>"Idle, not connected and has no IP.",
@@ -190,7 +199,11 @@ return [
'adminpw.title' => 'Change Admin Password',
'adminpw.explain' =>
'
- The "admin password" is used to manipulate the stored default settings and to change access restrictions. This password is not saved as part of the main config, i.e. using save / restore does not affect this password. When the admin password is forgotten, the easiest way to re-gain access is to wipe and re-flash the chip.
+ The "admin password" is used to manipulate the stored default settings
+ and to change access restrictions. This password is not saved as part
+ of the main config, i.e. using save / restore does not affect this
+ password. When the admin password is forgotten, the easiest way to
+ re-gain access is to wipe and re-flash the chip.
The default admin password is "%def_admin_pw%".
',
'adminpw.new_admin_pw' => 'New admin password',
@@ -214,13 +227,15 @@ return [
'persist.restore_defaults' => 'Reset to saved defaults',
'persist.write_defaults' => 'Save active settings as defaults',
'persist.restore_hard' => 'Reset active settings to factory defaults',
- 'persist.restore_hard_explain' => '(This clears the WiFi config! Does not affect saved defaults or admin password.)',
+ 'persist.restore_hard_explain' =>
+ '(This clears the WiFi config! Does not affect saved defaults or admin password.)',
// UART settings form
'uart.title' => 'Serial Port Parameters',
'uart.explain' => '
- This form controls the communication UART. The debug UART is fixed at 115.200 baud, one stop-bit and no parity.
+ This form controls the communication UART. The debug UART is fixed
+ at 115.200 baud, one stop-bit and no parity.
',
'uart.baud' => 'Baud rate',
'uart.parity' => 'Parity',
@@ -236,7 +251,10 @@ return [
'hwtuning.title' => 'Hardware Tuning',
'hwtuning.explain' => '
- ESP8266 can be overclocked from 80 MHz to 160 MHz. This will make it more responsive and allow faster screen updates at the expense of slightly higher power consumption. This can also make it more susceptible to interference. Use with care.
+ ESP8266 can be overclocked from 80 MHz to 160 MHz. This will make
+ it more responsive and allow faster screen updates at the expense of slightly
+ higher power consumption. This can also make it more susceptible to interference.
+ Use with care.
',
'hwtuning.overclock' => 'Overclock to 160MHz',
From 7c912035289c0d43283625a738a39d341ac383b7 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sat, 30 Sep 2017 22:16:01 +0200
Subject: [PATCH 45/86] Fix parser derp, show internal info if available
---
js/term/buttons.js | 1 -
js/term/debug_screen.js | 16 ++++++++++++++++
js/term/screen_parser.js | 38 ++++++++++++++++++++++++--------------
3 files changed, 40 insertions(+), 15 deletions(-)
diff --git a/js/term/buttons.js b/js/term/buttons.js
index ceb5e69..929464d 100644
--- a/js/term/buttons.js
+++ b/js/term/buttons.js
@@ -34,7 +34,6 @@ module.exports = function initButtons (input) {
// sync with DOM
let update = function updateButtons () {
- console.log(labels)
if (labels.length > buttons.length) {
for (let i = buttons.length; i < labels.length; i++) {
pushButton()
diff --git a/js/term/debug_screen.js b/js/term/debug_screen.js
index 0f486c6..b4c58a1 100644
--- a/js/term/debug_screen.js
+++ b/js/term/debug_screen.js
@@ -247,14 +247,30 @@ module.exports = function attachDebugScreen (screen) {
return `((${y},${x})=${cell}:${hexcode}:F${cellFG}:B${cellBG}:A${cellAttrs.toString(2)})`
}
+ let internalInfo = {}
+
updateToolbar = () => {
if (!toolbarAttached) return
let text = `C((${screen.cursor.y},${screen.cursor.x}),hang:${screen.cursor.hanging},vis:${screen.cursor.visible})`
if (mouseHoverCell) {
text += ' m' + getCellData(mouseHoverCell[1] * screen.window.width + mouseHoverCell[0])
}
+ if ('flags' in internalInfo) {
+ // we got ourselves some internal data
+ text += ' '
+ text += ` flags:${internalInfo.flags}`
+ text += ` curAttrs:${internalInfo.cursorAttrs}`
+ text += ` Region:${internalInfo.regionStart}->${internalInfo.regionEnd}`
+ text += ` Charset:${internalInfo.charsetGx} (0:${internalInfo.charsetG0},1:${internalInfo.charsetG1})`
+ text += ` Heap:${internalInfo.freeHeap}`
+ text += ` Clients:${internalInfo.clientCount}`
+ }
dataDisplay.textContent = text
}
screen.on('draw', updateToolbar)
+ screen.on('internal', data => {
+ internalInfo = data
+ updateToolbar()
+ })
}
diff --git a/js/term/screen_parser.js b/js/term/screen_parser.js
index 16400a6..8e20ab3 100644
--- a/js/term/screen_parser.js
+++ b/js/term/screen_parser.js
@@ -212,8 +212,8 @@ module.exports = class ScreenParser {
this.screen.beep()
} else if (topic === TOPIC_INTERNAL) {
-
// debug info
+
const flags = du(strArray[ci++])
const cursorAttrs = du(strArray[ci++])
const regionStart = du(strArray[ci++])
@@ -222,15 +222,25 @@ module.exports = class ScreenParser {
const charsetG0 = strArray[ci++]
const charsetG1 = strArray[ci++]
const freeHeap = du(strArray[ci++])
- const numClients = du(strArray[ci++])
- // TODO do something with those
-
+ const clientCount = du(strArray[ci++])
+
+ this.emit('internal', {
+ flags,
+ cursorAttrs,
+ regionStart,
+ regionEnd,
+ charsetGx,
+ charsetG0,
+ charsetG1,
+ freeHeap,
+ clientCount
+ })
} else if (topic === TOPIC_CONTENT) {
// set screen content
const frameY = du(strArray[ci++])
const frameX = du(strArray[ci++])
- const frameHeight = du(strArray[ci++]) // FIXME unused, useless data!
+ const frameHeight = du(strArray[ci++])
const frameWidth = du(strArray[ci++])
// content
@@ -239,7 +249,7 @@ module.exports = class ScreenParser {
let attrs = 0
let cell = 0 // cell index
let lastChar = ' '
- let screenLength = this.screen.window.width * this.screen.window.height
+ let screenLength = frameWidth * frameHeight
if (resized) {
this.screen.updateSize()
@@ -258,11 +268,13 @@ module.exports = class ScreenParser {
let myAttrs = attrs
let hasFG = attrs & ATTR_FG
let hasBG = attrs & ATTR_BG
+ let cellFG = fg
+ let cellBG = bg
// use 0,0 if no fg/bg. this is to match back-end implementation
// and allow leaving out fg/bg setting for cells with none
- if (!hasFG) fg = 0
- if (!hasBG) bg = 0
+ if (!hasFG) cellFG = 0
+ if (!hasBG) cellBG = 0
if ((myAttrs & MASK_BLINK) !== 0 &&
((lastChar === ' ' && ((myAttrs & MASK_LINE_ATTR) === 0)) || // no line styles
@@ -281,16 +293,14 @@ module.exports = class ScreenParser {
let cellYInFrame = Math.floor(cell / frameWidth)
let index = (frameY + cellYInFrame) * this.screen.window.width + frameX + cellXInFrame
- let cellFg = fg
-
// 8 dark system colors turn bright when bold
- if ((myAttrs & ATTR_BOLD) && !(myAttrs & ATTR_FAINT) && hasFG && fg < 8) {
- cellFg += 8
+ if ((myAttrs & ATTR_BOLD) && !(myAttrs & ATTR_FAINT) && hasFG && cellFG < 8) {
+ cellFG += 8
}
this.screen.screen[index] = lastChar
- this.screen.screenFG[index] = cellFg
- this.screen.screenBG[index] = bg
+ this.screen.screenFG[index] = cellFG
+ this.screen.screenBG[index] = cellBG
this.screen.screenAttrs[index] = myAttrs
}
From e105344ccc83eccf2d3956af7742f8478f0a226d Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sat, 30 Sep 2017 22:21:35 +0200
Subject: [PATCH 46/86] Remove generated lang.js
---
.gitignore | 1 +
js/lang.js | 14 --------------
2 files changed, 1 insertion(+), 14 deletions(-)
delete mode 100644 js/lang.js
diff --git a/.gitignore b/.gitignore
index 0de9aaf..015a031 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ node_modules/
.idea
.sass-cache
*.map
+js/lang.js
diff --git a/js/lang.js b/js/lang.js
deleted file mode 100644
index 429f1ac..0000000
--- a/js/lang.js
+++ /dev/null
@@ -1,14 +0,0 @@
-// Generated from PHP locale file
-let _tr = {
- "wifi.connected_ip_is": "Connected, IP is ",
- "wifi.not_conn": "Not connected.",
- "wifi.enter_passwd": "Enter password for \":ssid:\"",
- "term_nav.fullscreen": "Fullscreen",
- "term_conn.connecting": "Connecting",
- "term_conn.waiting_content": "Waiting for content",
- "term_conn.disconnected": "Disconnected",
- "term_conn.waiting_server": "Waiting for server",
- "term_conn.reconnecting": "Reconnecting"
-};
-
-module.exports = function tr (key) { return _tr[key] || '?' + key + '?' }
From c7b13ddaff487cb56d76946ed0014b77b3941310 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sat, 30 Sep 2017 22:29:06 +0200
Subject: [PATCH 47/86] Screen length & frame length are different things
---
js/term/screen_parser.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/js/term/screen_parser.js b/js/term/screen_parser.js
index 8e20ab3..b5fec5c 100644
--- a/js/term/screen_parser.js
+++ b/js/term/screen_parser.js
@@ -249,7 +249,8 @@ module.exports = class ScreenParser {
let attrs = 0
let cell = 0 // cell index
let lastChar = ' '
- let screenLength = frameWidth * frameHeight
+ let frameLength = frameWidth * frameHeight
+ let screenLength = this.screen.window.width * this.screen.window.height
if (resized) {
this.screen.updateSize()
@@ -304,7 +305,7 @@ module.exports = class ScreenParser {
this.screen.screenAttrs[index] = myAttrs
}
- while (ci < strArray.length && cell < screenLength) {
+ while (ci < strArray.length && cell < frameLength) {
let character = strArray[ci++]
let charCode = character.codePointAt(0)
@@ -314,7 +315,7 @@ module.exports = class ScreenParser {
count = du(strArray[ci++])
for (let j = 0; j < count; j++) {
pushCell()
- if (++cell > screenLength) break
+ if (++cell > frameLength) break
}
break
From 4e65c575297841a98e55545f2819e3763398f0cb Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sat, 30 Sep 2017 22:47:57 +0200
Subject: [PATCH 48/86] Fix emit being called on the wrong object
---
js/term/screen_parser.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/term/screen_parser.js b/js/term/screen_parser.js
index b5fec5c..2d0ebff 100644
--- a/js/term/screen_parser.js
+++ b/js/term/screen_parser.js
@@ -224,7 +224,7 @@ module.exports = class ScreenParser {
const freeHeap = du(strArray[ci++])
const clientCount = du(strArray[ci++])
- this.emit('internal', {
+ this.screen.emit('internal', {
flags,
cursorAttrs,
regionStart,
From 4c42230a4466cdfb7742a7ba71cca48a8fb5a14e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sat, 30 Sep 2017 22:42:52 +0200
Subject: [PATCH 49/86] partial cz translation, improvd lang funcs
---
base.php | 22 +++-
dump_js_lang.php | 14 +--
lang/common.php | 19 ++++
lang/cs.php | 255 +++++++++++++++++++++++++++++++++++++++++++++++
lang/de.php | 16 ---
lang/en.php | 16 ---
sass/app.scss | 2 +-
7 files changed, 301 insertions(+), 43 deletions(-)
create mode 100644 lang/common.php
create mode 100644 lang/cs.php
diff --git a/base.php b/base.php
index a7dc7f5..57ce7fb 100644
--- a/base.php
+++ b/base.php
@@ -62,6 +62,8 @@ APS
define('LOCALE', isset($_GET['locale']) ? $_GET['locale'] : (getenv('ESP_LANG') ?: 'en'));
$_messages = require(__DIR__ . '/lang/' . LOCALE . '.php');
+$_messages_fallback = require(__DIR__ . '/lang/en.php');
+$_messages_common = require(__DIR__ . '/lang/common.php');
$_pages = require(__DIR__ . '/_pages.php');
define('APP_NAME', 'ESPTerm');
@@ -97,12 +99,26 @@ function je($s)
function tr($key)
{
- global $_messages;
- if (isset($_messages[$key])) return $_messages[$key];
- else {
+ global $_messages, $_messages_fallback, $_messages_common;
+
+ if (isset($_messages[$key])) {
+ $str = $_messages[$key];
+ }
+ else if (isset($_messages_fallback[$key])) {
+ $str = $_messages_fallback[$key];
+ }
+ else if (isset($_messages_common[$key])) {
+ $str = $_messages_common[$key];
+ }
+ else{
ob_end_clean();
die('??' . $key . '??');
}
+
+ // allow tildes in translation
+ $str = preg_replace('/(?<=[^ \\\\])~(?=[^ ])/', ' ', $str);
+ $str = str_replace('\~', '~', $str);
+ return $str;
}
/** Like eval, but allows */
diff --git a/dump_js_lang.php b/dump_js_lang.php
index 6c85fa7..80196de 100755
--- a/dump_js_lang.php
+++ b/dump_js_lang.php
@@ -8,17 +8,17 @@ $selected = [
'wifi.connected_ip_is',
'wifi.not_conn',
'wifi.enter_passwd',
- 'term_nav.fullscreen',
- 'term_conn.connecting',
- 'term_conn.waiting_content',
- 'term_conn.disconnected',
- 'term_conn.waiting_server',
- 'term_conn.reconnecting'
+ 'term_nav.fullscreen',
+ 'term_conn.connecting',
+ 'term_conn.waiting_content',
+ 'term_conn.disconnected',
+ 'term_conn.waiting_server',
+ 'term_conn.reconnecting'
];
$out = [];
foreach ($selected as $key) {
- $out[$key] = $_messages[$key];
+ $out[$key] = tr($key);
}
file_put_contents(__DIR__. '/js/lang.js',
diff --git a/lang/common.php b/lang/common.php
new file mode 100644
index 0000000..f2d6c75
--- /dev/null
+++ b/lang/common.php
@@ -0,0 +1,19 @@
+ 'ESPTerm',
+ 'appname_demo' => 'ESPTerm DEMO',
+
+ // not used - api etc. Added to suppress warnings
+ 'menu.term_set' => '',
+ 'menu.wifi_connstatus' => '',
+ 'menu.wifi_set' => '',
+ 'menu.wifi_scan' => '',
+ 'menu.network_set' => '',
+ 'menu.system_set' => '',
+ 'menu.write_defaults' => '',
+ 'menu.restore_defaults' => '',
+ 'menu.restore_hard' => '',
+ 'menu.reset_screen' => '',
+ 'menu.index' => '',
+];
diff --git a/lang/cs.php b/lang/cs.php
new file mode 100644
index 0000000..9c39e10
--- /dev/null
+++ b/lang/cs.php
@@ -0,0 +1,255 @@
+ 'Nastavení WiFi',
+ 'menu.cfg_network' => 'Nastavení sítě',
+ 'menu.cfg_term' => 'Nastavení terminalu',
+ 'menu.about' => 'About',
+ 'menu.help' => 'Nápověda',
+ 'menu.term' => 'Zpět k terminálu',
+ 'menu.cfg_system' => 'Nastavení systému',
+ 'menu.cfg_wifi_conn' => 'Připojování',
+ 'menu.settings' => 'Nastavení',
+
+ // Terminal page
+
+ 'title.term' => 'Terminál', // page title of the terminal page
+
+ 'term_nav.fullscreen' => 'Celá obr.',
+ 'term_nav.config' => 'Nastavení',
+ 'term_nav.wifi' => 'WiFi',
+ 'term_nav.help' => 'Nápověda',
+ 'term_nav.about' => 'About',
+ 'term_nav.paste' => 'Vložit',
+ 'term_nav.upload' => 'Nahrát',
+ 'term_nav.keybd' => 'Klávesnice',
+ 'term_nav.paste_prompt' => 'Vložte text k~odeslání:',
+
+ 'term_conn.connecting' => 'Připojuji se',
+ 'term_conn.waiting_content' => 'Čekám na data',
+ 'term_conn.disconnected' => 'Odpojen',
+ 'term_conn.waiting_server' => 'Čekám na server',
+ 'term_conn.reconnecting' => 'Obnova spojení',
+
+ // Terminal settings page
+
+ 'term.defaults' => 'Výchozí nastavení',
+ 'term.expert' => 'Pokročilé volby',
+ 'term.explain_initials' => '
+ Tato nastavení jsou použita po spuštění a při resetu obrazovky
+ (příkaz RIS, \ec
). Tyto volby lze měnit za běhu
+ pomocí řídicích sekvencí.
+ ',
+ 'term.explain_expert' => '
+ Interní parametry terminálu. Změnou časování lze dosáhnout kratší
+ latence a~rychlejšího překreslování, hodnoty záleží na konkrétní
+ aplikaci. Timeout parseru je čas do automatického zrušení započaté
+ řídicí sekvence.',
+
+ 'term.example' => 'Náhled výchozích barev',
+
+ 'term.explain_scheme' => '
+ Výchozí barvu textu a pozadí vyberete kliknutím na barvy v~paletě.
+ Dále lze použít ANSI barvy 0-255 a hex ve formátu #FFFFFF.
+ ',
+
+ 'term.fgbg_presets' => 'Předvolby výchozích
barev textu a pozadí',
+ 'term.color_scheme' => 'Barevné schéma',
+ 'term.reset_screen' => 'Resetovat obrazovku a parser',
+ 'term.term_title' => 'Nadpis',
+ 'term.term_width' => 'Šířka',
+ 'term.term_height' => 'Výška',
+ 'term.buttons' => 'Text tlačítke',
+ 'term.theme' => 'Barevná paleta',
+ 'term.cursor_shape' => 'Styl kurzoru',
+ 'term.parser_tout_ms' => 'Timeout parseru',
+ 'term.display_tout_ms' => 'Prodleva překreslení',
+ 'term.display_cooldown_ms' => 'Min. čas překreslení',
+ 'term.allow_decopt_12' => 'Povolit \e?12h/l',
+ 'term.fn_alt_mode' => 'SS3 Fx klávesy',
+ 'term.show_config_links' => 'Menu pod obrazovkou',
+ 'term.show_buttons' => 'Zobrazit tlačítka',
+ 'term.loopback' => 'Loopback (SRM)',
+ 'term.crlf_mode' => 'Enter = CR+LF (LNM)',
+ 'term.want_all_fn' => 'Zachytávat F5, F11, F12',
+ 'term.button_msgs' => 'Reporty tlačítek
(dek. ASCII CSV)',
+ 'term.color_fg' => 'Výchozí text',
+ 'term.color_bg' => 'Výchozí pozadí',
+ 'term.color_fg_prev' => 'Barva textu',
+ 'term.color_bg_prev' => 'Barva pozadí',
+ 'term.colors_preview' => '',
+
+ 'cursor.block_blink' => 'Blok, blikající',
+ 'cursor.block_steady' => 'Blok, stálý',
+ 'cursor.underline_blink' => 'Podtržítko, blikající',
+ 'cursor.underline_steady' => 'Podtržítko, stálé',
+ 'cursor.bar_blink' => 'Svislice, blikající',
+ 'cursor.bar_steady' => 'Svislice, stálá',
+
+ // Network config page
+
+ 'net.explain_sta' => '
+ Odškrtněte "Použít dynamickou IP" pro nastavení statické IP adresy.',
+
+ 'net.explain_ap' => '
+ Tato nastavení ovlivňují interní DHCP server v AP režimu (hotspot).',
+
+ 'net.ap_dhcp_time' => 'Doba zapůjčení adresy',
+ 'net.ap_dhcp_start' => 'Začátek IP poolu',
+ 'net.ap_dhcp_end' => 'Konec IP poolu',
+ 'net.ap_addr_ip' => 'Vlastní IP adresa',
+ 'net.ap_addr_mask' => 'Maska podsítě',
+
+ 'net.sta_dhcp_enable' => 'Použít dynamickou IP',
+ 'net.sta_addr_ip' => 'Statická IP modulu',
+ 'net.sta_addr_mask' => 'Maska podsítě',
+ 'net.sta_addr_gw' => 'Gateway',
+
+ 'net.ap' => 'DHCP server (AP)',
+ 'net.sta' => 'DHCP klient',
+ 'net.sta_mac' => 'MAC adresa klienta',
+ 'net.ap_mac' => 'MAC adresa AP',
+ 'net.details' => 'MAC adresy',
+
+ // Wifi config page
+
+ 'wifi.ap' => 'Vlastní hotspot (AP)',
+ 'wifi.sta' => 'Připojení k~externí síti',
+
+ 'wifi.enable' => 'Zapnuto',
+ 'wifi.tpw' => 'Vysílací výkon',
+ 'wifi.ap_channel' => 'WiFi kanál',
+ 'wifi.ap_ssid' => 'Jméno hotspotu',
+ 'wifi.ap_password' => 'Přístupové heslo',
+ 'wifi.ap_hidden' => 'Skrýt síť',
+ 'wifi.sta_info' => 'Zvolená síť',
+
+ 'wifi.not_conn' => 'Nepřipojen.',
+ 'wifi.sta_none' => 'Žádná',
+ 'wifi.sta_active_pw' => '🔒 Heslo uloženo',
+ 'wifi.sta_active_nopw' => '🔓 Bez hesla',
+ 'wifi.connected_ip_is' => 'Připojen, IP: ',
+ 'wifi.sta_password' => 'Heslo:',
+
+ 'wifi.scanning' => 'Hledám sítě',
+ 'wifi.scan_now' => 'Klikněte pro vyhledání sítí!',
+ 'wifi.cant_scan_no_sta' => 'Klikněte pro zapnutí režimu klienta a vyhledání sítí!',
+ 'wifi.select_ssid' => 'Dostupné sítě:',
+ 'wifi.enter_passwd' => 'Zadejte heslo pro ":ssid:"',
+ 'wifi.sta_explain' => 'Vyberte síť a připojte se tlačítkem vpravo nahoře.',
+
+ // Wifi connecting status page
+
+ 'wificonn.status' => 'Stav:',
+ 'wificonn.back_to_config' => 'Zpět k~nastavení WiFi',
+ 'wificonn.telemetry_lost' => 'Telemetry lost; something went wrong, or your device disconnected.',
+ 'wificonn.explain_android_sucks' => '
+ If you\'re configuring ESPTerm via a smartphone, or were connected
+ from another external network, your device may lose connection and
+ this progress indicator won\'t work. Please wait a while (~ 15 seconds),
+ then check if the connection succeeded.',
+
+ 'wificonn.explain_reset' => '
+ To force enable the built-in AP, hold the BOOT button until the blue LED
+ starts flashing. Hold the button longer (until the LED flashes rapidly)
+ for a "factory reset".',
+
+ 'wificonn.disabled' =>"Station mode is disabled.",
+ 'wificonn.idle' =>"Idle, not connected and has no IP.",
+ 'wificonn.success' => "Connected! Received IP ",
+ 'wificonn.working' => "Connecting to selected AP",
+ 'wificonn.fail' => "Connection failed, check settings & try again. Cause: ",
+
+ // Access restrictions form
+
+ 'pwlock.title' => 'Access Restrictions',
+ 'pwlock.explain' => '
+ Some parts, or all of the web interface can be protected by a password prompt.
+ Leave the new password fields empty if you do not wish to change it.
+ The default password is "%def_access_pw%".
+ ',
+ 'pwlock.region' => 'Protected pages',
+ 'pwlock.region.none' => 'None, all open',
+ 'pwlock.region.settings_noterm' => 'WiFi, Net & System settings',
+ 'pwlock.region.settings' => 'All settings pages',
+ 'pwlock.region.menus' => 'This entire menu section',
+ 'pwlock.region.all' => 'Everything, even terminal',
+ 'pwlock.new_access_pw' => 'New password',
+ 'pwlock.new_access_pw2' => 'Repeat',
+ 'pwlock.admin_pw' => 'Admin password',
+ 'pwlock.access_name' => 'Username',
+
+ // Setting admin password
+
+ 'adminpw.title' => 'Change Admin Password',
+ 'adminpw.explain' =>
+ '
+ The "admin password" is used to manipulate the stored default settings
+ and to change access restrictions. This password is not saved as part
+ of the main config, i.e. using save / restore does not affect this
+ password. When the admin password is forgotten, the easiest way to
+ re-gain access is to wipe and re-flash the chip.
+ The default admin password is "%def_admin_pw%".
+ ',
+ 'adminpw.new_admin_pw' => 'New admin password',
+ 'adminpw.new_admin_pw2' => 'Repeat',
+ 'adminpw.old_admin_pw' => 'Old admin password',
+
+ // Persist form
+
+ 'persist.title' => 'Save & Restore',
+ 'persist.explain' => '
+ ESPTerm saves all settings in Flash. The active settings can be copied to
+ the "defaults area" and restored later using the blue button below.
+ ',
+ 'persist.confirm_restore' => 'Restore all settings to their default values?',
+ 'persist.confirm_restore_hard' =>
+ 'Restore to firmware default settings? This will reset ' .
+ 'all active settings and switch to AP mode with the default SSID.',
+ 'persist.confirm_store_defaults' =>
+ 'Enter admin password to confirm you want to overwrite the default settings.',
+ 'persist.password' => 'Admin password:',
+ 'persist.restore_defaults' => 'Reset to saved defaults',
+ 'persist.write_defaults' => 'Save active settings as defaults',
+ 'persist.restore_hard' => 'Reset active settings to factory defaults',
+ 'persist.restore_hard_explain' =>
+ '(This clears the WiFi config! Does not affect saved defaults or admin password.)',
+
+ // UART settings form
+
+ 'uart.title' => 'Serial Port Parameters',
+ 'uart.explain' => '
+ This form controls the communication UART. The debug UART is fixed
+ at 115.200 baud, one stop-bit and no parity.
+ ',
+ 'uart.baud' => 'Baud rate',
+ 'uart.parity' => 'Parity',
+ 'uart.parity.none' => 'None',
+ 'uart.parity.odd' => 'Odd',
+ 'uart.parity.even' => 'Even',
+ 'uart.stop_bits' => 'Stop-bits',
+ 'uart.stop_bits.one' => 'One',
+ 'uart.stop_bits.one_and_half' => 'One and half',
+ 'uart.stop_bits.two' => 'Two',
+
+ // HW tuning form
+
+ 'hwtuning.title' => 'Hardware Tuning',
+ 'hwtuning.explain' => '
+ ESP8266 can be overclocked from 80 MHz to 160 MHz. This will make
+ it more responsive and allow faster screen updates at the expense of slightly
+ higher power consumption. This can also make it more susceptible to interference.
+ Use with care.
+ ',
+ 'hwtuning.overclock' => 'Overclock to 160MHz',
+
+ // Generic button / dialog labels
+
+ 'apply' => 'Apply!',
+ 'enabled' => 'Enabled',
+ 'disabled' => 'Disabled',
+ 'yes' => 'Yes',
+ 'no' => 'No',
+ 'confirm' => 'OK',
+ 'form_errors' => 'Validation errors for:',
+];
diff --git a/lang/de.php b/lang/de.php
index 36218b7..9f840e7 100644
--- a/lang/de.php
+++ b/lang/de.php
@@ -1,9 +1,6 @@
'ESPTerm',
- 'appname_demo' => 'ESPTerm DEMO',
-
'menu.cfg_wifi' => 'WLAN-Einstellungen',
'menu.cfg_network' => 'Netzwerkeinstellungen',
'menu.cfg_term' => 'Terminaleinstellungen',
@@ -14,19 +11,6 @@ return [
'menu.cfg_wifi_conn' => 'Verbinden mit dem Netzwerk',
'menu.settings' => 'Einstellungen',
- // not used - api etc. Added to suppress warnings
- 'menu.term_set' => '',
- 'menu.wifi_connstatus' => '',
- 'menu.wifi_set' => '',
- 'menu.wifi_scan' => '',
- 'menu.network_set' => '',
- 'menu.system_set' => '',
- 'menu.write_defaults' => '',
- 'menu.restore_defaults' => '',
- 'menu.restore_hard' => '',
- 'menu.reset_screen' => '',
- 'menu.index' => '',
-
// Terminal page
'title.term' => 'Terminal', // page title of the terminal page
diff --git a/lang/en.php b/lang/en.php
index cc69837..17adff0 100644
--- a/lang/en.php
+++ b/lang/en.php
@@ -1,9 +1,6 @@
'ESPTerm',
- 'appname_demo' => 'ESPTerm DEMO',
-
'menu.cfg_wifi' => 'WiFi Settings',
'menu.cfg_network' => 'Network Settings',
'menu.cfg_term' => 'Terminal Settings',
@@ -14,19 +11,6 @@ return [
'menu.cfg_wifi_conn' => 'Connecting to Network',
'menu.settings' => 'Settings',
- // not used - api etc. Added to suppress warnings
- 'menu.term_set' => '',
- 'menu.wifi_connstatus' => '',
- 'menu.wifi_set' => '',
- 'menu.wifi_scan' => '',
- 'menu.network_set' => '',
- 'menu.system_set' => '',
- 'menu.write_defaults' => '',
- 'menu.restore_defaults' => '',
- 'menu.restore_hard' => '',
- 'menu.reset_screen' => '',
- 'menu.index' => '',
-
// Terminal page
'title.term' => 'Terminal', // page title of the terminal page
diff --git a/sass/app.scss b/sass/app.scss
index 51dcf1e..5397f25 100644
--- a/sass/app.scss
+++ b/sass/app.scss
@@ -7,7 +7,7 @@
@import "utils";
-$form-label-w: 180px;
+$form-label-w: 220px;
$form-label-gap: 8px;
$form-field-w: 250px;
From f9e687bf8db928cca5d705fa738f5dde7f33c558 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sat, 30 Sep 2017 23:37:45 +0200
Subject: [PATCH 50/86] Fix debug toolbar being too wide
---
sass/pages/_term.scss | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sass/pages/_term.scss b/sass/pages/_term.scss
index e7bc72b..f547456 100644
--- a/sass/pages/_term.scss
+++ b/sass/pages/_term.scss
@@ -111,6 +111,9 @@ body.term {
padding: 6px;
font-family: $screen-stack;
font-size: 12px;
+ white-space: normal;
+ // close enough:
+ max-width: 400px;
}
}
From 4711d1c17ca91863e94136505b41aa451adf91e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sat, 30 Sep 2017 23:40:23 +0200
Subject: [PATCH 51/86] added more cs lang
---
lang/cs.php | 149 ++++++++++++++++++++++++++--------------------------
1 file changed, 74 insertions(+), 75 deletions(-)
diff --git a/lang/cs.php b/lang/cs.php
index 9c39e10..97dc7de 100644
--- a/lang/cs.php
+++ b/lang/cs.php
@@ -113,7 +113,7 @@ return [
// Wifi config page
- 'wifi.ap' => 'Vlastní hotspot (AP)',
+ 'wifi.ap' => 'WiFi hotspot',
'wifi.sta' => 'Připojení k~externí síti',
'wifi.enable' => 'Zapnuto',
@@ -126,7 +126,7 @@ return [
'wifi.not_conn' => 'Nepřipojen.',
'wifi.sta_none' => 'Žádná',
- 'wifi.sta_active_pw' => '🔒 Heslo uloženo',
+ 'wifi.sta_active_pw' => '🔒 Uložené heslo',
'wifi.sta_active_nopw' => '🔓 Bez hesla',
'wifi.connected_ip_is' => 'Připojen, IP: ',
'wifi.sta_password' => 'Heslo:',
@@ -142,114 +142,113 @@ return [
'wificonn.status' => 'Stav:',
'wificonn.back_to_config' => 'Zpět k~nastavení WiFi',
- 'wificonn.telemetry_lost' => 'Telemetry lost; something went wrong, or your device disconnected.',
+ 'wificonn.telemetry_lost' => 'Spojení bylo přerušeno; připojování selhalo, nebo jste byli odpojeni od sítě.',
'wificonn.explain_android_sucks' => '
- If you\'re configuring ESPTerm via a smartphone, or were connected
- from another external network, your device may lose connection and
- this progress indicator won\'t work. Please wait a while (~ 15 seconds),
- then check if the connection succeeded.',
+ Pokud ESPTerm konfigurujete pomocí mobilu nebo z~externí sítě, může se stát
+ že některé ze zařízení změní síť a~ukazatel průběhu přestane fungovat.
+ Počkejte ~15s a pak zkontrolujte, zda se připojení zdařilo.
+ ',
'wificonn.explain_reset' => '
- To force enable the built-in AP, hold the BOOT button until the blue LED
- starts flashing. Hold the button longer (until the LED flashes rapidly)
- for a "factory reset".',
+ Interní hotspot lze kdykoliv vynutit podržením tlačítka BOOT, až modrá LED začne blikat.
+ Podržíte-li tlačítko déle (LED začne blikat rychleji), dojde k~obnovení do výchozích anstavení.',
- 'wificonn.disabled' =>"Station mode is disabled.",
- 'wificonn.idle' =>"Idle, not connected and has no IP.",
- 'wificonn.success' => "Connected! Received IP ",
- 'wificonn.working' => "Connecting to selected AP",
- 'wificonn.fail' => "Connection failed, check settings & try again. Cause: ",
+ 'wificonn.disabled' => "Režim klienta není povolen.",
+ 'wificonn.idle' => "Žádná IP adresa, připojování neprobíhá.",
+ 'wificonn.success' => "Připijen! IP adresa je ",
+ 'wificonn.working' => "Připojuji k zvolené síti",
+ 'wificonn.fail' => "Připojení selhalo, zkontrolujte nastavení a~pokus opakujte. Důvod: ",
// Access restrictions form
- 'pwlock.title' => 'Access Restrictions',
+ 'pwlock.title' => 'Omezení přístupu',
'pwlock.explain' => '
- Some parts, or all of the web interface can be protected by a password prompt.
- Leave the new password fields empty if you do not wish to change it.
- The default password is "%def_access_pw%".
+ Části webového rozhraní lze chránit heslem. Nemáte-li v úmyslu heslo měnit,
+ do jeho políčka nic nevyplňujte.
+ Výchozí přístupové heslo je "%def_access_pw%".
',
- 'pwlock.region' => 'Protected pages',
- 'pwlock.region.none' => 'None, all open',
- 'pwlock.region.settings_noterm' => 'WiFi, Net & System settings',
- 'pwlock.region.settings' => 'All settings pages',
- 'pwlock.region.menus' => 'This entire menu section',
- 'pwlock.region.all' => 'Everything, even terminal',
- 'pwlock.new_access_pw' => 'New password',
- 'pwlock.new_access_pw2' => 'Repeat',
- 'pwlock.admin_pw' => 'Admin password',
- 'pwlock.access_name' => 'Username',
+ 'pwlock.region' => 'Chránit heslem',
+ 'pwlock.region.none' => 'Nic, vše volně přístupné',
+ 'pwlock.region.settings_noterm' => 'Nastavení, mimo terminál',
+ 'pwlock.region.settings' => 'Všechna nastavení',
+ 'pwlock.region.menus' => 'Celá admin. sekce',
+ 'pwlock.region.all' => 'Vše, včetně terminálu',
+ 'pwlock.new_access_pw' => 'Nové přístupové heslo',
+ 'pwlock.new_access_pw2' => 'Zopakujte nové heslo',
+ 'pwlock.admin_pw' => 'Systémové heslo',
+ 'pwlock.access_name' => 'Uživatelské jméno',
// Setting admin password
- 'adminpw.title' => 'Change Admin Password',
+ 'adminpw.title' => 'Změna systémového hesla',
'adminpw.explain' =>
'
- The "admin password" is used to manipulate the stored default settings
- and to change access restrictions. This password is not saved as part
- of the main config, i.e. using save / restore does not affect this
- password. When the admin password is forgotten, the easiest way to
- re-gain access is to wipe and re-flash the chip.
- The default admin password is "%def_admin_pw%".
+ Systémové heslo slouží k úpravám uložených výchozích nastavení
+ a ke změně přístupových oprávnění.
+ Toto heslo je uloženo mimo ostatní data, obnovení do výchozách nastavení
+ na něj nemá vliv.
+ Toto heslo nelze jednoduše obnovit, v případě zapomenutí vymažte flash paměť a obnovte firmware.
+ Vychozí systémové heslo je "%def_admin_pw%".
',
- 'adminpw.new_admin_pw' => 'New admin password',
- 'adminpw.new_admin_pw2' => 'Repeat',
- 'adminpw.old_admin_pw' => 'Old admin password',
+ 'adminpw.new_admin_pw' => 'Nové systémové heslo',
+ 'adminpw.new_admin_pw2' => 'Zopakujte nové heslo',
+ 'adminpw.old_admin_pw' => 'Původní systémové heslo',
// Persist form
- 'persist.title' => 'Save & Restore',
+ 'persist.title' => 'Záloha a~obnovení konfigurace',
'persist.explain' => '
- ESPTerm saves all settings in Flash. The active settings can be copied to
- the "defaults area" and restored later using the blue button below.
+ Všechna nastavení jsou ukládána do flash paměti. V~paměti jsou
+ vyhrazené dva oddíly, aktivní nastavení a záloha. Zálohu lze přepsat
+ za použití systémového hesla, původní nastavení z ní pak můžete kdykoliv obnovit.
+ Pro obnovení ze zálohy stačí podržet tlačítko BOOT, až modrá LED začne rychle blikat.
',
- 'persist.confirm_restore' => 'Restore all settings to their default values?',
+ 'persist.confirm_restore' => 'Chcete obnovit všechna nastavení?',
'persist.confirm_restore_hard' =>
- 'Restore to firmware default settings? This will reset ' .
- 'all active settings and switch to AP mode with the default SSID.',
+ 'Opravdu chcete načíst tovární nastavení? Všechna nastavení kromě zálohy a systémového hesla
+ budou přepsána, včetně nastavení WiFi!',
'persist.confirm_store_defaults' =>
- 'Enter admin password to confirm you want to overwrite the default settings.',
- 'persist.password' => 'Admin password:',
- 'persist.restore_defaults' => 'Reset to saved defaults',
- 'persist.write_defaults' => 'Save active settings as defaults',
- 'persist.restore_hard' => 'Reset active settings to factory defaults',
+ 'Zadejte systémové heslo pro přepsání zálohy aktuálními parametry.',
+ 'persist.password' => 'Systémové heslo:',
+ 'persist.restore_defaults' => 'Obnovit ze zálohy',
+ 'persist.write_defaults' => 'Zálohovat aktuální nastavení',
+ 'persist.restore_hard' => 'Načíst tovární nastavení',
'persist.restore_hard_explain' =>
- '(This clears the WiFi config! Does not affect saved defaults or admin password.)',
+ '(Tímto vymažete nastavení WiFi! Záloha a systémové heslo zůstanou beze změny.)',
// UART settings form
- 'uart.title' => 'Serial Port Parameters',
+ 'uart.title' => 'Sériový port',
'uart.explain' => '
- This form controls the communication UART. The debug UART is fixed
- at 115.200 baud, one stop-bit and no parity.
+ Tímto formulářem můžete upravit nastavení komunikačního UARTu.
+ Ladicí výpisy jsou na pinu P2 s~pevnými parametry: 115200 baud, 1 stop bit, žádná parita.
',
- 'uart.baud' => 'Baud rate',
- 'uart.parity' => 'Parity',
- 'uart.parity.none' => 'None',
- 'uart.parity.odd' => 'Odd',
- 'uart.parity.even' => 'Even',
- 'uart.stop_bits' => 'Stop-bits',
- 'uart.stop_bits.one' => 'One',
- 'uart.stop_bits.one_and_half' => 'One and half',
- 'uart.stop_bits.two' => 'Two',
+ 'uart.baud' => 'Rychlost',
+ 'uart.parity' => 'Parita',
+ 'uart.parity.none' => 'Źádná',
+ 'uart.parity.odd' => 'Lichá',
+ 'uart.parity.even' => 'Sudá',
+ 'uart.stop_bits' => 'Stop-bity',
+ 'uart.stop_bits.one' => '1',
+ 'uart.stop_bits.one_and_half' => '1.5',
+ 'uart.stop_bits.two' => '2',
// HW tuning form
- 'hwtuning.title' => 'Hardware Tuning',
+ 'hwtuning.title' => 'Tuning hardwaru',
'hwtuning.explain' => '
- ESP8266 can be overclocked from 80 MHz to 160 MHz. This will make
- it more responsive and allow faster screen updates at the expense of slightly
- higher power consumption. This can also make it more susceptible to interference.
- Use with care.
+ ESP8266 lze přetaktovat z~80~MHz na 160~MHz. Vyšší rychlost umožní rychlejší překreslování
+ obrazovky a stránky se budou načítat rychleji. Nevýhodou je vyšší spotřeba a citlivost k~rušení.
',
- 'hwtuning.overclock' => 'Overclock to 160MHz',
+ 'hwtuning.overclock' => 'Přetaktovat na 160~MHz',
// Generic button / dialog labels
- 'apply' => 'Apply!',
- 'enabled' => 'Enabled',
- 'disabled' => 'Disabled',
- 'yes' => 'Yes',
- 'no' => 'No',
+ 'apply' => 'Uložit!',
+ 'enabled' => 'Zapnuto',
+ 'disabled' => 'Vypnuto',
+ 'yes' => 'Ano',
+ 'no' => 'Ne',
'confirm' => 'OK',
- 'form_errors' => 'Validation errors for:',
+ 'form_errors' => 'Neplatné hodnoty:',
];
From 8c120007912196be29ffc4c90ccccd6d6d3f75fc Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sun, 1 Oct 2017 00:01:43 +0200
Subject: [PATCH 52/86] Make strings shorter in lang/de and fix some strings
---
lang/de.php | 56 ++++++++++++++++++++++++++---------------------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/lang/de.php b/lang/de.php
index 9f840e7..46dff77 100644
--- a/lang/de.php
+++ b/lang/de.php
@@ -5,7 +5,7 @@ return [
'menu.cfg_network' => 'Netzwerkeinstellungen',
'menu.cfg_term' => 'Terminaleinstellungen',
'menu.about' => 'Über ESPTerm',
- 'menu.help' => 'Referenz',
+ 'menu.help' => 'Schnellreferenz',
'menu.term' => 'Zurück zum Terminal',
'menu.cfg_system' => 'Systemeinstellungen',
'menu.cfg_wifi_conn' => 'Verbinden mit dem Netzwerk',
@@ -36,23 +36,23 @@ return [
'term.defaults' => 'Anfangseinstellungen',
'term.expert' => 'Expertenoptionen',
'term.explain_initials' => '
- Dies sind die Anfangseinstellungen, die benutzt werden, nachdem ESPTerm startet,
- oder wenn der Bildschirm mit dem \ec
-Kommando zurückgesetzt wird.
+ Dies sind die Anfangseinstellungen, die benutzt werden, nachdem ESPTerm startet,
+ oder wenn der Bildschirm mit dem \ec
-Kommando zurückgesetzt wird.
Sie können durch Escape-Sequenzen verändert werden.
',
'term.explain_expert' => '
- Dies sind erweiterte Konfigurationsoptionen, die meistens nicht verändert
+ Dies sind erweiterte Konfigurationsoptionen, die meistens nicht verändert
werden müssen. Bearbeite sie nur, wenn du weißt, was du tust.',
'term.example' => 'Standardfarbenvorschau',
'term.explain_scheme' => '
- Um die Standardtextfarbe und Standardhintergrundfarbe auszuwählen, klicke auf
- die Vorschaupalette, oder benutze die Zahlen 0-15 für die Themafarben, 16-255
+ Um die Standardtextfarbe und Standardhintergrundfarbe auszuwählen, klicke auf
+ die Vorschaupalette, oder benutze die Zahlen 0-15 für die Themafarben, 16-255
für Standardfarben, oder Hexadezimal (#FFFFFF) für True Color (24-bit).
',
- 'term.fgbg_presets' => 'Standardvoreinstellungen',
+ 'term.fgbg_presets' => 'Voreinstellungen',
'term.color_scheme' => 'Farbschema',
'term.reset_screen' => 'Bildschirm & Parser zurücksetzen',
'term.term_title' => 'Titeltext',
@@ -66,7 +66,7 @@ return [
'term.display_cooldown_ms' => 'Zeichenabkühlzeit',
'term.allow_decopt_12' => '\e?12h/l erlauben',
'term.fn_alt_mode' => 'SS3 Fn-Tasten',
- 'term.show_config_links' => 'Navigationslinks anzeigen',
+ 'term.show_config_links' => 'Links anzeigen',
'term.show_buttons' => 'Tasten anzeigen',
'term.loopback' => 'Lokales Echo (SRM)',
'term.crlf_mode' => 'Enter = CR+LF (LNM)',
@@ -99,7 +99,7 @@ return [
'net.ap_addr_ip' => 'Eigene IP-Addresse',
'net.ap_addr_mask' => 'Subnet-Maske',
- 'net.sta_dhcp_enable' => 'Dynamische IP verwenden',
+ 'net.sta_dhcp_enable' => 'Dynamische IP',
'net.sta_addr_ip' => 'ESPTerm statische IP',
'net.sta_addr_mask' => 'Subnet-Mask',
'net.sta_addr_gw' => 'Gateway-IP',
@@ -144,14 +144,14 @@ return [
'wificonn.back_to_config' => 'Zurück zur WLAN-Konfiguration',
'wificonn.telemetry_lost' => 'Telemetrie verloren; etwas lief schief, oder dein Gerät wurde getrennt.',
'wificonn.explain_android_sucks' => '
- Wenn du gerade ESPTerm mit einem Handy oder über ein anderes externes Netzwerk
- konfigurierst, kann dein Gerät die Verbindung verlieren und diese Fortschrittsanzeige
- wird nicht funktionieren. Bitte warte eine Weile (etwa 15 Sekunden) und prüfe dann,
+ Wenn du gerade ESPTerm mit einem Handy oder über ein anderes externes Netzwerk
+ konfigurierst, kann dein Gerät die Verbindung verlieren und diese Fortschrittsanzeige
+ wird nicht funktionieren. Bitte warte eine Weile (etwa 15 Sekunden) und prüfe dann,
ob die Verbindung gelangen ist.',
'wificonn.explain_reset' => '
- Um den eingebauten AP zur Aktivierung zu zwingen, halte den BOOT-Knopf gedrückt bis die
- blaue LED beginnt, zu blinken. Halte ihn länger gedrückt (bis die LED schnell blinkt)
+ Um den eingebauten AP zur Aktivierung zu zwingen, halte den BOOT-Knopf gedrückt bis die
+ blaue LED beginnt, zu blinken. Halte ihn länger gedrückt (bis die LED schnell blinkt)
um eine "Werksrückstellung" zu vollziehen.',
'wificonn.disabled' => "Stationsmodus ist deaktiviert.",
@@ -175,30 +175,30 @@ return [
'pwlock.region.all' => 'Alles, sogar das Terminal',
'pwlock.new_access_pw' => 'Neues Passwort',
'pwlock.new_access_pw2' => 'Wiederholen',
- 'pwlock.admin_pw' => 'Administratorpasswort',
+ 'pwlock.admin_pw' => 'Admin. Passwort',
'pwlock.access_name' => 'Benutzername',
// Setting admin password
'adminpw.title' => 'Administratorpasswort ändern',
'adminpw.explain' =>'
- Das "Administratorpasswort" wird benutzt, um die gespeicherten Standardeinstellungen
- und die Zugriffsbeschränkungen zu verändern. Dieses Passwort wird nicht als Teil
- der Hauptkonfiguration gespeichert, d.h. Speichern / Wiederherstellen wird das
- Passwort nicht beeinflussen. Wenn das Administratorpasswort vergessen wird, ist
+ Das "Administratorpasswort" wird benutzt, um die gespeicherten Standardeinstellungen
+ und die Zugriffsbeschränkungen zu verändern. Dieses Passwort wird nicht als Teil
+ der Hauptkonfiguration gespeichert, d.h. Speichern / Wiederherstellen wird das
+ Passwort nicht beeinflussen. Wenn das Administratorpasswort vergessen wird, ist
die einfachste Weise, wieder Zugriff zu erhalten, ein Re-flash des Chips.
Das voreingestellte Administratorpasswort ist "%def_admin_pw%".
',
- 'adminpw.new_admin_pw' => 'Neues Administratorpasswort',
+ 'adminpw.new_admin_pw' => 'Neues Passwort',
'adminpw.new_admin_pw2' => 'Wiederholen',
- 'adminpw.old_admin_pw' => 'Altes Administratorpasswort',
+ 'adminpw.old_admin_pw' => 'Altes Passwort',
// Persist form
'persist.title' => 'Speichern & Wiederherstellen',
'persist.explain' => '
- ESPTerm speichert alle Einstellungen im Flash-Speicher. Die aktiven Einstellungen
- können in den “Voreinstellungsbereich” kopiert werden und später wiederhergestellt
+ ESPTerm speichert alle Einstellungen im Flash-Speicher. Die aktiven Einstellungen
+ können in den “Voreinstellungsbereich” kopiert werden und später wiederhergestellt
werden mit der Taste unten.',
'persist.confirm_restore' => 'Alle Einstellungen zu den Voreinstellungen zurücksetzen?',
'persist.confirm_restore_hard' => '
@@ -211,14 +211,14 @@ return [
'persist.write_defaults' => 'Aktive Einstellungen als Voreinstellungen speichern',
'persist.restore_hard' => 'Aktive Einstellungen zu Werkseinstellungen zurücksetzen',
'persist.restore_hard_explain' => '
- (Dies löscht die WLAN-Konfiguration! Beeinflusst die gespeicherten Voreinstellungen
+ (Dies löscht die WLAN-Konfiguration! Beeinflusst die gespeicherten Voreinstellungen
oder das Administratorpasswort nicht.)',
// UART settings form
'uart.title' => 'Serienportparameter',
'uart.explain' => '
- Dies steuert den Kommunikations-UART. Der Debug-UART ist auf 115.200 baud fest
+ Dies steuert den Kommunikations-UART. Der Debug-UART ist auf 115.200 baud fest
eingestellt mit einem Stop-Bit und keiner Parität.
',
'uart.baud' => 'Baudrate',
@@ -235,11 +235,11 @@ return [
'hwtuning.title' => 'Hardware-Tuning',
'hwtuning.explain' => '
- ESP8266 kann overclocked werden von 80 MHz auf 160 MHz.
- Alles wird etwas schneller sein, aber mit höherem Stromverbrauch,
+ ESP8266 kann übertaktet werden von 80 MHz auf 160 MHz.
+ Alles wird etwas schneller sein, aber mit höherem Stromverbrauch,
und eventuell auch mit höherer Interferenz. Mit Sorgfalt benutzen.
',
- 'hwtuning.overclock' => 'Auf 160MHz Overclocken',
+ 'hwtuning.overclock' => 'Übertakten',
// Generic button / dialog labels
From 822e2694b2775e9115d5cb5b34698b70320088b1 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sun, 1 Oct 2017 00:14:12 +0200
Subject: [PATCH 53/86] Administratorpasswort -> Systempasswort
---
lang/de.php | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/lang/de.php b/lang/de.php
index 46dff77..28ccc71 100644
--- a/lang/de.php
+++ b/lang/de.php
@@ -175,23 +175,23 @@ return [
'pwlock.region.all' => 'Alles, sogar das Terminal',
'pwlock.new_access_pw' => 'Neues Passwort',
'pwlock.new_access_pw2' => 'Wiederholen',
- 'pwlock.admin_pw' => 'Admin. Passwort',
+ 'pwlock.admin_pw' => 'Systempasswort',
'pwlock.access_name' => 'Benutzername',
// Setting admin password
- 'adminpw.title' => 'Administratorpasswort ändern',
+ 'adminpw.title' => 'Systempasswort ändern',
'adminpw.explain' =>'
- Das "Administratorpasswort" wird benutzt, um die gespeicherten Standardeinstellungen
+ Das "Systempasswort" wird benutzt, um die gespeicherten Standardeinstellungen
und die Zugriffsbeschränkungen zu verändern. Dieses Passwort wird nicht als Teil
der Hauptkonfiguration gespeichert, d.h. Speichern / Wiederherstellen wird das
- Passwort nicht beeinflussen. Wenn das Administratorpasswort vergessen wird, ist
+ Passwort nicht beeinflussen. Wenn das Systempasswort vergessen wird, ist
die einfachste Weise, wieder Zugriff zu erhalten, ein Re-flash des Chips.
- Das voreingestellte Administratorpasswort ist "%def_admin_pw%".
+ Das voreingestellte Systempasswort ist "%def_admin_pw%".
',
- 'adminpw.new_admin_pw' => 'Neues Passwort',
+ 'adminpw.new_admin_pw' => 'Neues Systempasswort',
'adminpw.new_admin_pw2' => 'Wiederholen',
- 'adminpw.old_admin_pw' => 'Altes Passwort',
+ 'adminpw.old_admin_pw' => 'Altes Systempasswort',
// Persist form
@@ -205,14 +205,14 @@ return [
Zurücksetzen zu den Firmware-Voreinstellungen? Dies wird alle aktiven
Einstellungen zürucksetzen und den AP-Modus aktivieren mit der Standard-SSID.',
'persist.confirm_store_defaults' =>
- 'Administratorpasswort eingeben um Voreinstellungen zu überschreiben',
- 'persist.password' => 'Administratorpasswort:',
+ 'Systempasswort eingeben um Voreinstellungen zu überschreiben',
+ 'persist.password' => 'Systempasswort:',
'persist.restore_defaults' => 'Zu gespeicherten Voreinstellungen zurücksetzen',
'persist.write_defaults' => 'Aktive Einstellungen als Voreinstellungen speichern',
'persist.restore_hard' => 'Aktive Einstellungen zu Werkseinstellungen zurücksetzen',
'persist.restore_hard_explain' => '
(Dies löscht die WLAN-Konfiguration! Beeinflusst die gespeicherten Voreinstellungen
- oder das Administratorpasswort nicht.)',
+ oder das Systempasswort nicht.)',
// UART settings form
From e2e89c6053e1ccfe9cb4ef3763254bf24c8d7082 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sun, 1 Oct 2017 00:40:39 +0200
Subject: [PATCH 54/86] Show update frames in debug mode
---
js/term/debug_screen.js | 28 +++++++++++++++++++++++++++-
js/term/screen_parser.js | 4 ++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/js/term/debug_screen.js b/js/term/debug_screen.js
index b4c58a1..a80ed8a 100644
--- a/js/term/debug_screen.js
+++ b/js/term/debug_screen.js
@@ -46,6 +46,7 @@ module.exports = function attachDebugScreen (screen) {
let startTime, endTime, lastReason
let cells = new Map()
let clippedRects = []
+ let updateFrames = []
let startDrawing
@@ -65,6 +66,11 @@ module.exports = function attachDebugScreen (screen) {
},
clipRect (...args) {
clippedRects.push(args)
+ },
+ pushFrame (frame) {
+ frame.push(Date.now())
+ updateFrames.push(frame)
+ startDrawing()
}
}
@@ -155,6 +161,26 @@ module.exports = function attachDebugScreen (screen) {
ctx.fill()
}
+ let didDrawUpdateFrames = false
+ if (updateFrames.length) {
+ let framesToDelete = []
+ for (let frame of updateFrames) {
+ let time = frame[4]
+ let elapsed = Date.now() - time
+ if (elapsed > 1000) framesToDelete.push(frame)
+ else {
+ didDrawUpdateFrames = true
+ ctx.globalAlpha = 1 - elapsed / 1000
+ ctx.strokeStyle = '#ff0'
+ ctx.lineWidth = 2
+ ctx.strokeRect(frame[0] * cellWidth, frame[1] * cellHeight, frame[2] * cellWidth, frame[3] * cellHeight)
+ }
+ }
+ for (let frame of framesToDelete) {
+ updateFrames.splice(updateFrames.indexOf(frame), 1)
+ }
+ }
+
if (mouseHoverCell) {
ctx.save()
ctx.globalAlpha = 1
@@ -170,7 +196,7 @@ module.exports = function attachDebugScreen (screen) {
ctx.restore()
}
- if (activeCells === 0 && !mouseHoverCell) {
+ if (activeCells === 0 && !mouseHoverCell && !didDrawUpdateFrames) {
isDrawing = false
removeCanvas()
}
diff --git a/js/term/screen_parser.js b/js/term/screen_parser.js
index 2d0ebff..1e9f197 100644
--- a/js/term/screen_parser.js
+++ b/js/term/screen_parser.js
@@ -243,6 +243,10 @@ module.exports = class ScreenParser {
const frameHeight = du(strArray[ci++])
const frameWidth = du(strArray[ci++])
+ if (this.screen._debug && this.screen.window.debug) {
+ this.screen._debug.pushFrame([frameX, frameY, frameWidth, frameHeight])
+ }
+
// content
let fg = 7
let bg = 0
From cf1ef08db4c0df5ceeba04801cc46c8785152158 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sun, 1 Oct 2017 00:47:50 +0200
Subject: [PATCH 55/86] some triangle cleaning, not fixed
---
js/lib/colortriangle.js | 72 +++++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 31 deletions(-)
diff --git a/js/lib/colortriangle.js b/js/lib/colortriangle.js
index 2c4e60d..d3ec922 100644
--- a/js/lib/colortriangle.js
+++ b/js/lib/colortriangle.js
@@ -54,21 +54,6 @@ function each (obj, fn) {
}
}
-function getOffsets (el) {
- let left = 0
- let top = 0
-
- while (el !== null) {
- console.log(el)
- console.log(el.offsetLeft, el.offsetTop)
- left += el.offsetLeft
- top += el.offsetTop
- el = el.offsetParent
- }
-
- return [left, top]
-}
-
module.exports = class ColorTriangle {
/****************
* ColorTriangle *
@@ -305,12 +290,35 @@ module.exports = class ColorTriangle {
// The Element and the DOM
inject (parent) {
parent.appendChild(this.container)
+ }
+
+ _getRelativeCoordinates (evt) {
+ let pos = {}
+ let offset = {}
+ let ref
+
+ // FIXME this doesn't really work with scroll
+ // this.triangle is the canvas element
+
+ ref = this.triangle.offsetParent
- // calculate canvas position on page
- const offsets = getOffsets(this.triangle)
- this.offset = {
- x: offsets[0],
- y: offsets[1]
+ pos.x = evt.touches ? evt.touches[0].pageX : evt.pageX
+ pos.y = evt.touches ? evt.touches[0].pageY : evt.pageY
+
+ offset.left = this.triangle.offsetLeft
+ offset.top = this.triangle.offsetTop
+
+ while (ref) {
+
+ offset.left += ref.offsetLeft
+ offset.top += ref.offsetTop
+
+ ref = ref.offsetParent
+ }
+
+ return {
+ x: pos.x - offset.left,
+ y: pos.y - offset.top
}
}
@@ -379,11 +387,14 @@ module.exports = class ColorTriangle {
doc.body.addEventListener('mousemove', mousemove, false)
doc.body.addEventListener('mouseup', mouseup, false)
- this._map(evt.pageX, evt.pageY)
+
+ let xy = this._getRelativeCoordinates(evt)
+ this._map(xy.x, xy.y)
}
let mousemove = (evt) => {
- this._move(evt.pageX, evt.pageY)
+ let xy = this._getRelativeCoordinates(evt)
+ this._move(xy.x, xy.y)
}
let mouseup = (evt) => {
@@ -400,23 +411,22 @@ module.exports = class ColorTriangle {
}
_map (x, y) {
- const ox = x
- const oy = y
-
- x -= this.offset.x + this.wheelRadius
- y -= this.offset.y + this.wheelRadius
+ let x0 = x
+ let y0 = y
+ x -= this.wheelRadius
+ y -= this.wheelRadius
const r = M.sqrt(x * x + y * y) // Pythagoras
if (r > this.triangleRadius && r < this.wheelRadius) {
// Wheel
this.down = 'wheel'
this._fireEvent('dragstart')
- this._move(ox, oy)
+ this._move(x0, y0)
} else if (r < this.triangleRadius) {
// Inner circle
this.down = 'triangle'
this._fireEvent('dragstart')
- this._move(ox, oy)
+ this._move(x0, y0)
}
}
@@ -425,8 +435,8 @@ module.exports = class ColorTriangle {
return
}
- x -= this.offset.x + this.wheelRadius
- y -= this.offset.y + this.wheelRadius
+ x -= this.wheelRadius
+ y -= this.wheelRadius
let rad = M.atan2(-y, x)
if (rad < 0) {
From 454b92e8787cbbcb51ab0abd4344f06c2fb06263 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sun, 1 Oct 2017 01:05:58 +0200
Subject: [PATCH 56/86] woo fixed triangle
---
js/lib/colortriangle.js | 28 ++++------------------------
1 file changed, 4 insertions(+), 24 deletions(-)
diff --git a/js/lib/colortriangle.js b/js/lib/colortriangle.js
index d3ec922..8523be7 100644
--- a/js/lib/colortriangle.js
+++ b/js/lib/colortriangle.js
@@ -293,32 +293,12 @@ module.exports = class ColorTriangle {
}
_getRelativeCoordinates (evt) {
- let pos = {}
- let offset = {}
- let ref
-
- // FIXME this doesn't really work with scroll
- // this.triangle is the canvas element
-
- ref = this.triangle.offsetParent
-
- pos.x = evt.touches ? evt.touches[0].pageX : evt.pageX
- pos.y = evt.touches ? evt.touches[0].pageY : evt.pageY
-
- offset.left = this.triangle.offsetLeft
- offset.top = this.triangle.offsetTop
-
- while (ref) {
-
- offset.left += ref.offsetLeft
- offset.top += ref.offsetTop
-
- ref = ref.offsetParent
- }
+ let elem = this.triangle
+ let rect = elem.getBoundingClientRect()
return {
- x: pos.x - offset.left,
- y: pos.y - offset.top
+ x: evt.clientX - rect.x,
+ y: evt.clientY - rect.y
}
}
From 979d457b7b27473fcd86273746b4599c54ec371e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sun, 1 Oct 2017 01:16:16 +0200
Subject: [PATCH 57/86] fixed broken wheel number box flipping caused by some
dubious optimization
---
js/appcommon.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/js/appcommon.js b/js/appcommon.js
index 0f103df..963bc5a 100644
--- a/js/appcommon.js
+++ b/js/appcommon.js
@@ -61,7 +61,7 @@ $.ready(function () {
}, 1000)
// flipping number boxes with the mouse wheel
- $('input[type=number]').on('mousewheel', function (e) {
+ $('input[type=number]').on('wheel', function (e) {
let $this = $(this)
let val = +$this.val()
if (isNaN(val)) val = 1
@@ -69,14 +69,14 @@ $.ready(function () {
const step = +($this.attr('step') || 1)
const min = +$this.attr('min')
const max = +$this.attr('max')
- if (e.wheelDelta > 0) {
+ if (e.deltaY > 0) {
val += step
} else {
val -= step
}
- if (!Number.isFinite(min)) val = Math.max(val, +min)
- if (!Number.isFinite(max)) val = Math.min(val, +max)
+ if (Number.isFinite(min)) val = Math.max(val, +min)
+ if (Number.isFinite(max)) val = Math.min(val, +max)
$this.val(val)
if ('createEvent' in document) {
From 55e2def6e3899a708a9afca099252bdf44919b7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sun, 1 Oct 2017 02:07:09 +0200
Subject: [PATCH 58/86] add toggle for ascii debug
---
lang/cs.php | 2 ++
lang/en.php | 2 ++
pages/cfg_term.php | 13 +++++++++++++
3 files changed, 17 insertions(+)
diff --git a/lang/cs.php b/lang/cs.php
index 97dc7de..0bfa267 100644
--- a/lang/cs.php
+++ b/lang/cs.php
@@ -78,6 +78,8 @@ return [
'term.color_fg_prev' => 'Barva textu',
'term.color_bg_prev' => 'Barva pozadí',
'term.colors_preview' => '',
+ 'term.debugbar' => 'Zobraz ladicí panel',
+ 'term.ascii_debug' => 'ASCII debug režim',
'cursor.block_blink' => 'Blok, blikající',
'cursor.block_steady' => 'Blok, stálý',
diff --git a/lang/en.php b/lang/en.php
index 17adff0..e98738c 100644
--- a/lang/en.php
+++ b/lang/en.php
@@ -77,6 +77,8 @@ return [
'term.color_fg_prev' => 'Foreground',
'term.color_bg_prev' => 'Background',
'term.colors_preview' => '',
+ 'term.debugbar' => 'Show debug panel',
+ 'term.ascii_debug' => 'ASCII debug mode',
'cursor.block_blink' => 'Block, blinking',
'cursor.block_steady' => 'Block, steady',
diff --git a/pages/cfg_term.php b/pages/cfg_term.php
index 9db48f2..2f90bae 100644
--- a/pages/cfg_term.php
+++ b/pages/cfg_term.php
@@ -270,6 +270,19 @@
ms
+
+
+
+
+
+
+
+
+
+
+
From 0a281414a84ef60e472858284681178d112b76a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sun, 1 Oct 2017 03:22:44 +0200
Subject: [PATCH 59/86] support binary socket messages
---
js/term/connection.js | 77 ++++++++++++++++++++++++++-----------------
1 file changed, 47 insertions(+), 30 deletions(-)
diff --git a/js/term/connection.js b/js/term/connection.js
index 8e8f7be..1acad23 100644
--- a/js/term/connection.js
+++ b/js/term/connection.js
@@ -17,6 +17,14 @@ module.exports = class TermConnection extends EventEmitter {
this.reconnTimeout = null
this.forceClosing = false
+ this.blobReader = new FileReader()
+ this.blobReader.onload = (evt) => {
+ this.onDecodedWSMessage(this.blobReader.result)
+ }
+ this.blobReader.onerror = (evt) => {
+ console.error(evt)
+ }
+
this.pageShown = false
this.disconnectTimeout = null
@@ -64,38 +72,47 @@ module.exports = class TermConnection extends EventEmitter {
this.emit('disconnect', evt.code)
}
- onWSMessage (evt) {
- try {
- switch (evt.data.charAt(0)) {
- case '.':
- // heartbeat, no-op message
- break
-
- case '-':
- // console.log('xoff');
- this.xoff = true
- this.autoXoffTimeout = setTimeout(() => {
- this.xoff = false
- }, 250)
- break
-
- case '+':
- // console.log('xon');
+ onDecodedWSMessage (str) {
+ switch (str.charAt(0)) {
+ case '.':
+ // heartbeat, no-op message
+ break
+
+ case '-':
+ // console.log('xoff');
+ this.xoff = true
+ this.autoXoffTimeout = setTimeout(() => {
this.xoff = false
- clearTimeout(this.autoXoffTimeout)
- break
-
- default:
- this.screen.load(evt.data)
- if (!this.pageShown) {
- window.showPage()
- this.pageShown = true
- }
- break
+ }, 250)
+ break
+
+ case '+':
+ // console.log('xon');
+ this.xoff = false
+ clearTimeout(this.autoXoffTimeout)
+ break
+
+ default:
+ this.screen.load(str)
+ if (!this.pageShown) {
+ window.showPage()
+ this.pageShown = true
+ }
+ break
+ }
+ this.heartbeat()
+ }
+
+ onWSMessage (evt) {
+ if (typeof evt.data === 'string') this.onDecodedWSMessage(evt.data)
+ else {
+ if (this.blobReader.readyState !== 1) {
+ this.blobReader.readAsText(evt.data)
+ } else {
+ setTimeout(() => {
+ this.onWSMessage(evt)
+ }, 1)
}
- this.heartbeat()
- } catch (e) {
- console.error(e)
}
}
From d41d4ce2d25acdb34ca2ff9e992e10bd8ac0e19b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sun, 1 Oct 2017 03:25:20 +0200
Subject: [PATCH 60/86] lang..
---
lang/cs.php | 4 ++--
lang/en.php | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lang/cs.php b/lang/cs.php
index 0bfa267..f743dbf 100644
--- a/lang/cs.php
+++ b/lang/cs.php
@@ -78,8 +78,8 @@ return [
'term.color_fg_prev' => 'Barva textu',
'term.color_bg_prev' => 'Barva pozadí',
'term.colors_preview' => '',
- 'term.debugbar' => 'Zobraz ladicí panel',
- 'term.ascii_debug' => 'ASCII debug režim',
+ 'term.debugbar' => 'Zobraz debug panel',
+ 'term.ascii_debug' => 'Použít debug parser',
'cursor.block_blink' => 'Blok, blikající',
'cursor.block_steady' => 'Blok, stálý',
diff --git a/lang/en.php b/lang/en.php
index e98738c..1f1d61c 100644
--- a/lang/en.php
+++ b/lang/en.php
@@ -78,7 +78,7 @@ return [
'term.color_bg_prev' => 'Background',
'term.colors_preview' => '',
'term.debugbar' => 'Show debug panel',
- 'term.ascii_debug' => 'ASCII debug mode',
+ 'term.ascii_debug' => 'Debug parser',
'cursor.block_blink' => 'Block, blinking',
'cursor.block_steady' => 'Block, steady',
From 1d4c41ff5a5c117afecd99ee11cf6d06f5ff0273 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sun, 1 Oct 2017 09:31:14 +0200
Subject: [PATCH 61/86] =?UTF-8?q?Add=202x=20to=20color=20triangle,=20and?=
=?UTF-8?q?=20use=20camelCase=20&=20=CF=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
js/lib/color_utils.js | 48 ++++-----
js/lib/colortriangle.js | 210 ++++++++++++++++++----------------------
js/term/themes.js | 6 +-
3 files changed, 116 insertions(+), 148 deletions(-)
diff --git a/js/lib/color_utils.js b/js/lib/color_utils.js
index 1ed5a65..c3f490a 100644
--- a/js/lib/color_utils.js
+++ b/js/lib/color_utils.js
@@ -29,9 +29,9 @@
*******************/
const M = Math
-const PI = M.PI
+const TAU = 2 * M.PI
-exports.hue_to_rgb = function (v1, v2, h) {
+exports.hue2rgb = function (v1, v2, h) {
if (h < 0) h += 1
if (h > 1) h -= 1
@@ -41,8 +41,8 @@ exports.hue_to_rgb = function (v1, v2, h) {
return v1
}
-exports.hsl_to_rgb = function (h, s, l) {
- h /= 2 * PI
+exports.hsl2rgb = function (h, s, l) {
+ h /= TAU
let r, g, b
if (s === 0) {
@@ -55,14 +55,14 @@ exports.hsl_to_rgb = function (h, s, l) {
var_1 = 2 * l - var_2
- r = exports.hue_to_rgb(var_1, var_2, h + (1 / 3))
- g = exports.hue_to_rgb(var_1, var_2, h)
- b = exports.hue_to_rgb(var_1, var_2, h - (1 / 3))
+ r = exports.hue2rgb(var_1, var_2, h + (1 / 3))
+ g = exports.hue2rgb(var_1, var_2, h)
+ b = exports.hue2rgb(var_1, var_2, h - (1 / 3))
}
return [r, g, b]
}
-exports.rgb_to_hsl = function (r, g, b) {
+exports.rgb2hsl = function (r, g, b) {
const min = M.min(r, g, b)
const max = M.max(r, g, b)
const d = max - min // delta
@@ -90,39 +90,29 @@ exports.rgb_to_hsl = function (r, g, b) {
if (h < 0) h += 1
else if (h > 1) h -= 1
}
- h *= 2 * PI
+ h *= TAU
return [h, s, l]
}
-exports.hex_to_rgb = function (hex) {
- const groups = hex.match(/^#([A-Fa-f0-9]+)$/)
- if (groups && groups[1].length % 3 === 0) {
+exports.hex2rgb = function (hex) {
+ const groups = hex.match(/^#([\da-f]{3,6})$/i)
+ if (groups) {
hex = groups[1]
const bytes = hex.length / 3
- const max = Math.pow(16, bytes) - 1
- const r = parseInt(hex.slice(0 * bytes, 1 * bytes), 16) / max
- const g = parseInt(hex.slice(1 * bytes, 2 * bytes), 16) / max
- const b = parseInt(hex.slice(2 * bytes, 3 * bytes), 16) / max
- return [r, g, b]
+ const max = (16 ** bytes) - 1
+ return [0, 1, 2].map(x => parseInt(hex.slice(x * bytes, (x + 1) * bytes), 16) / max)
}
return [0, 0, 0]
}
function pad (n) {
- if (n.length === 1) n = '0' + n
- return n
+ return `00${n}`.substr(-2)
}
-exports.rgb255_to_hex = function (r, g, b) {
- r = r.toString(16)
- g = g.toString(16)
- b = b.toString(16)
- return `#${pad(r)}${pad(g)}${pad(b)}`
+exports.rgb255ToHex = function (r, g, b) {
+ return '#' + [r, g, b].map(x => pad(x.toString(16))).join('')
}
-exports.rgb_to_hex = function (r, g, b) {
- r = Math.round(r * 255).toString(16)
- g = Math.round(g * 255).toString(16)
- b = Math.round(b * 255).toString(16)
- return `#${pad(r)}${pad(g)}${pad(b)}`
+exports.rgb2hex = function (r, g, b) {
+ return '#' + [r, g, b].map(x => pad(Math.round(x * 255).toString(16))).join('')
}
diff --git a/js/lib/colortriangle.js b/js/lib/colortriangle.js
index 8523be7..699f351 100644
--- a/js/lib/colortriangle.js
+++ b/js/lib/colortriangle.js
@@ -21,18 +21,20 @@
*/
// NOTE: Converted to ES6 by MightyPork (2017)
+// Modified for ESPTerm
+const EventEmitter = require('events')
const {
- rgb_to_hex,
- hex_to_rgb,
- hsl_to_rgb,
- rgb_to_hsl
+ rgb2hex,
+ hex2rgb,
+ hsl2rgb,
+ rgb2hsl
} = require('./color_utils')
const win = window
const doc = document
const M = Math
-const PI = M.PI
+const TAU = 2 * M.PI
function times (i, fn) {
for (let j = 0; j < i; j++) {
@@ -54,13 +56,15 @@ function each (obj, fn) {
}
}
-module.exports = class ColorTriangle {
+module.exports = class ColorTriangle extends EventEmitter {
/****************
* ColorTriangle *
****************/
// Constructor function:
constructor (color, options) {
+ super()
+
this.options = {
size: 150,
padding: 8,
@@ -74,15 +78,17 @@ module.exports = class ColorTriangle {
background: 'transparent'
}
- this._setOptions(options)
- this._calculateProperties()
+ this.pixelRatio = window.devicePixelRatio
+
+ this.setOptions(options)
+ this.calculateProperties()
- this._createContainer()
- this._createTriangle()
- this._createWheel()
- this._createWheelPointer()
- this._createTrianglePointer()
- this._attachEvents()
+ this.createContainer()
+ this.createTriangle()
+ this.createWheel()
+ this.createWheelPointer()
+ this.createTrianglePointer()
+ this.attachEvents()
color = color || '#f00'
if (typeof color == 'string') {
@@ -90,7 +96,7 @@ module.exports = class ColorTriangle {
}
}
- _calculateProperties () {
+ calculateProperties () {
let opts = this.options
this.padding = opts.padding
@@ -104,10 +110,10 @@ module.exports = class ColorTriangle {
this.triangleSideLength = M.sqrt(3) * this.triangleRadius
}
- _calculatePositions () {
+ calculatePositions () {
const r = this.triangleRadius
const hue = this.hue
- const third = (2 / 3) * PI
+ const third = TAU / 3
const s = this.saturation
const l = this.lightness
@@ -128,7 +134,7 @@ module.exports = class ColorTriangle {
this.y = sy + (vy - sy) * l + (hy - my) * a
}
- _createContainer () {
+ createContainer () {
let c = this.container = doc.createElement('div')
c.className = 'color-triangle'
@@ -141,38 +147,41 @@ module.exports = class ColorTriangle {
c.style.background = this.options.background
}
- _createWheel () {
+ createWheel () {
let c = this.wheel = doc.createElement('canvas')
- c.width = c.height = this.innerSize
+ c.width = c.height = this.innerSize * this.pixelRatio
+ c.style.width = c.style.height = `${this.innerSize}px`
c.style.position = 'absolute'
c.style.margin = c.style.padding = '0'
c.style.left = c.style.top = `${this.padding}px`
- this._drawWheel(c.getContext('2d'))
+ this.drawWheel(c.getContext('2d'))
this.container.appendChild(c)
}
- _drawWheel (ctx) {
+ drawWheel (ctx) {
let s, i
ctx.save()
+ ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0)
ctx.translate(this.wheelRadius, this.wheelRadius)
s = this.wheelRadius - this.triangleRadius
// Draw a circle for every color
for (i = 0; i < 360; i++) {
- ctx.rotate(PI / -180) // rotate one degree
+ ctx.rotate(TAU / -360) // rotate one degree
ctx.beginPath()
ctx.fillStyle = 'hsl(' + i + ', 100%, 50%)'
- ctx.arc(this.wheelRadius - (s / 2), 0, s / 2, 0, PI * 2, true)
+ ctx.arc(this.wheelRadius - (s / 2), 0, s / 2, 0, TAU, true)
ctx.fill()
}
ctx.restore()
}
- _createTriangle () {
+ createTriangle () {
let c = this.triangle = doc.createElement('canvas')
- c.width = c.height = this.innerSize
+ c.width = c.height = this.innerSize * this.pixelRatio
+ c.style.width = c.style.height = `${this.innerSize}px`
c.style.position = 'absolute'
c.style.margin = c.style.padding = '0'
c.style.left = c.style.top = this.padding + 'px'
@@ -182,7 +191,7 @@ module.exports = class ColorTriangle {
this.container.appendChild(c)
}
- _drawTriangle () {
+ drawTriangle () {
const hx = this.hx
const hy = this.hy
const sx = this.sx
@@ -194,9 +203,10 @@ module.exports = class ColorTriangle {
let ctx = this.triangleCtx
// clear
- ctx.clearRect(0, 0, size, size)
+ ctx.clearRect(0, 0, size * this.pixelRatio, size * this.pixelRatio)
ctx.save()
+ ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0)
ctx.translate(this.wheelRadius, this.wheelRadius)
// make a triangle
@@ -213,7 +223,7 @@ module.exports = class ColorTriangle {
// create gradient from hsl(hue, 1, 1) to transparent
let grad0 = ctx.createLinearGradient(hx, hy, (sx + vx) / 2, (sy + vy) / 2)
- const hsla = 'hsla(' + M.round(this.hue * (180 / PI)) + ', 100%, 50%, '
+ const hsla = 'hsla(' + M.round(this.hue * (360 / TAU)) + ', 100%, 50%, '
grad0.addColorStop(0, hsla + '1)')
grad0.addColorStop(1, hsla + '0)')
ctx.fillStyle = grad0
@@ -233,57 +243,60 @@ module.exports = class ColorTriangle {
}
// The two pointers
- _createWheelPointer () {
+ createWheelPointer () {
let c = this.wheelPointer = doc.createElement('canvas')
const size = this.wheelPointerSize
- c.width = c.height = size
+ c.width = c.height = size * this.pixelRatio
+ c.style.width = c.style.height = `${size}px`
c.style.position = 'absolute'
c.style.margin = c.style.padding = '0'
- this._drawPointer(c.getContext('2d'), size / 2, this.options.wheelPointerColor1, this.options.wheelPointerColor2)
+ this.drawPointer(c.getContext('2d'), size / 2, this.options.wheelPointerColor1, this.options.wheelPointerColor2)
this.container.appendChild(c)
}
- _moveWheelPointer () {
+ moveWheelPointer () {
const r = this.wheelPointerSize / 2
const s = this.wheelPointer.style
s.top = this.padding + this.wheelRadius - M.sin(this.hue) * (this.triangleRadius + this.wheelThickness / 2) - r + 'px'
s.left = this.padding + this.wheelRadius + M.cos(this.hue) * (this.triangleRadius + this.wheelThickness / 2) - r + 'px'
}
- _createTrianglePointer () { // create pointer in the triangle
+ createTrianglePointer () { // create pointer in the triangle
let c = this.trianglePointer = doc.createElement('canvas')
const size = this.options.trianglePointerSize
- c.width = c.height = size
+ c.width = c.height = size * this.pixelRatio
+ c.style.width = c.style.height = `${size}px`
c.style.position = 'absolute'
c.style.margin = c.style.padding = '0'
- this._drawPointer(c.getContext('2d'), size / 2, this.options.trianglePointerColor1, this.options.trianglePointerColor2)
+ this.drawPointer(c.getContext('2d'), size / 2, this.options.trianglePointerColor1, this.options.trianglePointerColor2)
this.container.appendChild(c)
}
- _moveTrianglePointer (x, y) {
+ moveTrianglePointer (x, y) {
const s = this.trianglePointer.style
const r = this.options.trianglePointerSize / 2
s.top = (this.y + this.wheelRadius + this.padding - r) + 'px'
s.left = (this.x + this.wheelRadius + this.padding - r) + 'px'
}
- _drawPointer (ctx, r, color1, color2) {
+ drawPointer (ctx, r, color1, color2) {
+ ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0)
ctx.fillStyle = color2
ctx.beginPath()
- ctx.arc(r, r, r, 0, PI * 2, true)
+ ctx.arc(r, r, r, 0, TAU, true)
ctx.fill() // => black circle
ctx.fillStyle = color1
ctx.beginPath()
- ctx.arc(r, r, r - 2, 0, PI * 2, true)
+ ctx.arc(r, r, r - 2, 0, TAU, true)
ctx.fill() // => white circle with 1px black border
ctx.fillStyle = color2
ctx.beginPath()
- ctx.arc(r, r, r / 4 + 2, 0, PI * 2, true)
+ ctx.arc(r, r, r / 4 + 2, 0, TAU, true)
ctx.fill() // => black circle with big white border and a small black border
ctx.globalCompositeOperation = 'destination-out'
ctx.beginPath()
- ctx.arc(r, r, r / 4, 0, PI * 2, true)
+ ctx.arc(r, r, r / 4, 0, TAU, true)
ctx.fill() // => transparent center
}
@@ -292,7 +305,7 @@ module.exports = class ColorTriangle {
parent.appendChild(this.container)
}
- _getRelativeCoordinates (evt) {
+ getRelativeCoordinates (evt) {
let elem = this.triangle
let rect = elem.getBoundingClientRect()
@@ -315,7 +328,7 @@ module.exports = class ColorTriangle {
// Color accessors
getCSS () {
- const h = Math.round(this.hue * (180 / PI))
+ const h = Math.round(this.hue * (360 / TAU))
const s = Math.round(this.saturation * 100)
const l = Math.round(this.lightness * 100)
@@ -323,19 +336,19 @@ module.exports = class ColorTriangle {
}
getHEX () {
- return rgb_to_hex(...this.getRGB())
+ return rgb2hex(...this.getRGB())
}
setHEX (hex) {
- this.setRGB(...hex_to_rgb(hex))
+ this.setRGB(...hex2rgb(hex))
}
getRGB () {
- return hsl_to_rgb(...this.getHSL())
+ return hsl2rgb(...this.getHSL())
}
setRGB (r, g, b) {
- this.setHSL(...rgb_to_hsl(r, g, b))
+ this.setHSL(...rgb2hsl(r, g, b))
}
getHSL () {
@@ -347,18 +360,18 @@ module.exports = class ColorTriangle {
this.saturation = s
this.lightness = l
- this._initColor()
+ this.initColor()
}
- _initColor () {
- this._calculatePositions()
- this._moveWheelPointer()
- this._drawTriangle()
- this._moveTrianglePointer()
+ initColor () {
+ this.calculatePositions()
+ this.moveWheelPointer()
+ this.drawTriangle()
+ this.moveTrianglePointer()
}
// Mouse event handling
- _attachEvents () {
+ attachEvents () {
this.down = null
let mousedown = (evt) => {
@@ -368,19 +381,19 @@ module.exports = class ColorTriangle {
doc.body.addEventListener('mousemove', mousemove, false)
doc.body.addEventListener('mouseup', mouseup, false)
- let xy = this._getRelativeCoordinates(evt)
- this._map(xy.x, xy.y)
+ let xy = this.getRelativeCoordinates(evt)
+ this.map(xy.x, xy.y)
}
let mousemove = (evt) => {
- let xy = this._getRelativeCoordinates(evt)
- this._move(xy.x, xy.y)
+ let xy = this.getRelativeCoordinates(evt)
+ this.move(xy.x, xy.y)
}
let mouseup = (evt) => {
if (this.down) {
this.down = null
- this._fireEvent('dragend')
+ this.emit('dragend')
}
doc.body.removeEventListener('mousemove', mousemove, false)
doc.body.removeEventListener('mouseup', mouseup, false)
@@ -390,7 +403,7 @@ module.exports = class ColorTriangle {
this.container.addEventListener('mousemove', mousemove, false)
}
- _map (x, y) {
+ map (x, y) {
let x0 = x
let y0 = y
x -= this.wheelRadius
@@ -400,17 +413,17 @@ module.exports = class ColorTriangle {
if (r > this.triangleRadius && r < this.wheelRadius) {
// Wheel
this.down = 'wheel'
- this._fireEvent('dragstart')
- this._move(x0, y0)
+ this.emit('dragstart')
+ this.move(x0, y0)
} else if (r < this.triangleRadius) {
// Inner circle
this.down = 'triangle'
- this._fireEvent('dragstart')
- this._move(x0, y0)
+ this.emit('dragstart')
+ this.move(x0, y0)
}
}
- _move (x, y) {
+ move (x, y) {
if (!this.down) {
return
}
@@ -420,17 +433,17 @@ module.exports = class ColorTriangle {
let rad = M.atan2(-y, x)
if (rad < 0) {
- rad += 2 * PI
+ rad += TAU
}
if (this.down === 'wheel') {
this.hue = rad
- this._initColor()
- this._fireEvent('drag')
+ this.initColor()
+ this.emit('drag')
} else if (this.down === 'triangle') {
// get radius and max radius
- let rad0 = (rad + 2 * PI - this.hue) % (2 * PI)
- let rad1 = rad0 % ((2 / 3) * PI) - (PI / 3)
+ let rad0 = (rad + TAU - this.hue) % TAU
+ let rad1 = rad0 % (TAU / 3) - (TAU / 6)
let a = 0.5 * this.triangleRadius
let b = M.tan(rad1) * a
let r = M.sqrt(x * x + y * y) // Pythagoras
@@ -439,15 +452,15 @@ module.exports = class ColorTriangle {
if (r > maxR) {
const dx = M.tan(rad1) * r
let rad2 = M.atan(dx / maxR)
- if (rad2 > PI / 3) {
- rad2 = PI / 3
- } else if (rad2 < -PI / 3) {
- rad2 = -PI / 3
+ if (rad2 > TAU / 6) {
+ rad2 = TAU / 6
+ } else if (rad2 < -TAU / 6) {
+ rad2 = -TAU / 6
}
rad += rad2 - rad1
- rad0 = (rad + 2 * PI - this.hue) % (2 * PI)
- rad1 = rad0 % ((2 / 3) * PI) - (PI / 3)
+ rad0 = (rad + TAU - this.hue) % TAU
+ rad1 = rad0 % (TAU / 3) - (TAU / 6)
b = M.tan(rad1) * a
r = maxR = M.sqrt(a * a + b * b) // Pythagoras
}
@@ -467,9 +480,9 @@ module.exports = class ColorTriangle {
this.x = x
this.y = y
- this._moveTrianglePointer()
+ this.moveTrianglePointer()
- this._fireEvent('drag')
+ this.emit('drag')
}
}
@@ -491,7 +504,7 @@ module.exports = class ColorTriangle {
options.event = options.event || 'dragend'
ct = new ColorTriangle(hex, options)
- ct.addEventListener(options.event, () => {
+ ct.on(options.event, () => {
const hex = ct.getHEX()
input.value = options.uppercase ? hex.toUpperCase() : hex
fireChangeEvent()
@@ -545,7 +558,7 @@ module.exports = class ColorTriangle {
* Helper functions *
*******************/
- _setOptions (opts) {
+ setOptions (opts) {
opts = opts || {}
let dflt = this.options
let options = this.options = {}
@@ -556,39 +569,4 @@ module.exports = class ColorTriangle {
: val
})
}
-
- addEventListener (type, fn) {
- if (!this.events) {
- this.events = {}
- }
- if (!this.events[type]) {
- this.events[type] = []
- }
- this.events[type].push(fn)
- }
-
- removeEventListener (type, fn) {
- if (this.events) {
- let fns = this.events[type]
- const l = fns.length
- for (let i = 0; i < l; i += 1) {
- if (fns[i] === fn) {
- fns.splice(i, 1)
- break
- }
- }
- }
- }
-
- _fireEvent (type) {
- if (this.events) {
- let evts = this.events[type]
- if (evts) {
- const args = Array.prototype.slice.call(arguments, 1)
- each(evts, function (evt) {
- evt(...args)
- })
- }
- }
- }
}
diff --git a/js/term/themes.js b/js/term/themes.js
index a1b84ee..8fb47ac 100644
--- a/js/term/themes.js
+++ b/js/term/themes.js
@@ -1,5 +1,5 @@
const $ = require('../lib/chibi')
-const { rgb255_to_hex } = require('../lib/color_utils')
+const { rgb255ToHex } = require('../lib/color_utils')
const themes = exports.themes = [
[ // 0 - Tango - terminator
@@ -84,14 +84,14 @@ exports.buildColorTable = function () {
let redValue = red * 40 + (red ? 55 : 0)
let greenValue = green * 40 + (green ? 55 : 0)
let blueValue = blue * 40 + (blue ? 55 : 0)
- colorTable256.push(rgb255_to_hex(redValue, greenValue, blueValue))
+ colorTable256.push(rgb255ToHex(redValue, greenValue, blueValue))
}
}
}
// colors 232-255 are a grayscale ramp, sans black and white
for (let gray = 0; gray < 24; gray++) {
let value = gray * 10 + 8
- colorTable256.push(rgb255_to_hex(value, value, value))
+ colorTable256.push(rgb255ToHex(value, value, value))
}
return colorTable256
From 57cdd04523e17eed709e27a029da0a2db5ec8e43 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sun, 1 Oct 2017 10:12:27 +0200
Subject: [PATCH 62/86] Fix wrong screen coords; show flags in binary
---
js/term/debug_screen.js | 20 ++++++++++----------
js/term/screen.js | 9 +++++----
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/js/term/debug_screen.js b/js/term/debug_screen.js
index a80ed8a..5c17372 100644
--- a/js/term/debug_screen.js
+++ b/js/term/debug_screen.js
@@ -19,15 +19,15 @@ module.exports = function attachDebugScreen (screen) {
let addCanvas = function () {
if (!debugCanvas.parentNode) {
screen.canvas.parentNode.appendChild(debugCanvas)
- screen.canvas.parentNode.addEventListener('mousemove', onMouseMove)
- screen.canvas.parentNode.addEventListener('mouseout', onMouseOut)
+ screen.canvas.addEventListener('mousemove', onMouseMove)
+ screen.canvas.addEventListener('mouseout', onMouseOut)
}
}
let removeCanvas = function () {
if (debugCanvas.parentNode) {
debugCanvas.parentNode.removeChild(debugCanvas)
- screen.canvas.parentNode.removeEventListener('mousemove', onMouseMove)
- screen.canvas.parentNode.removeEventListener('mouseout', onMouseOut)
+ screen.canvas.removeEventListener('mousemove', onMouseMove)
+ screen.canvas.removeEventListener('mouseout', onMouseOut)
onMouseOut()
}
}
@@ -261,10 +261,10 @@ module.exports = function attachDebugScreen (screen) {
const formatColor = color => color < 256 ? color : `#${`000000${(color - 256).toString(16)}`.substr(-6)}`
const getCellData = cell => {
if (cell < 0 || cell > screen.screen.length) return '(-)'
- let cellAttrs = screen.renderer.drawnScreenAttrs[cell]
- let cellFG = formatColor(screen.renderer.drawnScreenFG[cell])
- let cellBG = formatColor(screen.renderer.drawnScreenBG[cell])
- let cellCode = (screen.renderer.drawnScreen[cell] || '').codePointAt(0)
+ let cellAttrs = screen.renderer.drawnScreenAttrs[cell] | 0
+ let cellFG = formatColor(screen.renderer.drawnScreenFG[cell]) | 0
+ let cellBG = formatColor(screen.renderer.drawnScreenBG[cell]) | 0
+ let cellCode = (screen.renderer.drawnScreen[cell] || '').codePointAt(0) | 0
let hexcode = cellCode.toString(16).toUpperCase()
if (hexcode.length < 4) hexcode = `0000${hexcode}`.substr(-4)
hexcode = `U+${hexcode}`
@@ -284,8 +284,8 @@ module.exports = function attachDebugScreen (screen) {
if ('flags' in internalInfo) {
// we got ourselves some internal data
text += ' '
- text += ` flags:${internalInfo.flags}`
- text += ` curAttrs:${internalInfo.cursorAttrs}`
+ text += ` flags:${internalInfo.flags.toString(2)}`
+ text += ` curAttrs:${internalInfo.cursorAttrs.toString(2)}`
text += ` Region:${internalInfo.regionStart}->${internalInfo.regionEnd}`
text += ` Charset:${internalInfo.charsetGx} (0:${internalInfo.charsetG0},1:${internalInfo.charsetG1})`
text += ` Heap:${internalInfo.freeHeap}`
diff --git a/js/term/screen.js b/js/term/screen.js
index 3fbd187..98ff13d 100644
--- a/js/term/screen.js
+++ b/js/term/screen.js
@@ -321,11 +321,12 @@ module.exports = class TermScreen extends EventEmitter {
x = x / this._windowScale - this._padding
y = y / this._windowScale - this._padding
+ x = Math.floor((x + (rounded ? cellSize.width / 2 : 0)) / cellSize.width)
+ y = Math.floor(y / cellSize.height)
+ x = Math.max(0, Math.min(this.window.width - 1, x))
+ y = Math.max(0, Math.min(this.window.height - 1, y))
- return [
- Math.floor((x + (rounded ? cellSize.width / 2 : 0)) / cellSize.width),
- Math.floor(y / cellSize.height)
- ]
+ return [x, y]
}
/**
From 29b813457c7a185c41e050d358b001fadd2498e4 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sun, 1 Oct 2017 11:15:58 +0200
Subject: [PATCH 63/86] Improve smooth scrolling
---
js/term/screen.js | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/js/term/screen.js b/js/term/screen.js
index 98ff13d..4a28355 100644
--- a/js/term/screen.js
+++ b/js/term/screen.js
@@ -268,10 +268,20 @@ module.exports = class TermScreen extends EventEmitter {
}
})
+ let aggregateWheelDelta = 0
this.canvas.addEventListener('wheel', e => {
if (this.mouseMode.clicks) {
- this.input.onMouseWheel(...this.screenToGrid(e.offsetX, e.offsetY),
- e.deltaY > 0 ? 1 : -1)
+ if (Math.abs(e.wheelDeltaY) === 120) {
+ // mouse wheel scrolling
+ this.input.onMouseWheel(...this.screenToGrid(e.offsetX, e.offsetY), e.deltaY > 0 ? 1 : -1)
+ } else {
+ // smooth scrolling
+ aggregateWheelDelta -= e.wheelDeltaY
+ if (Math.abs(aggregateWheelDelta) >= 40) {
+ this.input.onMouseWheel(...this.screenToGrid(e.offsetX, e.offsetY), aggregateWheelDelta > 0 ? 1 : -1)
+ aggregateWheelDelta = 0
+ }
+ }
// prevent page scrolling
e.preventDefault()
From 5eec2f523ba79e08a1fe453772f29a82d219ae56 Mon Sep 17 00:00:00 2001
From: cpsdqs
Date: Sun, 1 Oct 2017 21:22:56 +0200
Subject: [PATCH 64/86] Make debug toolbar a bit nicer
---
js/term/debug_screen.js | 79 +++++++++++++++++++++++++++++++++++++++--
sass/pages/_term.scss | 2 --
2 files changed, 76 insertions(+), 5 deletions(-)
diff --git a/js/term/debug_screen.js b/js/term/debug_screen.js
index 5c17372..eed2c0a 100644
--- a/js/term/debug_screen.js
+++ b/js/term/debug_screen.js
@@ -218,6 +218,9 @@ module.exports = function attachDebugScreen (screen) {
const dataDisplay = mk('div')
dataDisplay.classList.add('data-display')
toolbar.appendChild(dataDisplay)
+ const internalDisplay = mk('div')
+ internalDisplay.classList.add('internal-display')
+ toolbar.appendChild(internalDisplay)
toolbar.appendChild(drawInfo)
const buttons = mk('div')
buttons.classList.add('toolbar-buttons')
@@ -258,6 +261,28 @@ module.exports = function attachDebugScreen (screen) {
}
})
+ const displayCellAttrs = attrs => {
+ let result = attrs.toString(16)
+ if (attrs & 1 || attrs & 2) {
+ result += ':has('
+ if (attrs & 1) result += 'fg'
+ if (attrs & 2) result += (attrs & 1 ? ',' : '') + 'bg'
+ result += ')'
+ }
+ let attributes = []
+ if (attrs & (1 << 2)) attributes.push('\\(bold)bold\\()')
+ if (attrs & (1 << 3)) attributes.push('\\(underline)underln\\()')
+ if (attrs & (1 << 4)) attributes.push('\\(invert)invert\\()')
+ if (attrs & (1 << 5)) attributes.push('blink')
+ if (attrs & (1 << 6)) attributes.push('\\(italic)italic\\()')
+ if (attrs & (1 << 7)) attributes.push('\\(strike)strike\\()')
+ if (attrs & (1 << 8)) attributes.push('\\(overline)overln\\()')
+ if (attrs & (1 << 9)) attributes.push('\\(faint)faint\\()')
+ if (attrs & (1 << 10)) attributes.push('fraktur')
+ if (attributes.length) result += ':' + attributes.join()
+ return result.trim()
+ }
+
const formatColor = color => color < 256 ? color : `#${`000000${(color - 256).toString(16)}`.substr(-6)}`
const getCellData = cell => {
if (cell < 0 || cell > screen.screen.length) return '(-)'
@@ -270,7 +295,53 @@ module.exports = function attachDebugScreen (screen) {
hexcode = `U+${hexcode}`
let x = cell % screen.window.width
let y = Math.floor(cell / screen.window.width)
- return `((${y},${x})=${cell}:${hexcode}:F${cellFG}:B${cellBG}:A${cellAttrs.toString(2)})`
+ return `((${y},${x})=${cell}:\\(bold)${hexcode}\\():F${cellFG}:B${cellBG}:A(${displayCellAttrs(cellAttrs)}))`
+ }
+
+ const setFormattedText = (node, text) => {
+ node.innerHTML = ''
+
+ let match
+ let attrs = {}
+
+ let pushSpan = content => {
+ let span = mk('span')
+ node.appendChild(span)
+ span.textContent = content
+ for (let key in attrs) span[key] = attrs[key]
+ }
+
+ while ((match = text.match(/\\\((.*?)\)/))) {
+ if (match.index > 0) pushSpan(text.substr(0, match.index))
+
+ attrs = { style: '' }
+ let data = match[1].split(' ')
+ for (let attr of data) {
+ if (!attr) continue
+ let key, value
+ if (attr.indexOf('=') > -1) {
+ key = attr.substr(0, attr.indexOf('='))
+ value = attr.substr(attr.indexOf('=') + 1)
+ } else {
+ key = attr
+ value = true
+ }
+
+ if (key === 'bold') attrs.style += 'font-weight:bold;'
+ if (key === 'italic') attrs.style += 'font-style:italic;'
+ if (key === 'underline') attrs.style += 'text-decoration:underline;'
+ if (key === 'invert') attrs.style += 'background:#000;filter:invert(1);'
+ if (key === 'strike') attrs.style += 'text-decoration:line-through;'
+ if (key === 'overline') attrs.style += 'text-decoration:overline;'
+ if (key === 'faint') attrs.style += 'opacity:0.5;'
+ else if (key === 'color') attrs.style += `color:${value};`
+ else attrs[key] = value
+ }
+
+ text = text.substr(match.index + match[0].length)
+ }
+
+ if (text) pushSpan(text)
}
let internalInfo = {}
@@ -281,17 +352,19 @@ module.exports = function attachDebugScreen (screen) {
if (mouseHoverCell) {
text += ' m' + getCellData(mouseHoverCell[1] * screen.window.width + mouseHoverCell[0])
}
+ setFormattedText(dataDisplay, text)
+
if ('flags' in internalInfo) {
// we got ourselves some internal data
- text += ' '
+ let text = ' '
text += ` flags:${internalInfo.flags.toString(2)}`
text += ` curAttrs:${internalInfo.cursorAttrs.toString(2)}`
text += ` Region:${internalInfo.regionStart}->${internalInfo.regionEnd}`
text += ` Charset:${internalInfo.charsetGx} (0:${internalInfo.charsetG0},1:${internalInfo.charsetG1})`
text += ` Heap:${internalInfo.freeHeap}`
text += ` Clients:${internalInfo.clientCount}`
+ setFormattedText(internalDisplay, text)
}
- dataDisplay.textContent = text
}
screen.on('draw', updateToolbar)
diff --git a/sass/pages/_term.scss b/sass/pages/_term.scss
index f547456..f2c5537 100644
--- a/sass/pages/_term.scss
+++ b/sass/pages/_term.scss
@@ -112,8 +112,6 @@ body.term {
font-family: $screen-stack;
font-size: 12px;
white-space: normal;
- // close enough:
- max-width: 400px;
}
}
From 8d2d5fda42fb2b6f87fa43c779fd1d13a0a0b95a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sun, 1 Oct 2017 22:46:10 +0200
Subject: [PATCH 65/86] some reconn timing adjustments
---
js/term/connection.js | 65 +++++++++++++++++++++++++++----------------
1 file changed, 41 insertions(+), 24 deletions(-)
diff --git a/js/term/connection.js b/js/term/connection.js
index 1acad23..7e10520 100644
--- a/js/term/connection.js
+++ b/js/term/connection.js
@@ -3,6 +3,9 @@ const $ = require('../lib/chibi')
let demo
try { demo = require('./demo') } catch (err) {}
+const RECONN_DELAY = 2000
+const HEARTBEAT_TIME = 3000
+
/** Handle connections */
module.exports = class TermConnection extends EventEmitter {
constructor (screen) {
@@ -17,12 +20,16 @@ module.exports = class TermConnection extends EventEmitter {
this.reconnTimeout = null
this.forceClosing = false
- this.blobReader = new FileReader()
- this.blobReader.onload = (evt) => {
- this.onDecodedWSMessage(this.blobReader.result)
- }
- this.blobReader.onerror = (evt) => {
- console.error(evt)
+ try {
+ this.blobReader = new FileReader()
+ this.blobReader.onload = (evt) => {
+ this.onDecodedWSMessage(this.blobReader.result)
+ }
+ this.blobReader.onerror = (evt) => {
+ console.error(evt)
+ }
+ } catch (e) {
+ this.blobReader = null
}
this.pageShown = false
@@ -67,7 +74,7 @@ module.exports = class TermConnection extends EventEmitter {
}
clearTimeout(this.reconnTimeout)
- this.reconnTimeout = setTimeout(() => this.init(), 2000)
+ this.reconnTimeout = setTimeout(() => this.init(), RECONN_DELAY)
this.emit('disconnect', evt.code)
}
@@ -75,6 +82,7 @@ module.exports = class TermConnection extends EventEmitter {
onDecodedWSMessage (str) {
switch (str.charAt(0)) {
case '.':
+ console.log(str)
// heartbeat, no-op message
break
@@ -106,6 +114,11 @@ module.exports = class TermConnection extends EventEmitter {
onWSMessage (evt) {
if (typeof evt.data === 'string') this.onDecodedWSMessage(evt.data)
else {
+ if (!this.blobReader) {
+ console.error('No FileReader!')
+ return
+ }
+
if (this.blobReader.readyState !== 1) {
this.blobReader.readAsText(evt.data)
} else {
@@ -183,7 +196,24 @@ module.exports = class TermConnection extends EventEmitter {
heartbeat () {
clearTimeout(this.heartbeatTimeout)
- this.heartbeatTimeout = setTimeout(() => this.onHeartbeatFail(), 2500)
+ this.heartbeatTimeout = setTimeout(() => this.onHeartbeatFail(), HEARTBEAT_TIME)
+ }
+
+ sendPing () {
+ console.log('> ping')
+ this.emit('ping')
+ $.get('http://' + window._root + '/system/ping', (resp, status) => {
+ if (status === 200) {
+ clearInterval(this.pingInterval)
+ console.info('Server ready, opening socket…')
+ this.emit('ping-success')
+ this.init()
+ // location.reload()
+ } else this.emit('ping-fail', status)
+ }, {
+ timeout: 100,
+ loader: false // we have loader on-screen
+ })
}
onHeartbeatFail () {
@@ -191,22 +221,9 @@ module.exports = class TermConnection extends EventEmitter {
this.emit('silence')
console.error('Heartbeat lost, probing server...')
clearInterval(this.pingInterval)
+ this.pingInterval = setInterval(() => { this.sendPing() }, 1000)
- this.pingInterval = setInterval(() => {
- console.log('> ping')
- this.emit('ping')
- $.get('http://' + window._root + '/system/ping', (resp, status) => {
- if (status === 200) {
- clearInterval(this.pingInterval)
- console.info('Server ready, opening socket…')
- this.emit('ping-success')
- this.init()
- // location.reload()
- } else this.emit('ping-fail', status)
- }, {
- timeout: 100,
- loader: false // we have loader on-screen
- })
- }, 1000)
+ // first ping, if this gets through, it'll will reduce delay
+ setTimeout(() => { this.sendPing() }, 200)
}
}
From 6f165da9b6237fd88efc836a663a429ed8aadb6e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Sun, 1 Oct 2017 23:05:39 +0200
Subject: [PATCH 66/86] update api routes
---
_pages.php | 2 +-
js/term/connection.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/_pages.php b/_pages.php
index c2d9ad7..b45d23f 100644
--- a/_pages.php
+++ b/_pages.php
@@ -41,7 +41,7 @@ pg('help', 'cfg page-help', 'help', '/help');
pg('about', 'cfg page-about', 'about', '/about');
pg('term', 'term', '', '/', 'title.term');
-pg('reset_screen', 'api', '', '/system/cls', 'title.term');
+pg('reset_screen', 'api', '', '/api/v1/clear', 'title.term');
pg('index', 'api', '', '/', '');
diff --git a/js/term/connection.js b/js/term/connection.js
index 7e10520..d53966c 100644
--- a/js/term/connection.js
+++ b/js/term/connection.js
@@ -202,7 +202,7 @@ module.exports = class TermConnection extends EventEmitter {
sendPing () {
console.log('> ping')
this.emit('ping')
- $.get('http://' + window._root + '/system/ping', (resp, status) => {
+ $.get('http://' + window._root + '/api/v1/ping', (resp, status) => {
if (status === 200) {
clearInterval(this.pingInterval)
console.info('Server ready, opening socket…')
From 6c0b0aa6e12d1343837245e9366c1e7e86345dfe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?=
Date: Mon, 2 Oct 2017 02:53:34 +0200
Subject: [PATCH 67/86] document networking commands
---
pages/help.php | 1 +
pages/help/cmd_d2d.php | 87 +++++++++++++++++++++++++++++++++++++++
pages/help/sgr_colors.php | 2 +-
pages/help/sgr_styles.php | 2 +-
4 files changed, 90 insertions(+), 2 deletions(-)
create mode 100644 pages/help/cmd_d2d.php
diff --git a/pages/help.php b/pages/help.php
index e577a72..a7529a4 100644
--- a/pages/help.php
+++ b/pages/help.php
@@ -16,6 +16,7 @@
+
+
+