mirror of
https://github.com/4yn/slidershim.git
synced 2025-02-13 00:54:41 +01:00
better brokenithm
This commit is contained in:
parent
fcf80538b4
commit
cc24e628aa
@ -12,7 +12,7 @@ body {
|
|||||||
color: #ddd;
|
color: #ddd;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
font-size: 1rem;
|
/* font-size: 1rem; */
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,20 +23,49 @@ pre {
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
border: 0.125rem solid #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* titlebar */
|
||||||
|
|
||||||
|
.titlebar {
|
||||||
|
user-select: none;
|
||||||
|
background: #333;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-icon {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-icon img {
|
||||||
|
max-height: 1.5rem;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main */
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
|
margin-top: 2rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column nowrap;
|
flex-flow: column nowrap;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row,
|
.row,
|
||||||
.row-2 {
|
.row-2 {
|
||||||
margin: 0 0 0.5rem 0;
|
margin: 0 0 0.5rem 0;
|
||||||
@ -50,6 +79,14 @@ body {
|
|||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row .label[title] {
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row .label[title]:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.row .input {
|
.row .input {
|
||||||
flex: 2 2 0;
|
flex: 2 2 0;
|
||||||
}
|
}
|
||||||
@ -58,9 +95,7 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 5rem;
|
max-height: 5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
font-size: 0.75rem;
|
||||||
.serverlist > pre {
|
|
||||||
font-size: 0.75em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
@ -69,6 +104,7 @@ select {
|
|||||||
background-color: #444;
|
background-color: #444;
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
border: none;
|
border: none;
|
||||||
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@ -92,6 +128,8 @@ button.primary {
|
|||||||
background: rgb(35, 67, 211);
|
background: rgb(35, 67, 211);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Preview */
|
||||||
|
|
||||||
.preview {
|
.preview {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -107,6 +145,9 @@ button.primary {
|
|||||||
flex-flow: column-reverse nowrap;
|
flex-flow: column-reverse nowrap;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
border-radius: 0.5rem 0.5rem 0 0;
|
||||||
|
overflow: clip;
|
||||||
}
|
}
|
||||||
.air-data {
|
.air-data {
|
||||||
flex: 1 0;
|
flex: 1 0;
|
||||||
@ -121,6 +162,9 @@ button.primary {
|
|||||||
.ground {
|
.ground {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
|
|
||||||
|
border-radius: 0 0 0.5rem 0.5rem;
|
||||||
|
overflow: clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ground-btn,
|
.ground-btn,
|
||||||
@ -176,7 +220,7 @@ button.primary {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
justify-content: flex-start;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.extra-data {
|
.extra-data {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
|
BIN
public/icon.png
Normal file
BIN
public/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
@ -1,18 +1,24 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset='utf-8'>
|
<meta charset="utf-8" />
|
||||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
|
||||||
<title>Svelte app</title>
|
<title>Svelte app</title>
|
||||||
|
|
||||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||||
<link rel='stylesheet' href='/global.css'>
|
<link rel="stylesheet" href="/global.css" />
|
||||||
<link rel='stylesheet' href='/build/bundle.css'>
|
<link rel="stylesheet" href="/build/bundle.css" />
|
||||||
|
|
||||||
<script defer src='/build/bundle.js'></script>
|
<script defer src="/build/bundle.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
</body>
|
<div data-tauri-drag-region class="titlebar">
|
||||||
|
<div data-tauri-drag-region class="header-icon">
|
||||||
|
<img src="/icon.png" />
|
||||||
|
</div>
|
||||||
|
<div data-tauri-drag-region class="header"> slidershim</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
64
res/sshelper/index.html
Normal file
64
res/sshelper/index.html
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
max-width: 650px;
|
||||||
|
margin: 40px auto;
|
||||||
|
padding: 0 10px;
|
||||||
|
font: 18px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
|
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
|
||||||
|
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
body {
|
||||||
|
color: #ccc;
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
a:link {
|
||||||
|
color: #5bf;
|
||||||
|
}
|
||||||
|
a:visited {
|
||||||
|
color: #ccf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<title>brokenithm-qr</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>slidershim brokenithm helper</h1>
|
||||||
|
<ul class="links"></ul>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
const search = window.location.search;
|
||||||
|
if (search.slice(0, 3) !== "?d=" || search.length <= 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const ul = document.querySelector(".links");
|
||||||
|
search
|
||||||
|
.slice(3)
|
||||||
|
.split(";")
|
||||||
|
.map((x) => atob(x))
|
||||||
|
.forEach((ip) => {
|
||||||
|
const li = document.createElement("li");
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.innerText = ip;
|
||||||
|
a.setAttribute("target", "_blank");
|
||||||
|
a.setAttribute("rel", "noopener");
|
||||||
|
a.href = `http://${ip}:1606/`;
|
||||||
|
li.appendChild(a);
|
||||||
|
ul.appendChild(li);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
104
src-tauri/Cargo.lock
generated
104
src-tauri/Cargo.lock
generated
@ -225,6 +225,12 @@ version = "3.9.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
|
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@ -328,6 +334,12 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "checked_int_cast"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cocoa"
|
name = "cocoa"
|
||||||
version = "0.24.0"
|
version = "0.24.0"
|
||||||
@ -359,6 +371,12 @@ dependencies = [
|
|||||||
"objc",
|
"objc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "com"
|
name = "com"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -1073,6 +1091,16 @@ dependencies = [
|
|||||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gif"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
|
||||||
|
dependencies = [
|
||||||
|
"color_quant",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gio"
|
name = "gio"
|
||||||
version = "0.14.8"
|
version = "0.14.8"
|
||||||
@ -1433,6 +1461,25 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.23.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"color_quant",
|
||||||
|
"gif",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png 0.16.8",
|
||||||
|
"scoped_threadpool",
|
||||||
|
"tiff",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@ -1537,6 +1584,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-decoder"
|
||||||
|
version = "0.1.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
|
||||||
|
dependencies = [
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.56"
|
version = "0.3.56"
|
||||||
@ -1872,6 +1928,17 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
@ -2357,6 +2424,16 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "qrcode"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f"
|
||||||
|
dependencies = [
|
||||||
|
"checked_int_cast",
|
||||||
|
"image",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
@ -2649,6 +2726,12 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped_threadpool"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -2853,15 +2936,19 @@ name = "slidershim"
|
|||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"base64",
|
||||||
"directories",
|
"directories",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
|
"image",
|
||||||
"ipconfig",
|
"ipconfig",
|
||||||
"log",
|
"log",
|
||||||
|
"open",
|
||||||
"palette",
|
"palette",
|
||||||
"path-clean",
|
"path-clean",
|
||||||
|
"qrcode",
|
||||||
"rusb",
|
"rusb",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -3336,6 +3423,17 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
|
||||||
|
dependencies = [
|
||||||
|
"jpeg-decoder",
|
||||||
|
"miniz_oxide 0.4.4",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
@ -3805,6 +3903,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "widestring"
|
name = "widestring"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -20,6 +20,7 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
env_logger = "0.9.0"
|
env_logger = "0.9.0"
|
||||||
simple-logging = "2.0.2"
|
simple-logging = "2.0.2"
|
||||||
|
open = "2.0.2"
|
||||||
tauri = { version = "1.0.0-beta.8", features = ["shell-open", "system-tray"] }
|
tauri = { version = "1.0.0-beta.8", features = ["shell-open", "system-tray"] }
|
||||||
|
|
||||||
futures = "0.3.19"
|
futures = "0.3.19"
|
||||||
@ -37,6 +38,9 @@ winapi = "0.3.9"
|
|||||||
ipconfig = "0.3.0"
|
ipconfig = "0.3.0"
|
||||||
|
|
||||||
hyper = { version="0.14.16", features= ["server", "http1", "http2", "tcp", "stream", "runtime"] }
|
hyper = { version="0.14.16", features= ["server", "http1", "http2", "tcp", "stream", "runtime"] }
|
||||||
|
base64 = "0.13.0"
|
||||||
|
image = "0.23.14"
|
||||||
|
qrcode = { version="0.12.0", features= ["image"] }
|
||||||
path-clean = "0.1.0"
|
path-clean = "0.1.0"
|
||||||
tungstenite = { version="0.16.0", default-features=false }
|
tungstenite = { version="0.16.0", default-features=false }
|
||||||
tokio-tungstenite = "0.16.1"
|
tokio-tungstenite = "0.16.1"
|
||||||
|
File diff suppressed because one or more lines are too long
@ -67,6 +67,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
|
-ms-interpolation-mode: nearest-neighbor;
|
||||||
|
image-rendering: crisp-edges;
|
||||||
|
image-rendering: pixelated;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
margin: 0px -1.5625vw;
|
margin: 0px -1.5625vw;
|
||||||
}
|
}
|
||||||
@ -112,6 +115,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/config.js"></script>
|
<script src="/config.js"></script>
|
||||||
<script src="/app.js"></script>
|
<script src="/src.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -66,6 +66,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
|
-ms-interpolation-mode: nearest-neighbor;
|
||||||
|
image-rendering: crisp-edges;
|
||||||
|
image-rendering: pixelated;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
margin: 0px -1.5625vw;
|
margin: 0px -1.5625vw;
|
||||||
}
|
}
|
||||||
@ -111,6 +114,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/config.js"></script>
|
<script src="/config.js"></script>
|
||||||
<script src="/app.js"></script>
|
<script src="/src.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -236,15 +236,18 @@ const setupLed = () => {
|
|||||||
setupLed();
|
setupLed();
|
||||||
const updateLed = (data) => {
|
const updateLed = (data) => {
|
||||||
const buf = new Uint8Array(data);
|
const buf = new Uint8Array(data);
|
||||||
for (var i = 0; i < 32; i++) {
|
for (var i = 0; i < 31; i++) {
|
||||||
canvasData.data[i * 4] = buf[(31 - i) * 3 + 1]; // r
|
canvasData.data[i * 4 + 4] = buf[i * 3]; // r
|
||||||
canvasData.data[i * 4 + 1] = buf[(31 - i) * 3 + 2]; // g
|
canvasData.data[i * 4 + 5] = buf[i * 3 + 1]; // g
|
||||||
canvasData.data[i * 4 + 2] = buf[(31 - i) * 3 + 0]; // b
|
canvasData.data[i * 4 + 6] = buf[i * 3 + 2]; // b
|
||||||
}
|
}
|
||||||
// Copy from first led
|
canvasData.data[0] = buf[0]
|
||||||
canvasData.data[128] = buf[94];
|
canvasData.data[1] = buf[1]
|
||||||
canvasData.data[129] = buf[95];
|
canvasData.data[2] = buf[2]
|
||||||
canvasData.data[130] = buf[93];
|
canvasData.data[128] = buf[90];
|
||||||
|
canvasData.data[129] = buf[91];
|
||||||
|
canvasData.data[130] = buf[92];
|
||||||
|
|
||||||
canvasCtx.putImageData(canvasData, 0, 0);
|
canvasCtx.putImageData(canvasData, 0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ mod slider_io;
|
|||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
// use env_logger;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use tauri::{
|
use tauri::{
|
||||||
@ -32,9 +31,18 @@ fn quit_app() {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Setup logger
|
// Setup logger
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
env_logger::Builder::new()
|
||||||
|
.filter_level(log::LevelFilter::Debug)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
{
|
||||||
let log_file_path = slider_io::Config::get_log_file_path().unwrap();
|
let log_file_path = slider_io::Config::get_log_file_path().unwrap();
|
||||||
simple_logging::log_to_file(log_file_path.as_path(), log::LevelFilter::Debug).unwrap();
|
simple_logging::log_to_file(log_file_path.as_path(), log::LevelFilter::Debug).unwrap();
|
||||||
// simple_logging::log_to_file("./log.txt", log::LevelFilter::Debug).unwrap();
|
// simple_logging::log_to_file("./log.txt", log::LevelFilter::Debug).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let config = Arc::new(Mutex::new(Some(slider_io::Config::default())));
|
let config = Arc::new(Mutex::new(Some(slider_io::Config::default())));
|
||||||
let manager = Arc::new(Mutex::new(slider_io::Manager::new()));
|
let manager = Arc::new(Mutex::new(slider_io::Manager::new()));
|
||||||
@ -92,6 +100,22 @@ fn main() {
|
|||||||
quit_app();
|
quit_app();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Show logs
|
||||||
|
app.listen_global("openLogfile", |_| {
|
||||||
|
let log_file_path = slider_io::Config::get_log_file_path();
|
||||||
|
if let Some(log_file_path) = log_file_path {
|
||||||
|
open::that(log_file_path.as_path()).ok();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show brokenithm qr
|
||||||
|
app.listen_global("openBrokenithmQr", |_| {
|
||||||
|
let brokenithm_qr_path = slider_io::Config::get_brokenithm_qr_path();
|
||||||
|
if let Some(brokenithm_qr_path) = brokenithm_qr_path {
|
||||||
|
open::that(brokenithm_qr_path.as_path()).ok();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// UI ready event
|
// UI ready event
|
||||||
let app_handle = app.handle();
|
let app_handle = app.handle();
|
||||||
let config_clone = Arc::clone(&config);
|
let config_clone = Arc::clone(&config);
|
||||||
@ -109,11 +133,6 @@ fn main() {
|
|||||||
if let Ok(ips) = ips {
|
if let Ok(ips) = ips {
|
||||||
app_handle.emit_all("listIps", &ips).unwrap();
|
app_handle.emit_all("listIps", &ips).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_file_path = slider_io::Config::get_log_file_path().unwrap();
|
|
||||||
app_handle
|
|
||||||
.emit_all("updateLogPath", log_file_path.as_path().to_str().unwrap())
|
|
||||||
.unwrap();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// UI update event
|
// UI update event
|
||||||
|
@ -10,7 +10,12 @@ use hyper::{
|
|||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use path_clean::PathClean;
|
use path_clean::PathClean;
|
||||||
use std::{convert::Infallible, env::current_exe, future::Future, net::SocketAddr};
|
use std::{convert::Infallible, env::current_exe, future::Future, net::SocketAddr};
|
||||||
use tokio::fs::File;
|
use tokio::{
|
||||||
|
fs::File,
|
||||||
|
select,
|
||||||
|
sync::mpsc,
|
||||||
|
time::{sleep, Duration},
|
||||||
|
};
|
||||||
use tokio_tungstenite::WebSocketStream;
|
use tokio_tungstenite::WebSocketStream;
|
||||||
use tokio_util::codec::{BytesCodec, FramedRead};
|
use tokio_util::codec::{BytesCodec, FramedRead};
|
||||||
use tungstenite::{handshake, Message};
|
use tungstenite::{handshake, Message};
|
||||||
@ -51,6 +56,30 @@ async fn serve_file(path: &str) -> Result<Response<Body>, Infallible> {
|
|||||||
async fn handle_brokenithm(ws_stream: WebSocketStream<Upgraded>, state: FullState) {
|
async fn handle_brokenithm(ws_stream: WebSocketStream<Upgraded>, state: FullState) {
|
||||||
let (mut ws_write, mut ws_read) = ws_stream.split();
|
let (mut ws_write, mut ws_read) = ws_stream.split();
|
||||||
|
|
||||||
|
let (msg_write, mut msg_read) = mpsc::unbounded_channel::<Message>();
|
||||||
|
|
||||||
|
let write_task = async move {
|
||||||
|
// info!("Websocket write task open");
|
||||||
|
loop {
|
||||||
|
match msg_read.recv().await {
|
||||||
|
Some(msg) => match ws_write.send(msg).await.ok() {
|
||||||
|
Some(_) => {}
|
||||||
|
None => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// info!("Websocket write task done");
|
||||||
|
};
|
||||||
|
|
||||||
|
let msg_write_handle = msg_write.clone();
|
||||||
|
let state_handle = state.clone();
|
||||||
|
let read_task = async move {
|
||||||
|
// info!("Websocket read task open");
|
||||||
loop {
|
loop {
|
||||||
match ws_read.next().await {
|
match ws_read.next().await {
|
||||||
Some(msg) => match msg {
|
Some(msg) => match msg {
|
||||||
@ -60,10 +89,9 @@ async fn handle_brokenithm(ws_stream: WebSocketStream<Upgraded>, state: FullStat
|
|||||||
let head = chars.next().unwrap();
|
let head = chars.next().unwrap();
|
||||||
match head {
|
match head {
|
||||||
'a' => {
|
'a' => {
|
||||||
ws_write
|
msg_write_handle
|
||||||
.send(Message::Text("alive".to_string()))
|
.send(Message::Text("alive".to_string()))
|
||||||
.await
|
.ok();
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
'b' => {
|
'b' => {
|
||||||
let flat_state: Vec<bool> = chars
|
let flat_state: Vec<bool> = chars
|
||||||
@ -73,7 +101,7 @@ async fn handle_brokenithm(ws_stream: WebSocketStream<Upgraded>, state: FullStat
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let mut controller_state_handle = state.controller_state.lock().unwrap();
|
let mut controller_state_handle = state_handle.controller_state.lock().unwrap();
|
||||||
for (idx, c) in flat_state[0..32].iter().enumerate() {
|
for (idx, c) in flat_state[0..32].iter().enumerate() {
|
||||||
controller_state_handle.ground_state[idx] = match c {
|
controller_state_handle.ground_state[idx] = match c {
|
||||||
false => 0,
|
false => 0,
|
||||||
@ -86,10 +114,6 @@ async fn handle_brokenithm(ws_stream: WebSocketStream<Upgraded>, state: FullStat
|
|||||||
true => 1,
|
true => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// println!(
|
|
||||||
// "{:?} {:?}",
|
|
||||||
// controller_state_handle.ground_state, controller_state_handle.air_state
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
break;
|
break;
|
||||||
@ -112,6 +136,31 @@ async fn handle_brokenithm(ws_stream: WebSocketStream<Upgraded>, state: FullStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// info!("Websocket read task done");
|
||||||
|
};
|
||||||
|
|
||||||
|
let msg_write_handle = msg_write.clone();
|
||||||
|
let state_handle = state.clone();
|
||||||
|
let led_task = async move {
|
||||||
|
loop {
|
||||||
|
let mut led_data = vec![0; 93];
|
||||||
|
{
|
||||||
|
let led_state_handle = state_handle.led_state.lock().unwrap();
|
||||||
|
(&mut led_data).copy_from_slice(&led_state_handle.led_state);
|
||||||
|
}
|
||||||
|
msg_write_handle.send(Message::Binary(led_data)).ok();
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(50)).await;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("Websocket handling");
|
||||||
|
select! {
|
||||||
|
_ = read_task => {}
|
||||||
|
_ = write_task => {}
|
||||||
|
_ = led_task => {}
|
||||||
|
};
|
||||||
|
info!("Websocket done");
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_websocket(
|
async fn handle_websocket(
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
|
use image::Luma;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
use qrcode::QrCode;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{convert::TryFrom, fs, path::PathBuf};
|
use std::{convert::TryFrom, fs, path::PathBuf};
|
||||||
|
|
||||||
|
use crate::slider_io::utils::list_ips;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum DeviceMode {
|
pub enum DeviceMode {
|
||||||
None,
|
None,
|
||||||
@ -12,6 +16,38 @@ pub enum DeviceMode {
|
|||||||
Brokenithm { ground_only: bool },
|
Brokenithm { ground_only: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum OutputPolling {
|
||||||
|
Sixty,
|
||||||
|
Hundred,
|
||||||
|
ThreeHundred,
|
||||||
|
FiveHundred,
|
||||||
|
Thousand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputPolling {
|
||||||
|
pub fn from_str(s: &str) -> Option<Self> {
|
||||||
|
match s {
|
||||||
|
"60" => Some(OutputPolling::Sixty),
|
||||||
|
"100" => Some(OutputPolling::Hundred),
|
||||||
|
"330" => Some(OutputPolling::ThreeHundred),
|
||||||
|
"500" => Some(OutputPolling::FiveHundred),
|
||||||
|
"1000" => Some(OutputPolling::Thousand),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_t_u64(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
OutputPolling::Sixty => 16,
|
||||||
|
OutputPolling::Hundred => 10,
|
||||||
|
OutputPolling::ThreeHundred => 3,
|
||||||
|
OutputPolling::FiveHundred => 2,
|
||||||
|
OutputPolling::Thousand => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum KeyboardLayout {
|
pub enum KeyboardLayout {
|
||||||
Tasoller,
|
Tasoller,
|
||||||
@ -31,14 +67,17 @@ pub enum OutputMode {
|
|||||||
None,
|
None,
|
||||||
Keyboard {
|
Keyboard {
|
||||||
layout: KeyboardLayout,
|
layout: KeyboardLayout,
|
||||||
|
polling: OutputPolling,
|
||||||
sensitivity: u8,
|
sensitivity: u8,
|
||||||
},
|
},
|
||||||
Gamepad {
|
Gamepad {
|
||||||
layout: GamepadLayout,
|
layout: GamepadLayout,
|
||||||
|
polling: OutputPolling,
|
||||||
sensitivity: u8,
|
sensitivity: u8,
|
||||||
},
|
},
|
||||||
Websocket {
|
Websocket {
|
||||||
url: String,
|
url: String,
|
||||||
|
polling: OutputPolling,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,30 +131,37 @@ impl Config {
|
|||||||
"none" => OutputMode::None,
|
"none" => OutputMode::None,
|
||||||
"kb-32-tasoller" => OutputMode::Keyboard {
|
"kb-32-tasoller" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::Tasoller,
|
layout: KeyboardLayout::Tasoller,
|
||||||
|
polling: OutputPolling::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
},
|
},
|
||||||
"kb-32-yuancon" => OutputMode::Keyboard {
|
"kb-32-yuancon" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::Yuancon,
|
layout: KeyboardLayout::Yuancon,
|
||||||
|
polling: OutputPolling::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
},
|
},
|
||||||
"kb-8-deemo" => OutputMode::Keyboard {
|
"kb-8-deemo" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::Deemo,
|
layout: KeyboardLayout::Deemo,
|
||||||
|
polling: OutputPolling::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
},
|
},
|
||||||
"kb-voltex" => OutputMode::Keyboard {
|
"kb-voltex" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::Voltex,
|
layout: KeyboardLayout::Voltex,
|
||||||
|
polling: OutputPolling::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
},
|
},
|
||||||
"gamepad-voltex" => OutputMode::Gamepad {
|
"gamepad-voltex" => OutputMode::Gamepad {
|
||||||
layout: GamepadLayout::Voltex,
|
layout: GamepadLayout::Voltex,
|
||||||
|
polling: OutputPolling::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
},
|
},
|
||||||
"gamepad-neardayo" => OutputMode::Gamepad {
|
"gamepad-neardayo" => OutputMode::Gamepad {
|
||||||
layout: GamepadLayout::Neardayo,
|
layout: GamepadLayout::Neardayo,
|
||||||
|
polling: OutputPolling::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
},
|
},
|
||||||
"websocket" => OutputMode::Websocket {
|
"websocket" => OutputMode::Websocket {
|
||||||
url: v["outputWebsocketUrl"].as_str()?.to_string(),
|
url: v["outputWebsocketUrl"].as_str()?.to_string(),
|
||||||
|
polling: OutputPolling::from_str(v["outputPolling"].as_str()?)?,
|
||||||
},
|
},
|
||||||
_ => panic!("Invalid output mode"),
|
_ => panic!("Invalid output mode"),
|
||||||
},
|
},
|
||||||
@ -158,6 +204,7 @@ impl Config {
|
|||||||
"ledMode": "none",
|
"ledMode": "none",
|
||||||
"keyboardSensitivity": 20,
|
"keyboardSensitivity": 20,
|
||||||
"outputWebsocketUrl": "localhost:3000",
|
"outputWebsocketUrl": "localhost:3000",
|
||||||
|
"outputPolling": "60",
|
||||||
"ledSensitivity": 20,
|
"ledSensitivity": 20,
|
||||||
"ledWebsocketUrl": "localhost:3001",
|
"ledWebsocketUrl": "localhost:3001",
|
||||||
"ledSerialPort": "COM5"
|
"ledSerialPort": "COM5"
|
||||||
@ -176,6 +223,28 @@ impl Config {
|
|||||||
return Some(Box::new(log_path));
|
return Some(Box::new(log_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_brokenithm_qr_path() -> Option<Box<PathBuf>> {
|
||||||
|
let project_dir = ProjectDirs::from("me", "impress labs", "slidershim").unwrap();
|
||||||
|
let config_dir = project_dir.config_dir();
|
||||||
|
fs::create_dir_all(config_dir).unwrap();
|
||||||
|
|
||||||
|
let brokenithm_qr_path = config_dir.join("brokenithm.png");
|
||||||
|
|
||||||
|
let ips = list_ips().ok()?;
|
||||||
|
let link = "http://imp.ress.me/t/sshelper?d=".to_string()
|
||||||
|
+ &ips
|
||||||
|
.into_iter()
|
||||||
|
.filter(|s| s.as_str().chars().filter(|x| *x == '.').count() == 3)
|
||||||
|
.map(|s| base64::encode_config(s, base64::URL_SAFE_NO_PAD))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(";");
|
||||||
|
let qr = QrCode::new(link).ok()?;
|
||||||
|
let image = qr.render::<Luma<u8>>().build();
|
||||||
|
image.save(brokenithm_qr_path.as_path()).ok()?;
|
||||||
|
|
||||||
|
return Some(Box::new(brokenithm_qr_path));
|
||||||
|
}
|
||||||
|
|
||||||
fn get_saved_path() -> Option<Box<PathBuf>> {
|
fn get_saved_path() -> Option<Box<PathBuf>> {
|
||||||
let project_dir = ProjectDirs::from("me", "impress labs", "slidershim").unwrap();
|
let project_dir = ProjectDirs::from("me", "impress labs", "slidershim").unwrap();
|
||||||
let config_dir = project_dir.config_dir();
|
let config_dir = project_dir.config_dir();
|
||||||
|
@ -102,8 +102,8 @@ impl HidDeviceJob {
|
|||||||
.zip(led_state.led_state.chunks(3).rev())
|
.zip(led_state.led_state.chunks(3).rev())
|
||||||
{
|
{
|
||||||
buf_chunk[0] = state_chunk[2];
|
buf_chunk[0] = state_chunk[2];
|
||||||
buf_chunk[1] = state_chunk[1];
|
buf_chunk[1] = state_chunk[0];
|
||||||
buf_chunk[2] = state_chunk[0];
|
buf_chunk[2] = state_chunk[1];
|
||||||
}
|
}
|
||||||
buf.data[96..240].fill(0);
|
buf.data[96..240].fill(0);
|
||||||
},
|
},
|
||||||
@ -140,8 +140,8 @@ impl HidDeviceJob {
|
|||||||
.zip(led_state.led_state.chunks(3).rev())
|
.zip(led_state.led_state.chunks(3).rev())
|
||||||
{
|
{
|
||||||
buf_chunk[0] = state_chunk[2];
|
buf_chunk[0] = state_chunk[2];
|
||||||
buf_chunk[1] = state_chunk[1];
|
buf_chunk[1] = state_chunk[0];
|
||||||
buf_chunk[2] = state_chunk[0];
|
buf_chunk[2] = state_chunk[1];
|
||||||
}
|
}
|
||||||
buf.data[96..240].fill(0);
|
buf.data[96..240].fill(0);
|
||||||
},
|
},
|
||||||
|
@ -137,7 +137,7 @@ impl LedJob {
|
|||||||
{
|
{
|
||||||
led_state.paint(idx, &[(*buf_chunk)[1], (*buf_chunk)[2], (*buf_chunk)[0]]);
|
led_state.paint(idx, &[(*buf_chunk)[1], (*buf_chunk)[2], (*buf_chunk)[0]]);
|
||||||
}
|
}
|
||||||
println!("leds {:?}", led_state.led_state);
|
// println!("leds {:?}", led_state.led_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,10 +187,7 @@ impl ThreadJob for LedJob {
|
|||||||
LedMode::Serial { .. } => {
|
LedMode::Serial { .. } => {
|
||||||
if let Some(serial_port) = self.serial_port.as_mut() {
|
if let Some(serial_port) = self.serial_port.as_mut() {
|
||||||
let mut serial_data_avail = serial_port.bytes_to_read().unwrap_or(0);
|
let mut serial_data_avail = serial_port.bytes_to_read().unwrap_or(0);
|
||||||
if serial_data_avail < 100 {
|
if serial_data_avail >= 100 {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if serial_data_avail % 100 == 0 {
|
if serial_data_avail % 100 == 0 {
|
||||||
let mut serial_buffer_working = Buffer::new();
|
let mut serial_buffer_working = Buffer::new();
|
||||||
serial_port
|
serial_port
|
||||||
@ -207,6 +204,7 @@ impl ThreadJob for LedJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ impl Manager {
|
|||||||
let join_handle = thread::spawn(move || {
|
let join_handle = thread::spawn(move || {
|
||||||
info!("Manager thread started");
|
info!("Manager thread started");
|
||||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||||
.worker_threads(1)
|
.worker_threads(2)
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -12,6 +12,7 @@ pub trait OutputHandler: Send {
|
|||||||
|
|
||||||
pub struct OutputJob {
|
pub struct OutputJob {
|
||||||
state: FullState,
|
state: FullState,
|
||||||
|
t: u64,
|
||||||
sensitivity: u8,
|
sensitivity: u8,
|
||||||
handler: Box<dyn OutputHandler>,
|
handler: Box<dyn OutputHandler>,
|
||||||
}
|
}
|
||||||
@ -21,17 +22,21 @@ impl OutputJob {
|
|||||||
match mode {
|
match mode {
|
||||||
OutputMode::Keyboard {
|
OutputMode::Keyboard {
|
||||||
layout,
|
layout,
|
||||||
|
polling,
|
||||||
sensitivity,
|
sensitivity,
|
||||||
} => Self {
|
} => Self {
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
|
t: polling.to_t_u64(),
|
||||||
sensitivity: *sensitivity,
|
sensitivity: *sensitivity,
|
||||||
handler: Box::new(KeyboardOutput::new(layout.clone())),
|
handler: Box::new(KeyboardOutput::new(layout.clone())),
|
||||||
},
|
},
|
||||||
OutputMode::Gamepad {
|
OutputMode::Gamepad {
|
||||||
layout,
|
layout,
|
||||||
|
polling,
|
||||||
sensitivity,
|
sensitivity,
|
||||||
} => Self {
|
} => Self {
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
|
t: polling.to_t_u64(),
|
||||||
sensitivity: *sensitivity,
|
sensitivity: *sensitivity,
|
||||||
handler: Box::new(GamepadOutput::new(layout.clone())),
|
handler: Box::new(GamepadOutput::new(layout.clone())),
|
||||||
},
|
},
|
||||||
@ -53,7 +58,7 @@ impl ThreadJob for OutputJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.handler.tick(&flat_controller_state);
|
self.handler.tick(&flat_controller_state);
|
||||||
thread::sleep(Duration::from_millis(10));
|
thread::sleep(Duration::from_millis(self.t));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn teardown(&mut self) {
|
fn teardown(&mut self) {
|
||||||
|
@ -51,10 +51,7 @@
|
|||||||
"active": false
|
"active": false
|
||||||
},
|
},
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
"all": false,
|
"all": false
|
||||||
"shell": {
|
|
||||||
"open": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
@ -62,7 +59,9 @@
|
|||||||
"width": 500,
|
"width": 500,
|
||||||
"height": 550,
|
"height": 550,
|
||||||
"resizable": false,
|
"resizable": false,
|
||||||
"fullscreen": false
|
"fullscreen": false,
|
||||||
|
"decorations": false,
|
||||||
|
"transparent": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
let ledMode = "none";
|
let ledMode = "none";
|
||||||
|
|
||||||
let keyboardSensitivity = 20;
|
let keyboardSensitivity = 20;
|
||||||
|
let outputPolling = "100";
|
||||||
let outputWebsocketUrl = "http://localhost:3000";
|
let outputWebsocketUrl = "http://localhost:3000";
|
||||||
let ledSensitivity = 20;
|
let ledSensitivity = 20;
|
||||||
let ledWebsocketUrl = "http://localhost:3001";
|
let ledWebsocketUrl = "http://localhost:3001";
|
||||||
@ -28,7 +29,6 @@
|
|||||||
let polling = null;
|
let polling = null;
|
||||||
let tick = 0;
|
let tick = 0;
|
||||||
let previewData = Array(131).fill(0);
|
let previewData = Array(131).fill(0);
|
||||||
let logfile = "";
|
|
||||||
|
|
||||||
function updatePolling(enabled) {
|
function updatePolling(enabled) {
|
||||||
if (!!polling) {
|
if (!!polling) {
|
||||||
@ -44,6 +44,7 @@
|
|||||||
// console.log(enabled, polling, tick);
|
// console.log(enabled, polling, tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Receive events
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
// console.log(emit, listen);
|
// console.log(emit, listen);
|
||||||
await listen("showConfig", (event) => {
|
await listen("showConfig", (event) => {
|
||||||
@ -51,7 +52,9 @@
|
|||||||
deviceMode = payload.deviceMode || "none";
|
deviceMode = payload.deviceMode || "none";
|
||||||
outputMode = payload.outputMode || "none";
|
outputMode = payload.outputMode || "none";
|
||||||
ledMode = payload.ledMode || "none";
|
ledMode = payload.ledMode || "none";
|
||||||
|
|
||||||
keyboardSensitivity = payload.keyboardSensitivity || 20;
|
keyboardSensitivity = payload.keyboardSensitivity || 20;
|
||||||
|
outputPolling = payload.outputPolling || "100";
|
||||||
outputWebsocketUrl =
|
outputWebsocketUrl =
|
||||||
payload.outputWebsocketUrl || "http://localhost:3000/";
|
payload.outputWebsocketUrl || "http://localhost:3000/";
|
||||||
ledSensitivity = payload.ledSensitivity || 20;
|
ledSensitivity = payload.ledSensitivity || 20;
|
||||||
@ -69,10 +72,6 @@
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await listen("updateLogPath", (event) => {
|
|
||||||
logfile = event.payload as string;
|
|
||||||
});
|
|
||||||
|
|
||||||
await emit("ready", "");
|
await emit("ready", "");
|
||||||
|
|
||||||
updatePolling(true);
|
updatePolling(true);
|
||||||
@ -86,6 +85,8 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Emit events
|
||||||
|
|
||||||
async function setConfig() {
|
async function setConfig() {
|
||||||
console.log("Updating config");
|
console.log("Updating config");
|
||||||
await emit(
|
await emit(
|
||||||
@ -95,6 +96,7 @@
|
|||||||
outputMode,
|
outputMode,
|
||||||
ledMode,
|
ledMode,
|
||||||
keyboardSensitivity,
|
keyboardSensitivity,
|
||||||
|
outputPolling,
|
||||||
outputWebsocketUrl,
|
outputWebsocketUrl,
|
||||||
ledSensitivity,
|
ledSensitivity,
|
||||||
ledWebsocketUrl,
|
ledWebsocketUrl,
|
||||||
@ -114,17 +116,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function logs() {
|
async function logs() {
|
||||||
await open(logfile);
|
await emit("openLogfile", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function brokenithmQr() {
|
||||||
|
await emit("openBrokenithmQr");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main class="main">
|
<main class="main">
|
||||||
<div class="row">
|
<!-- <div class="row titlebar" data-tauri-drag-region> -->
|
||||||
<div class="header">
|
<!-- <div class="header"> -->
|
||||||
<!-- slidershim by @4yn -->
|
<!-- slidershim by @4yn -->
|
||||||
slidershim
|
<!-- slidershim -->
|
||||||
</div>
|
<!-- </div> -->
|
||||||
</div>
|
<!-- </div> -->
|
||||||
<!-- <div>
|
<!-- <div>
|
||||||
{debugstr}
|
{debugstr}
|
||||||
</div> -->
|
</div> -->
|
||||||
@ -149,7 +155,7 @@
|
|||||||
<div class="label" />
|
<div class="label" />
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<div class="serverlist">
|
<div class="serverlist">
|
||||||
Brokenithm open at:
|
Brokenithm server running, access at one of:
|
||||||
<pre>
|
<pre>
|
||||||
{ips.map((x) => `http://${x}:1606/`).join("\n")}
|
{ips.map((x) => `http://${x}:1606/`).join("\n")}
|
||||||
</pre>
|
</pre>
|
||||||
@ -175,7 +181,21 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if outputMode === "gamepad-voltex"}
|
{#if outputMode !== "none"}
|
||||||
|
<div class="row">
|
||||||
|
<div class="label">Output Polling</div>
|
||||||
|
<div class="input">
|
||||||
|
<select bind:value={outputPolling} on:change={markDirty}>
|
||||||
|
<option value="60">60 Hz</option>
|
||||||
|
<option value="100">100 Hz</option>
|
||||||
|
<option value="330">330 Hz</option>
|
||||||
|
<option value="500">500 Hz</option>
|
||||||
|
<option value="1000">1000 Hz</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if outputMode.slice(0, 7) === "gamepad"}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="label" />
|
<div class="label" />
|
||||||
<div class="input">
|
<div class="input">
|
||||||
@ -187,7 +207,9 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if outputMode.slice(0, 2) === "kb" && deviceMode.slice(0, 10) !== "brokenithm"}
|
{#if outputMode.slice(0, 2) === "kb" && deviceMode.slice(0, 10) !== "brokenithm"}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="label">Sensitivity</div>
|
<div class="label" title="Larger means harder to trigger">
|
||||||
|
Sensitivity
|
||||||
|
</div>
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
@ -242,7 +264,9 @@
|
|||||||
</div>
|
</div>
|
||||||
{#if ledMode.slice(0, 8) === "reactive" && deviceMode.slice(0, 10) !== "brokenithm"}
|
{#if ledMode.slice(0, 8) === "reactive" && deviceMode.slice(0, 10) !== "brokenithm"}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="label">Sensitivity</div>
|
<div class="label" title="Larger means harder to trigger">
|
||||||
|
Sensitivity
|
||||||
|
</div>
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
@ -314,8 +338,9 @@
|
|||||||
>
|
>
|
||||||
<button on:click={async () => await hide()}>Hide</button>
|
<button on:click={async () => await hide()}>Hide</button>
|
||||||
<button on:click={async () => await quit()}>Quit</button>
|
<button on:click={async () => await quit()}>Quit</button>
|
||||||
{#if !!logfile.length}
|
|
||||||
<button on:click={async () => await logs()}>Logs</button>
|
<button on:click={async () => await logs()}>Logs</button>
|
||||||
|
{#if deviceMode.slice(0, 10) === "brokenithm"}
|
||||||
|
<button on:click={async () => await brokenithmQr()}>Brokenithm QR</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
@ -5,12 +5,9 @@
|
|||||||
let botDatas = Array(16).fill(0);
|
let botDatas = Array(16).fill(0);
|
||||||
let airDatas = Array(6).fill(0);
|
let airDatas = Array(6).fill(0);
|
||||||
let extraDatas = Array(3).fill(0);
|
let extraDatas = Array(3).fill(0);
|
||||||
let ledDatas = Array(31)
|
|
||||||
.fill(0)
|
let ledDatas = Array(16).fill("#ff0");
|
||||||
.map((_, idx) => ({
|
let ledDividerDatas = Array(15).fill("#ff0");
|
||||||
color: !!(idx % 2) ? "#f0f" : "#ff0",
|
|
||||||
spec: idx % 2,
|
|
||||||
}));
|
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
if (data.length === 134) {
|
if (data.length === 134) {
|
||||||
@ -27,9 +24,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < 31; i++) {
|
for (let i = 0; i < 31; i++) {
|
||||||
ledDatas[i].color = `rgb(${data[41 + i * 3]}, ${data[42 + i * 3]}, ${
|
let rgbstr = `rgb(${data[41 + i * 3]}, ${data[42 + i * 3]}, ${
|
||||||
data[43 + i * 3]
|
data[43 + i * 3]
|
||||||
})`;
|
})`;
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
ledDatas[i / 2] = rgbstr;
|
||||||
|
} else {
|
||||||
|
ledDividerDatas[(i - 1) / 2] = rgbstr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,11 +46,18 @@
|
|||||||
<div class="ground">
|
<div class="ground">
|
||||||
<div class="ground-led">
|
<div class="ground-led">
|
||||||
<div class="ground-row">
|
<div class="ground-row">
|
||||||
|
{#each ledDatas as ledData, idx (idx)}
|
||||||
|
<div class={`ground-led-0`} style={`background-color: ${ledData}`} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ground-led">
|
||||||
|
<div class="ground-row ground-row-divider">
|
||||||
<div class="ground-led-2" />
|
<div class="ground-led-2" />
|
||||||
{#each ledDatas as { color, spec }, idx (idx)}
|
{#each ledDividerDatas as ledDividerData, idx (idx)}
|
||||||
<div
|
<div
|
||||||
class={`ground-led-${spec}`}
|
class="ground-led-1"
|
||||||
style={`background-color: ${color}`}
|
style={`background-color: ${ledDividerData}`}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
<div class="ground-led-2" />
|
<div class="ground-led-2" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user