remote-i3wm-go/static/js/main.js

400 lines
11 KiB
JavaScript

let ws
let pointer, scroller, response, screenshotImg
let scrollLastTimestamp, scrollLastValue
let mousePosX, mousePosY, mouseInitPosX, mouseInitPosY
let isLive = false
let wsLock = false
let isPointerLive = false
let isScreenshotWaiting = null
let isPointerScreenshotWaiting = false
let emptyImg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gIJDjc3srQk8gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAADElEQVQI12P48+cPAAXsAvVTWDc6AAAAAElFTkSuQmCC"
function createWebSocketConnection() {
const protocol = location.protocol === 'https:' ? 'wss' : 'ws'
ws = new WebSocket(`${protocol}://${window.location.hostname}:${window.location.port}/ws`)
ws.addEventListener('open', function(event) {
document.querySelector('#disconneced').style.display = 'none'
unLock()
})
ws.addEventListener('close', function(event) {
unLock()
document.querySelector('#disconneced').style.display = 'block'
window.setTimeout(createWebSocketConnection, 5000)
})
ws.addEventListener('message', function(event) {
unLock()
let data = JSON.parse(event.data)
if (data.type === 'response') {
response.innerText = data.value
response.style.display = 'block'
window.setTimeout(function() {
response.style.display = 'none'
}, 2500)
return
}
if (data.type === 'volume') {
if (data.value.length) {
setVolume(parseInt(data.value))
}
return
}
})
}
function isLocked() {
return wsLock === true
}
function lock() {
wsLock = true
}
function unLock() {
wsLock = false
}
function send(message) {
if (isLocked()) {
return
}
lock()
ws.send(message)
}
function navigationClickHandler(e) {
if (e.target.getAttribute('href') === '#') {
return
}
Array.from(document.querySelectorAll('.pane')).forEach((item) => {
item.style.display = 'none'
})
document.querySelector(e.target.getAttribute('href')).style.display = 'block'
Array.from(document.querySelectorAll('#nav a')).forEach((item) => {
item.classList.remove('active')
})
e.target.classList.add('active')
}
function buttonClickHandler(e) {
send(e.target.getAttribute('data-msg'))
}
function shortcutClearClickHandler(e) {
document.querySelector('#shortcut-key').value = ''
Array.from(document.querySelectorAll('#shortcuts_special_keys input:checked')).forEach((item) => {
item.checked = false
item.change()
})
}
function shortcutSendClickHandler(e) {
let keys = []
let key = document.querySelector('#shortcut-key').value
Array.from(document.querySelectorAll('#shortcuts_special_keys input:checked')).forEach((item) => {
keys.push(item.value)
})
if (keys.length) {
if (key) {
keys.push(key)
}
send('{"type":"keys","value": "' + (keys.join(',').replace('"', '\\"')) + '"}')
}
}
function textClearClickHandler(e) {
document.querySelector('#text').value = ''
}
function textSendClickHandler(e) {
const keys = document.querySelector('#text').value
if (keys.length) {
send('{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}')
}
}
function textKeyUpHandler(e) {
const keys = document.querySelector('#text').value
if (e.keyCode === 13) {
send('{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}')
}
}
function liveTextKeyUpHandler(e) {
const value = e.target.value
const size = value.length
const messages = []
if (size > 0) {
messages.push('{"type":"text","value": "' + (value.replace('"', '\\"')) + '"}')
if (value[size-1] === ' ') {
messages.push('{"type":"key","value":"space"}')
}
}
if (e.keyCode === 8) {
messages.push('{"type":"key","value": "backspace"}')
} else if (e.keyCode === 13 && size === 0) {
messages.push('{"type":"key","value": "enter"}')
}
send(`{"type":"messages","value":[${messages.join(',')}]}`)
e.target.value = ''
}
function shortcutsSpecialKeysOnChangeHandler(e) {
Array.from(document.querySelectorAll('#shortcuts_special_keys input:checked')).forEach((item) => {
item.parentNode.classList.add('btn-primary')
item.parentNode.classList.remove('btn-secondary')
})
Array.from(document.querySelectorAll('#shortcuts_special_keys input:not(:checked)')).forEach((item) => {
item.parentNode.classList.add('btn-secondary')
item.parentNode.classList.remove('btn-primary')
})
}
function pointerClickHandler(e) {
send('{"type":"pointer","click":"left"}')
}
function scrollerTouchStartHandler(e) {
mouseInitPosY = e.targetTouches[0].pageY
}
function scrollerTouchMoveHandler(e) {
let touch = e.changedTouches[0]
let value = ((touch.pageY - mouseInitPosY > 0) ? 'down' : 'up')
let now = new Date().getTime()
if (touch.pageY === mouseInitPosY || value === scrollLastValue && scrollLastTimestamp !== null && now - scrollLastTimestamp < 200) {
return
}
scrollLastTimestamp = now
scrollLastValue = value
mouseInitPosY = touch.pageY
send('{"type":"scroll","value": "' + value + '"}')
}
function pointerTouchStartHandler(e) {
const touch = e.targetTouches[0]
mouseInitPosX = touch.pageX
mouseInitPosY = touch.pageY
}
function pointerLiveHandler(e) {
if (!e.target.checked) {
pointer.style.backgroundImage = ""
} else {
pointer.style.backgroundImage = `url("/capture?type=live&pointer=1&${Math.random()}")`
}
}
function pointerTouchMoveHandler(e) {
if (e.changedTouches.length === 2) {
return scrollerTouchMoveHandler(e)
}
const touch = e.changedTouches[0]
mousePosX = touch.pageX
mousePosY = touch.pageY
const newX = mousePosX - mouseInitPosX
const newY = mousePosY - mouseInitPosY
mouseInitPosX = mousePosX
mouseInitPosY = mousePosY
let msg = '{"type":"pointer","x": "' + newX + '","y": "' + newY + '"}'
ws.send(msg)
}
function capture(mode) {
}
function captureScreenshotClickHandler(e) {
const img = e.target.parentNode.querySelector('.capture-img img')
img.src = "/capture?type=screenshot&" + Math.random()
}
function captureLiveClickHandler(e) {
const img = e.target.parentNode.querySelector('.capture-img img')
if (img.src.indexOf("live") > -1) {
img.src = emptyImg
} else {
img.src = "/capture?type=live&" + Math.random()
}
}
function fullscreenHandler(e) {
const targetConf = e.target.getAttribute('data-target')
const isFullscreen = parseInt(e.target.getAttribute('data-fullscreen'))
const element = (targetConf === 'this')
? e.target
: document.querySelector(targetConf)
document.querySelector('body').classList.toggle('fullscreen', isFullscreen)
if (isFullscreen) {
e.target.setAttribute('data-fullscreen', '0')
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen()
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
}
} else {
e.target.setAttribute('data-fullscreen', '1')
if (element.requestFullscreen) {
element.requestFullscreen()
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen()
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen()
}
}
}
function documentHashHandler() {
const hash = window.location.hash
if (hash) {
document.querySelector('a[href="' + hash + '"]').click()
} else {
document.querySelector('#nav > li:first-child a').click()
}
}
function addEventListenerOn(selector, eventName, listener) {
if (typeof selector === 'string') {
Array.from(document.querySelectorAll(selector)).forEach((element) => {
element.addEventListener(eventName, listener)
})
} else {
selector.addEventListener(eventName, listener)
}
}
function addListeners() {
addEventListenerOn('#nav a', 'click', navigationClickHandler)
addEventListenerOn('button[data-msg]', 'click', buttonClickHandler)
addEventListenerOn('#shortcut-clear', 'click', shortcutClearClickHandler)
addEventListenerOn('#shortcuts_special_keys input', 'change', shortcutsSpecialKeysOnChangeHandler)
addEventListenerOn('#shortcut-send', 'click', shortcutSendClickHandler)
addEventListenerOn('#text-clear', 'click', textClearClickHandler)
addEventListenerOn('#text-send', 'click', textSendClickHandler)
addEventListenerOn('#text', 'keyup', textKeyUpHandler)
Array.from(document.querySelectorAll('.live-text')).forEach((element) => {
element.setAttribute('data-composing', '0')
addEventListenerOn(element, 'compositionstart', (e) => {
element.setAttribute('data-composing', '1')
})
addEventListenerOn(element, 'compositionend', (e) => {
element.setAttribute('data-composing', '0')
})
addEventListenerOn(element, 'keyup', (e) => {
if (element.getAttribute('data-composing') === '1') {
return
}
liveTextKeyUpHandler(e)
})
})
addEventListenerOn(scroller, 'touchstart', scrollerTouchStartHandler)
addEventListenerOn(scroller, 'touchmove', scrollerTouchMoveHandler)
addEventListenerOn(pointer, 'click', pointerClickHandler)
addEventListenerOn(pointer, 'touchstart', pointerTouchStartHandler)
addEventListenerOn(pointer, 'touchmove', pointerTouchMoveHandler)
addEventListenerOn('#mouse-screenshot-live input', 'change', pointerLiveHandler)
addEventListenerOn('.capture-live', 'click', captureLiveClickHandler)
addEventListenerOn('.capture-screenshot', 'click', captureScreenshotClickHandler)
addEventListenerOn('.btn-fullscreen', 'click', fullscreenHandler)
}
function getVolume() {
if (document.querySelectorAll('.volume').length) {
try {
send('{"type":"volume","value":"value"}')
} catch (e) {
}
document.querySelectorAll('.volume input[type="range"]').forEach(function(input) {
if (input.getAttribute('data-event')) {
return
}
input.setAttribute('data-event', 'ok')
input.addEventListener('change', (e) => {
send(`{"type":"volume","value":"${e.target.value}"}`)
})
})
}
window.setTimeout(getVolume, 2000)
}
function setVolume(value) {
document.querySelectorAll('.volume').forEach(function(item) {
item.querySelector('input[type="range"]').value = value
})
}
function bootstrap() {
pointer = document.querySelector('#pointer')
scroller = document.querySelector('#scrollbar')
response = document.querySelector('#response')
screenshotImg = document.querySelector('#screenshot img')
shortcutsSpecialKeysOnChangeHandler()
createWebSocketConnection()
addListeners()
documentHashHandler()
getVolume()
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/static/js/service_worker.js')
}
}
addEventListenerOn(window, 'DOMContentLoaded', bootstrap)