Compare commits
10 commits
dd24fda35b
...
a9601c479d
Author | SHA1 | Date | |
---|---|---|---|
Simon Vieille | a9601c479d | ||
Simon Vieille | e65fccee03 | ||
Simon Vieille | 73b9f98297 | ||
Simon Vieille | fc8e74c772 | ||
Simon Vieille | 253073f15f | ||
Simon Vieille | c865080df1 | ||
Simon Vieille | 5f18c04d4d | ||
Simon Vieille | e6934dd9aa | ||
Simon Vieille | 71ce3bb90d | ||
Simon Vieille | 3533ea4dfe |
|
@ -1,5 +1,12 @@
|
|||
## [Unreleased]
|
||||
|
||||
## v2.0.0
|
||||
### Added
|
||||
* add an option to start the web server with TLS (HTTPS)
|
||||
### Changed
|
||||
* remove jquery
|
||||
* upgrade Bootstrap
|
||||
|
||||
## v1.0.2
|
||||
### Fixed
|
||||
* close connection on ws error
|
||||
|
|
|
@ -5,6 +5,12 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
type TlsConfig struct {
|
||||
Enable bool `yaml:"enable"`
|
||||
CertFile string `yaml:"certificate"`
|
||||
CertKeyFile string `yaml:"certificate_key"`
|
||||
}
|
||||
|
||||
type ServerAuthConfig struct {
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
|
@ -13,6 +19,7 @@ type ServerAuthConfig struct {
|
|||
type ServerConfig struct {
|
||||
Listen string `yaml:"listen"`
|
||||
Auth ServerAuthConfig `yaml:"auth"`
|
||||
Tls TlsConfig `yaml:tls`
|
||||
}
|
||||
|
||||
type RemoteItemConfigItem struct {
|
||||
|
|
|
@ -3,6 +3,10 @@ server:
|
|||
username: admin
|
||||
password: admin
|
||||
listen: 0.0.0.0:4000
|
||||
tls:
|
||||
enable: false
|
||||
certificate: /path/to/server.crt
|
||||
certificate_key: /path/to/server.key
|
||||
|
||||
remote:
|
||||
- label: Keyboard
|
||||
|
|
10
main.go
10
main.go
|
@ -62,5 +62,13 @@ func main() {
|
|||
e.GET("/", homeController)
|
||||
e.GET("/ws", wsController)
|
||||
|
||||
e.Logger.Fatal(e.Start(config.Server.Listen))
|
||||
if config.Server.Tls.Enable == false {
|
||||
e.Logger.Fatal(e.Start(config.Server.Listen))
|
||||
} else {
|
||||
e.Logger.Fatal(e.StartTLS(
|
||||
config.Server.Listen,
|
||||
config.Server.Tls.CertFile,
|
||||
config.Server.Tls.CertKeyFile,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
120
rice-box.go
120
rice-box.go
File diff suppressed because one or more lines are too long
7
static/bootstrap.bundle.min.js
vendored
7
static/bootstrap.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
7
static/bootstrap.min.css
vendored
7
static/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
7
static/bootstrap.min.js
vendored
7
static/bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
6
static/css/bootstrap.min.css
vendored
Normal file
6
static/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,10 @@
|
|||
:root {
|
||||
--link-color: #1e3650;
|
||||
--bs-link-color: var(--link-color);
|
||||
}
|
||||
|
||||
a {
|
||||
color: #1e3650;
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
.btn-primary {
|
BIN
static/img/icon.png
Normal file
BIN
static/img/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
4
static/jquery.min.js
vendored
4
static/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
316
static/js/main.js
Normal file
316
static/js/main.js
Normal file
|
@ -0,0 +1,316 @@
|
|||
let ws
|
||||
let pointer, scroller, response, screenshotImg
|
||||
let scrollLastTimestamp, scrollLastValue
|
||||
let mousePosX, mousePosY, mouseInitPosX, mouseInitPosY
|
||||
let isLive = false
|
||||
let isScreenshotWaiting = false
|
||||
|
||||
function createWebSocketConnection() {
|
||||
const protocol = location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
|
||||
ws = new WebSocket(`${protocol}://${window.location.hostname}:${window.location.port}/ws`)
|
||||
|
||||
ws.onopen = function(event) {
|
||||
document.querySelector('#disconneced').style.display = 'none'
|
||||
}
|
||||
|
||||
ws.onclose = function(event) {
|
||||
document.querySelector('#disconneced').style.display = 'block'
|
||||
|
||||
window.setTimeout(createWebSocketConnection, 5000)
|
||||
}
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
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)
|
||||
} else if (data.type === 'screenshot') {
|
||||
isScreenshotWaiting = false
|
||||
screenshotImg.setAttribute('src', 'data:image/pngbase64, ' + data.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
ws.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) => {
|
||||
console.log(item.checked)
|
||||
item.checked = false
|
||||
console.log(item.checked)
|
||||
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)
|
||||
}
|
||||
|
||||
ws.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) {
|
||||
ws.send('{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}')
|
||||
}
|
||||
}
|
||||
|
||||
function textKeyUpHandler(e) {
|
||||
const keys = document.querySelector('#text').value
|
||||
|
||||
if (e.keyCode === 13) {
|
||||
ws.send('{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}')
|
||||
}
|
||||
}
|
||||
|
||||
function liveTextKeyUpHandler(e) {
|
||||
const value = e.target.value
|
||||
|
||||
if (e.keyCode === 8) {
|
||||
ws.send('{"type":"key","value": "backspace"}')
|
||||
} else if (e.keyCode === 13) {
|
||||
ws.send('{"type":"key","value": "enter"}')
|
||||
} else if (value.length) {
|
||||
if (value === ' ') {
|
||||
ws.send('{"type":"key","value": "space"}')
|
||||
} else {
|
||||
ws.send('{"type":"text","value": "' + (value.replace('"', '\\"')) + '"}')
|
||||
}
|
||||
|
||||
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) {
|
||||
ws.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
|
||||
|
||||
ws.send('{"type":"scroll","value": "' + value + '"}')
|
||||
}
|
||||
|
||||
function pointerTouchStartHandler(e) {
|
||||
const touch = e.targetTouches[0]
|
||||
mouseInitPosX = touch.pageX
|
||||
mouseInitPosY = touch.pageY
|
||||
}
|
||||
|
||||
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 liveHqClickHandler(e) {
|
||||
return liveClickHandler(e, 'hq')
|
||||
}
|
||||
|
||||
function liveLqClickHandler(e) {
|
||||
return liveClickHandler(e, 'lq')
|
||||
}
|
||||
|
||||
function liveClickHandler(e, quality) {
|
||||
if (isLive) {
|
||||
isLive = false
|
||||
isScreenshotWaiting = false
|
||||
document.querySelector('#live-hq').innerText(`Live HQ`)
|
||||
document.querySelector('#live-lq').innerText(`Live LQ`)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
isLive = true
|
||||
|
||||
e.target.innerText('Stop live')
|
||||
|
||||
let doScreenshot = function() {
|
||||
if (isLive) {
|
||||
if (!isScreenshotWaiting) {
|
||||
isScreenshotWaiting = true
|
||||
ws.send(`{"type":"screenshot","quality":"${quality}"}`)
|
||||
}
|
||||
|
||||
window.setTimeout(doScreenshot, 100)
|
||||
}
|
||||
}
|
||||
|
||||
doScreenshot()
|
||||
}
|
||||
|
||||
function fullscreenHandler(e) {
|
||||
let element = document.querySelector(e.target.getAttribute('data-target'))
|
||||
let isFullscreen = parseInt(e.target.getAttribute('data-fullscreen'))
|
||||
|
||||
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)
|
||||
addEventListenerOn('.live-text', 'keyup', liveTextKeyUpHandler)
|
||||
|
||||
addEventListenerOn(scroller, 'touchstart', scrollerTouchStartHandler)
|
||||
addEventListenerOn(scroller, 'touchmove', scrollerTouchMoveHandler)
|
||||
|
||||
addEventListenerOn(pointer, 'click', pointerClickHandler)
|
||||
addEventListenerOn(pointer, 'touchstart', pointerTouchStartHandler)
|
||||
addEventListenerOn(pointer, 'touchmove', pointerTouchMoveHandler)
|
||||
|
||||
addEventListenerOn('#live-hq', 'click', liveHqClickHandler)
|
||||
addEventListenerOn('#live-lq', 'click', liveLqClickHandler)
|
||||
addEventListenerOn('.btn-fullscreen', 'click', fullscreenHandler)
|
||||
}
|
||||
|
||||
function bootstrap() {
|
||||
pointer = document.querySelector('#pointer')
|
||||
scroller = document.querySelector('#scrollbar')
|
||||
response = document.querySelector('#response')
|
||||
screenshotImg = document.querySelector('#screenshot img')
|
||||
|
||||
shortcutsSpecialKeysOnChangeHandler()
|
||||
createWebSocketConnection()
|
||||
addListeners()
|
||||
documentHashHandler()
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/static/js/service_worker.js')
|
||||
}
|
||||
}
|
||||
|
||||
addEventListenerOn(window, 'DOMContentLoaded', bootstrap)
|
3
static/js/service_worker.js
Normal file
3
static/js/service_worker.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
self.addEventListener("install", (e) => {
|
||||
console.log("[Service Worker] Install");
|
||||
});
|
308
static/main.js
308
static/main.js
|
@ -1,308 +0,0 @@
|
|||
var ws;
|
||||
var $pointer, $scroller, $response, $screenshotImg;
|
||||
var scrollLastTimestamp, scrollLastValue;
|
||||
var mousePosX, mousePosY, mouseInitPosX, mouseInitPosY;
|
||||
var isLive = false;
|
||||
var isScreenshotWaiting = false;
|
||||
|
||||
var createWebSocketConnection = function() {
|
||||
ws = new WebSocket(`ws://${window.location.hostname}:${window.location.port}/ws`);
|
||||
|
||||
ws.onopen = function(event) {
|
||||
$('#disconneced').fadeOut();
|
||||
}
|
||||
|
||||
ws.onclose = function(event) {
|
||||
$('#disconneced').fadeIn();
|
||||
|
||||
window.setTimeout(createWebSocketConnection, 5000);
|
||||
}
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
var data = JSON.parse(event.data);
|
||||
|
||||
if (data.type === 'response') {
|
||||
$response.text(data.value);
|
||||
$response.fadeIn();
|
||||
|
||||
window.setTimeout(function() {
|
||||
$response.fadeOut();
|
||||
}, 2500);
|
||||
} else if (data.type === 'screenshot') {
|
||||
isScreenshotWaiting = false
|
||||
$screenshotImg.attr('src', 'data:image/png;base64, ' + data.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var navigationClickHandler = function(e) {
|
||||
if ($(this).attr('href') === '#') {
|
||||
return
|
||||
}
|
||||
|
||||
$('.pane').hide();
|
||||
|
||||
var target = $(this).attr('href');
|
||||
$(target).show();
|
||||
|
||||
$('#nav a').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
|
||||
var buttonClickHandler = function(e) {
|
||||
var msg = $(this).attr('data-msg');
|
||||
ws.send(msg);
|
||||
}
|
||||
|
||||
var shortcutClearClickHandler = function(e) {
|
||||
$('#shortcut-key').val('');
|
||||
$('#shortcuts_special_keys input:checked').each(function() {
|
||||
$(this).prop('checked', false).trigger('change');
|
||||
});
|
||||
}
|
||||
|
||||
var shortcutSendClickHandler = function(e) {
|
||||
var keys = [];
|
||||
|
||||
$('#shortcuts_special_keys input:checked').each(function() {
|
||||
keys.push($(this).val());
|
||||
});
|
||||
|
||||
var key = $('#shortcut-key').val();
|
||||
|
||||
if (keys.length) {
|
||||
if (key) {
|
||||
keys.push(key);
|
||||
}
|
||||
|
||||
var msg = '{"type":"keys","value": "' + (keys.join(',').replace('"', '\\"')) + '"}';
|
||||
ws.send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
var textClearClickHandler = function(e) {
|
||||
$('#text').val('');
|
||||
}
|
||||
|
||||
var textSendClickHandler = function(e) {
|
||||
var keys = $('#text').val();
|
||||
|
||||
if (keys.length) {
|
||||
var msg = '{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}';
|
||||
ws.send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
var textKeyUpHandler = function(e) {
|
||||
var keys = $('#text').val();
|
||||
|
||||
if (e.keyCode === 13) {
|
||||
var msg = '{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}';
|
||||
ws.send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
var liveTextKeyUpHandler = function(e) {
|
||||
var value = $(this).val();
|
||||
var live = false;
|
||||
|
||||
if (e.keyCode === 8) {
|
||||
var msg = '{"type":"key","value": "backspace"}';
|
||||
ws.send(msg);
|
||||
} else if (e.keyCode === 13) {
|
||||
var msg = '{"type":"key","value": "enter"}';
|
||||
ws.send(msg);
|
||||
} else if (value.length) {
|
||||
if (value === ' ') {
|
||||
var msg = '{"type":"key","value": "space"}';
|
||||
ws.send(msg);
|
||||
} else {
|
||||
var msg = '{"type":"text","value": "' + (value.replace('"', '\\"')) + '"}';
|
||||
ws.send(msg);
|
||||
}
|
||||
|
||||
$(this).val('');
|
||||
}
|
||||
}
|
||||
|
||||
var shortcutsSpecialKeysOnChangeHandler = function(e) {
|
||||
$('#shortcuts_special_keys input:checked').each(function() {
|
||||
$(this).parent().addClass('btn-primary').removeClass('btn-secondary');
|
||||
})
|
||||
|
||||
$('#shortcuts_special_keys input:not(:checked)').each(function() {
|
||||
$(this).parent().addClass('btn-secondary').removeClass('btn-primary');
|
||||
})
|
||||
}
|
||||
|
||||
var pointerClickHandler = function(e) {
|
||||
var msg = '{"type":"pointer","click":"left"}';
|
||||
ws.send(msg);
|
||||
}
|
||||
|
||||
var scrollerTouchStartHandler = function(e) {
|
||||
var touch = e.targetTouches[0];
|
||||
mouseInitPosY = touch.pageY;
|
||||
}
|
||||
|
||||
var scrollerTouchMoveHandler = function(e) {
|
||||
var touch = e.changedTouches[0];
|
||||
var value = ((touch.pageY - mouseInitPosY > 0) ? 'down' : 'up');
|
||||
var now = new Date().getTime();
|
||||
|
||||
if (touch.pageY === mouseInitPosY || value === scrollLastValue && scrollLastTimestamp !== null && now - scrollLastTimestamp < 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
scrollLastTimestamp = now;
|
||||
scrollLastValue = value;
|
||||
|
||||
var msg = '{"type":"scroll","value": "' + value + '"}';
|
||||
|
||||
mouseInitPosY = touch.pageY;
|
||||
ws.send(msg);
|
||||
}
|
||||
|
||||
var pointerTouchStartHandler = function(e) {
|
||||
var touch = e.targetTouches[0];
|
||||
mouseInitPosX = touch.pageX;
|
||||
mouseInitPosY = touch.pageY;
|
||||
}
|
||||
|
||||
var pointerTouchMoveHandler = function(e) {
|
||||
if (e.changedTouches.length === 2) {
|
||||
return scrollerTouchMoveHandler(e);
|
||||
}
|
||||
|
||||
var touch = e.changedTouches[0];
|
||||
mousePosX = touch.pageX;
|
||||
mousePosY = touch.pageY;
|
||||
|
||||
var newX = mousePosX - mouseInitPosX;
|
||||
var newY = mousePosY - mouseInitPosY;
|
||||
|
||||
mouseInitPosX = mousePosX;
|
||||
mouseInitPosY = mousePosY;
|
||||
|
||||
var msg = '{"type":"pointer","x": "' + newX + '","y": "' + newY + '"}';
|
||||
|
||||
ws.send(msg);
|
||||
}
|
||||
|
||||
var liveHqClickHandler = function(e) {
|
||||
return liveClickHandler(e, 'hq')
|
||||
}
|
||||
|
||||
var liveLqClickHandler = function(e) {
|
||||
return liveClickHandler(e, 'lq')
|
||||
}
|
||||
|
||||
var liveClickHandler = function(e, quality) {
|
||||
if (isLive) {
|
||||
isLive = false;
|
||||
isScreenshotWaiting = false;
|
||||
$('#live-hq').text(`Live HQ`);
|
||||
$('#live-lq').text(`Live LQ`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
isLive = true;
|
||||
$(e.target).text('Stop live');
|
||||
|
||||
var doScreenshot = function() {
|
||||
if (isLive) {
|
||||
if (!isScreenshotWaiting) {
|
||||
isScreenshotWaiting = true
|
||||
ws.send(`{"type":"screenshot","quality":"${quality}"}`);
|
||||
}
|
||||
|
||||
window.setTimeout(doScreenshot, 100);
|
||||
}
|
||||
}
|
||||
|
||||
doScreenshot();
|
||||
}
|
||||
|
||||
var fullscreenHandler = function(e) {
|
||||
var element = $(e.target.getAttribute('data-target'));
|
||||
var isFullscreen = parseInt($(e.target).attr('data-fullscreen'));
|
||||
|
||||
$('body').toggleClass('fullscreen', isFullscreen)
|
||||
|
||||
if (isFullscreen) {
|
||||
element.attr('data-fullscreen', '0');
|
||||
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
}
|
||||
} else {
|
||||
$(e.target).attr('data-fullscreen', '1');
|
||||
|
||||
if (element.get(0).requestFullscreen) {
|
||||
element.get(0).requestFullscreen();
|
||||
} else if (element.get(0).webkitRequestFullscreen) {
|
||||
element.get(0).webkitRequestFullscreen();
|
||||
} else if (element.get(0).mozRequestFullScreen) {
|
||||
element.get(0).mozRequestFullScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var documentHashHandler = function() {
|
||||
var hash = window.location.hash;
|
||||
|
||||
if (hash) {
|
||||
$('a[href="' + hash + '"]').click();
|
||||
} else {
|
||||
$('#nav > li:first-child a').click();
|
||||
}
|
||||
}
|
||||
|
||||
var addListeners = function() {
|
||||
$('#nav a').click(navigationClickHandler);
|
||||
$('button[data-msg]').click(buttonClickHandler);
|
||||
|
||||
$('#shortcut-clear').click(shortcutClearClickHandler);
|
||||
$('#shortcuts_special_keys input').change(shortcutsSpecialKeysOnChangeHandler);
|
||||
$('#shortcut-send').click(shortcutSendClickHandler);
|
||||
|
||||
$('#text-clear').click(textClearClickHandler);
|
||||
$('#text-send').click(textSendClickHandler);
|
||||
$('#text').on('keyup', textKeyUpHandler);
|
||||
$('.live-text').on('keyup', liveTextKeyUpHandler);
|
||||
|
||||
$scroller
|
||||
.on('touchstart', scrollerTouchStartHandler)
|
||||
.on('touchmove', scrollerTouchMoveHandler);
|
||||
|
||||
$pointer
|
||||
.on('click', pointerClickHandler)
|
||||
.on('touchstart', pointerTouchStartHandler)
|
||||
.on('touchmove', pointerTouchMoveHandler);
|
||||
|
||||
$('#live-hq').click(liveHqClickHandler);
|
||||
$('#live-lq').click(liveLqClickHandler);
|
||||
|
||||
$('.btn-fullscreen').click(fullscreenHandler)
|
||||
}
|
||||
|
||||
var bootstrap = function() {
|
||||
shortcutsSpecialKeysOnChangeHandler();
|
||||
createWebSocketConnection();
|
||||
addListeners();
|
||||
documentHashHandler();
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$pointer = $('#pointer');
|
||||
$scroller = $('#scrollbar');
|
||||
$response = $('#response');
|
||||
$screenshotImg = $('#screenshot img');
|
||||
|
||||
bootstrap();
|
||||
});
|
17
static/manifest.json
Normal file
17
static/manifest.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"short_name": "RWM",
|
||||
"name": "Remote i3-wm",
|
||||
"theme_color": "#1e3650",
|
||||
"background_color": "#ffffff",
|
||||
"display": "fullscreen",
|
||||
"Scope": "/",
|
||||
"orientation": "portrait",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/img/icon.png",
|
||||
"type": "image/png",
|
||||
"sizes": "96x96"
|
||||
}
|
||||
],
|
||||
"start_url": "/"
|
||||
}
|
|
@ -4,8 +4,10 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
|
||||
<link rel="stylesheet" href="/static/bootstrap.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="/static/main.css" type="text/css">
|
||||
<link rel="stylesheet" href="/static/css/bootstrap.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="/static/css/main.css" type="text/css">
|
||||
<link rel="manifest" href="/static/manifest.json">
|
||||
<link rel="icon" type="image/png" href="/static/img/icon.png">
|
||||
<title>Remote i3-wm</title>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -17,10 +19,7 @@
|
|||
|
||||
<div id="response"></div>
|
||||
|
||||
<script src="/static/jquery.min.js"></script>
|
||||
<script src="/static/bootstrap.bundle.min.js"></script>
|
||||
<script src="/static/bootstrap.min.js"></script>
|
||||
<script src="/static/main.js"></script>
|
||||
<script src="/static/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
|
|
Loading…
Reference in a new issue