forked from vial-kb/vial-gui
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1835a8b
Showing
7 changed files
with
306,203 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,282 @@ | ||
<head> | ||
<title>Vial Web</title> | ||
<link rel="icon" href="/icon.png" type="image/png"> | ||
<style> | ||
body { | ||
font-family: sans-serif; | ||
margin: 0; | ||
padding: 0; | ||
background-color: #ccc; | ||
overscroll-behavior-y: none; | ||
} | ||
|
||
#canvas { | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
#startup { | ||
position: fixed; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
z-index: 90; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
text-align: center; | ||
} | ||
|
||
#startup_btn { | ||
font-size: 250%; | ||
padding: 1em; | ||
} | ||
|
||
#version { | ||
position: absolute; | ||
right: 0; | ||
bottom: 0; | ||
margin: 1em; | ||
color: #aaa; | ||
text-align: right; | ||
} | ||
|
||
#unlock { | ||
position: fixed; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
z-index: 100; | ||
background-color: rgba(0, 0, 0, 0.5); | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
} | ||
|
||
#unlock_status { | ||
width: 90%; | ||
height: 2em; | ||
} | ||
|
||
#unlock_inner { | ||
background-color: #454545; | ||
color: white; | ||
padding: 1em; | ||
border-radius: 1em; | ||
width: 30%; | ||
text-align: center; | ||
} | ||
|
||
#error_msg { | ||
color: red; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
|
||
<div id="startup"> | ||
<div id="startup_inner"> | ||
<input id="startup_btn" type="button" onclick="connect()" value="Start Vial" disabled="true" /><br> | ||
<div id="error" style="display:none"> | ||
<p id="error_msg"></p> | ||
<p>You can check web browser support at <a href="https://caniuse.com/webhid" | ||
target="_blank">caniuse.com</a>.<br> | ||
Latest versions of Chrome, Chromium or Edge are recommended to use Vial Web.<br> | ||
You can also download the standalone Vial application from <a href="https://get.vial.today/" | ||
target="_blank">get.vial.today</a>.</p> | ||
</div> | ||
</div> | ||
<div id="version">Vial: 2a69e22302625a8b0c0aa900093f2d8a1632f66f<br>Web: 2a69e22302625a8b0c0aa900093f2d8a1632f66f<br>Support: UNKNOWN</div> | ||
</div> | ||
|
||
<div id="unlock" style="display:none"> | ||
<div id="unlock_inner"> | ||
<p>In order to proceed, the keyboard must be set into unlocked mode. You should only perform this operation | ||
on computers that you trust.</p> | ||
<p>To exit this mode, you will need to replug the keyboard or select Security->Lock from the menu.</p> | ||
<p>Press and hold the following keys until the progress bar below fills up:</p> | ||
<p><img id="unlock_img"></p> | ||
<p><progress id="unlock_status" value="0" max="1"></progress></p> | ||
</div> | ||
</div> | ||
|
||
<canvas id="canvas" oncontextmenu="return false;" tabindex="-1"></canvas> | ||
|
||
<script> | ||
var Module = {}; | ||
Module.canvas = document.getElementById("canvas"); | ||
Module.qtCanvasElements = [Module.canvas]; | ||
|
||
function read_timeout() { | ||
console.log("device read timed out!"); | ||
_vialglue_set_response_error(); | ||
} | ||
|
||
function my_onmessage(e) { | ||
if (e.data.cmd == "write_device") { | ||
g_device.sendReport(0, new Uint8Array(e.data.data)); | ||
g_read_timeout = setTimeout(read_timeout, 500); | ||
} else if (e.data.cmd == "unlock_start") { | ||
var u8 = new Uint8Array(e.data.data); | ||
var blob = new Blob([u8], { 'type': 'image/png' }); | ||
var url = URL.createObjectURL(blob); | ||
var us = document.getElementById("unlock_status"); | ||
us.max = 1; | ||
us.value = 0; | ||
var img = document.getElementById("unlock_img"); | ||
img.src = url; | ||
img.style.width = Math.round(e.data.width / window.devicePixelRatio) + "px"; | ||
img.style.height = Math.round(e.data.height / window.devicePixelRatio) + "px"; | ||
document.getElementById("unlock_inner").style.minWidth = img.style.width; | ||
document.getElementById("unlock").style.display = ""; | ||
} else if (e.data.cmd == "unlock_status") { | ||
var us = document.getElementById("unlock_status"); | ||
us.max = Math.max(us.max, e.data.data); | ||
us.value = us.max - e.data.data; | ||
} else if (e.data.cmd == "unlock_done") { | ||
document.getElementById("unlock").style.display = "none"; | ||
} else if (e.data.cmd == "notify_ready") { | ||
clearInterval(g_animation); | ||
document.getElementById("startup").style.display = "none"; | ||
} else if (e.data.cmd == "notify_alive") { | ||
document.getElementById("startup_btn").disabled = false; | ||
} else if (e.data.cmd == "load_layout") { | ||
loadLayout(); | ||
} else if (e.data.cmd == "save_layout") { | ||
saveLayout(e.data.layout); | ||
} else if (e.data.cmd == "fatal_error") { | ||
alert(e.data.msg); | ||
} | ||
} | ||
|
||
const FILE_OPTIONS = { | ||
types: [ | ||
{ | ||
description: "Vial layout", | ||
accept: { "application/json": [".vil"] }, | ||
}, | ||
], | ||
excludeAcceptAllOption: false, | ||
multiple: false, | ||
}; | ||
|
||
async function loadLayout() { | ||
if (!window.showOpenFilePicker) { | ||
alert("File loading API unavailable. Please use a newer browser."); | ||
return; | ||
} | ||
|
||
const [handle] = await window.showOpenFilePicker(FILE_OPTIONS); | ||
|
||
if (!handle) { | ||
return; | ||
} | ||
|
||
const file = await handle.getFile(); | ||
const layout = await file.text(); | ||
|
||
PThread.runningWorkers[0].postMessage({ | ||
cmd: "py", | ||
payload: `import webmain;webmain.window.on_layout_loaded(b${JSON.stringify(layout)})`, | ||
}); | ||
} | ||
|
||
async function saveLayout(layout) { | ||
if (window.showSaveFilePicker) { | ||
// This shows a file chooser dialog. It's a nicer experience | ||
// if available, allowing the user to select a target | ||
// filename and directory. | ||
const handle = await window.showSaveFilePicker(FILE_OPTIONS); | ||
const stream = await handle.createWritable(); | ||
await stream.write(layout); | ||
await stream.close(); | ||
} else { | ||
// If the File System API isn't available, we can at least | ||
// trigger a simple download with a hardcoded filename. | ||
const download = document.createElement('a'); | ||
download.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(layout)); | ||
download.setAttribute('download', 'layout.vil'); | ||
|
||
if (document.createEvent) { | ||
var event = document.createEvent('MouseEvents'); | ||
event.initEvent('click', true, true); | ||
download.dispatchEvent(event); | ||
} else { | ||
download.click(); | ||
} | ||
} | ||
} | ||
|
||
async function connect() { | ||
var btn = document.getElementById("startup_btn"); | ||
|
||
btn.disabled = true; | ||
btn.value = "Requesting device list..."; | ||
devices = await navigator.hid.requestDevice({ filters: [{ usagePage: 0xFF60, usage: 0x61 }] }); | ||
if (devices.length != 1) { | ||
btn.value = "Start Vial"; | ||
btn.disabled = false; | ||
return; | ||
} | ||
btn.value = "Connecting to the device..."; | ||
await devices[0].open(); | ||
devices[0].oninputreport = function (ev) { | ||
clearTimeout(g_read_timeout); | ||
var ptr = _malloc(32); | ||
for (var i = 0; i < 32; ++i) { | ||
setValue(ptr + i, ev.data.getUint8(i), "i8"); | ||
} | ||
_vialglue_set_response(ptr); | ||
_free(ptr); | ||
} | ||
|
||
g_device = devices[0]; | ||
var device_desc = { | ||
path: "/webhid", | ||
vendor_id: g_device.vendorId, | ||
product_id: g_device.productId, | ||
serial_number: "", | ||
release_number: 1, | ||
manufacturer_string: "", | ||
product_string: g_device.productName, | ||
usage_page: 65376, | ||
usage: 97, | ||
interface_number: 1 | ||
}; | ||
_vialglue_set_device_desc(allocateUTF8(JSON.stringify(device_desc))); | ||
|
||
btn.value = "Starting up...."; | ||
PThread.runningWorkers[0].postMessage({ cmd: "py", payload: "import webmain;webmain.main(qtApp)" }); | ||
|
||
g_animation = setInterval(update_animation, 500); | ||
g_animation_counter = 0; | ||
} | ||
|
||
function update_animation() { | ||
g_animation_counter = (g_animation_counter + 1) % 5; | ||
document.getElementById("startup_btn").value = "Starting up" + ".".repeat(g_animation_counter + 1); | ||
} | ||
|
||
function show_error(e) { | ||
document.getElementById("startup_btn").style.display = "none"; | ||
document.getElementById("error").style.display = ""; | ||
document.getElementById("error_msg").innerHTML = e; | ||
} | ||
|
||
if (!("hid" in navigator)) { | ||
show_error("Your web browser does not support WebHID"); | ||
} else if (!HTMLCanvasElement.prototype.transferControlToOffscreen) { | ||
show_error("Your web browser does not support OffscreenCanvas"); | ||
} | ||
|
||
window.onerror = function (message, source, lineno, colno, error) { | ||
alert(message); | ||
}; | ||
</script> | ||
|
||
<script src="main-080193360590c1f7ffedea1e766bf950dbf213cfb12be9223c75c194275e07e2.js"></script> | ||
|
||
</body> |
Oops, something went wrong.