Skip to content

Commit

Permalink
deploy: 2a69e22
Browse files Browse the repository at this point in the history
  • Loading branch information
ilc committed Aug 18, 2024
0 parents commit 1835a8b
Show file tree
Hide file tree
Showing 7 changed files with 306,203 additions and 0 deletions.
Empty file added .nojekyll
Empty file.
Binary file added icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
282 changes: 282 additions & 0 deletions index.html
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>
Loading

0 comments on commit 1835a8b

Please sign in to comment.