Compare commits
4 Commits
8cd94b30f6
...
93b66b6a26
Author | SHA1 | Date | |
---|---|---|---|
93b66b6a26 | |||
ee1750c23c | |||
f5104c807d | |||
2c49a72d94 |
@ -26,8 +26,7 @@ As a unique bonus, you can launch a full text editor from within.
|
|||||||
xP
|
xP
|
||||||
--
|
--
|
||||||
The web frontend for 'xC', making use of its networked relay interface.
|
The web frontend for 'xC', making use of its networked relay interface.
|
||||||
So far it's quite basic, yet usable. Build it using `make` in its directory,
|
So far it's quite basic, yet usable.
|
||||||
and run it from within the _public_ subdirectory.
|
|
||||||
|
|
||||||
xF
|
xF
|
||||||
--
|
--
|
||||||
@ -116,6 +115,11 @@ a Screen or tmux session.
|
|||||||
file or something like `killall` if you want to terminate it. You can run it
|
file or something like `killall` if you want to terminate it. You can run it
|
||||||
as a `forking` type systemd user service.
|
as a `forking` type systemd user service.
|
||||||
|
|
||||||
|
xP
|
||||||
|
~~
|
||||||
|
Install the Go compiler, and build the server using `make` in its directory,
|
||||||
|
then run it from within the _public_ subdirectory.
|
||||||
|
|
||||||
Client Certificates
|
Client Certificates
|
||||||
-------------------
|
-------------------
|
||||||
'xC' will use the SASL EXTERNAL method to authenticate using the TLS client
|
'xC' will use the SASL EXTERNAL method to authenticate using the TLS client
|
||||||
|
@ -24,8 +24,8 @@ class RelayRpc extends EventTarget {
|
|||||||
}
|
}
|
||||||
// It's going to be code 1006 with no further info.
|
// It's going to be code 1006 with no further info.
|
||||||
ws.onclose = event => {
|
ws.onclose = event => {
|
||||||
reject()
|
|
||||||
this.ws = undefined
|
this.ws = undefined
|
||||||
|
reject()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -122,15 +122,25 @@ class RelayRpc extends EventTarget {
|
|||||||
|
|
||||||
// ---- Event processing -------------------------------------------------------
|
// ---- Event processing -------------------------------------------------------
|
||||||
|
|
||||||
// TODO: Probably reset state on disconnect, and indicate to user.
|
|
||||||
let rpc = new RelayRpc(proxy)
|
let rpc = new RelayRpc(proxy)
|
||||||
rpc.connect()
|
|
||||||
.then(result => {
|
|
||||||
rpc.send({command: 'Hello', version: 1})
|
|
||||||
})
|
|
||||||
|
|
||||||
let buffers = new Map()
|
let buffers = new Map()
|
||||||
let bufferCurrent = undefined
|
let bufferCurrent = undefined
|
||||||
|
let connecting = true
|
||||||
|
rpc.connect().then(result => {
|
||||||
|
buffers.clear()
|
||||||
|
bufferCurrent = undefined
|
||||||
|
rpc.send({command: 'Hello', version: 1})
|
||||||
|
connecting = false
|
||||||
|
m.redraw()
|
||||||
|
}).catch(error => {
|
||||||
|
connecting = false
|
||||||
|
m.redraw()
|
||||||
|
})
|
||||||
|
|
||||||
|
rpc.addEventListener('close', event => {
|
||||||
|
m.redraw()
|
||||||
|
})
|
||||||
|
|
||||||
rpc.addEventListener('BufferUpdate', event => {
|
rpc.addEventListener('BufferUpdate', event => {
|
||||||
let e = event.detail, b = buffers.get(e.bufferName)
|
let e = event.detail, b = buffers.get(e.bufferName)
|
||||||
@ -155,13 +165,17 @@ rpc.addEventListener('BufferRemove', event => {
|
|||||||
rpc.addEventListener('BufferActivate', event => {
|
rpc.addEventListener('BufferActivate', event => {
|
||||||
let e = event.detail
|
let e = event.detail
|
||||||
bufferCurrent = e.bufferName
|
bufferCurrent = e.bufferName
|
||||||
// TODO: Somehow scroll to the end of it immediately.
|
setTimeout(() => {
|
||||||
// TODO: Focus the textarea.
|
let el = document.getElementById('input')
|
||||||
|
if (el !== null)
|
||||||
|
el.focus()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
rpc.addEventListener('BufferLine', event => {
|
rpc.addEventListener('BufferLine', event => {
|
||||||
let e = event.detail, b = buffers.get(e.bufferName)
|
let e = event.detail, b = buffers.get(e.bufferName)
|
||||||
if (b !== undefined)
|
if (b === undefined)
|
||||||
|
return
|
||||||
b.lines.push({when: e.when, rendition: e.rendition, items: e.items})
|
b.lines.push({when: e.when, rendition: e.rendition, items: e.items})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -194,11 +208,11 @@ function applyColor(fg, bg, inverse) {
|
|||||||
if (inverse)
|
if (inverse)
|
||||||
[fg, bg] = [bg >= 0 ? bg : 15, fg >= 0 ? fg : 0]
|
[fg, bg] = [bg >= 0 ? bg : 15, fg >= 0 ? fg : 0]
|
||||||
|
|
||||||
let style = ''
|
let style = {}
|
||||||
if (fg >= 0)
|
if (fg >= 0)
|
||||||
style += `color: ${palette[fg]};`
|
style.color = palette[fg]
|
||||||
if (bg >= 0)
|
if (bg >= 0)
|
||||||
style += `background-color: ${palette[bg]};`
|
style.backgroundColor = palette[bg]
|
||||||
if (style)
|
if (style)
|
||||||
return style
|
return style
|
||||||
}
|
}
|
||||||
@ -295,6 +309,19 @@ let Content = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Buffer = {
|
let Buffer = {
|
||||||
|
oncreate: vnode => {
|
||||||
|
if (vnode.dom === undefined)
|
||||||
|
return
|
||||||
|
|
||||||
|
let el = vnode.dom.children[1]
|
||||||
|
if (el !== null)
|
||||||
|
el.scrollTop = el.scrollHeight
|
||||||
|
},
|
||||||
|
|
||||||
|
onupdate: vnode => {
|
||||||
|
Buffer.oncreate(vnode)
|
||||||
|
},
|
||||||
|
|
||||||
view: vnode => {
|
view: vnode => {
|
||||||
let lines = []
|
let lines = []
|
||||||
let b = buffers.get(bufferCurrent)
|
let b = buffers.get(bufferCurrent)
|
||||||
@ -365,7 +392,7 @@ function onKeyDown(event) {
|
|||||||
// and we'll probably have to intercept /all/ key presses.
|
// and we'll probably have to intercept /all/ key presses.
|
||||||
let Input = {
|
let Input = {
|
||||||
view: vnode => {
|
view: vnode => {
|
||||||
return m('textarea', {
|
return m('textarea#input', {
|
||||||
rows: 1,
|
rows: 1,
|
||||||
onkeydown: onKeyDown,
|
onkeydown: onKeyDown,
|
||||||
})
|
})
|
||||||
@ -374,8 +401,14 @@ let Input = {
|
|||||||
|
|
||||||
let Main = {
|
let Main = {
|
||||||
view: vnode => {
|
view: vnode => {
|
||||||
|
let state = "Connected"
|
||||||
|
if (connecting)
|
||||||
|
state = "Connecting..."
|
||||||
|
else if (rpc.ws === undefined)
|
||||||
|
state = "Disconnected"
|
||||||
|
|
||||||
return m('.xP', {}, [
|
return m('.xP', {}, [
|
||||||
m('.title', {}, "xP"),
|
m('.title', {}, `xP (${state})`),
|
||||||
m('.middle', {}, [m(BufferList), m(Buffer)]),
|
m('.middle', {}, [m(BufferList), m(Buffer)]),
|
||||||
m('.status', {}, bufferCurrent),
|
m('.status', {}, bufferCurrent),
|
||||||
m(Input),
|
m(Input),
|
||||||
@ -383,9 +416,4 @@ let Main = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Buffer names should work as routes.
|
window.addEventListener('load', () => m.mount(document.body, Main))
|
||||||
window.addEventListener('load', () => {
|
|
||||||
m.route(document.body, '/', {
|
|
||||||
'/': Main,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user