Added support for remote0
BIN
com.exension.hwinfo.sdPlugin/DejaVuSans-Bold.ttf
Normal file
BIN
com.exension.hwinfo.sdPlugin/css/buttons.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
com.exension.hwinfo.sdPlugin/css/buttons@2x.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
3
com.exension.hwinfo.sdPlugin/css/caret.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="6" viewBox="0 0 12 6">
|
||||
<polygon fill="#8E8E92" fill-rule="evenodd" points="5 4 9 0 10 1 5 6 0 1 1 0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 171 B |
BIN
com.exension.hwinfo.sdPlugin/css/check.png
Normal file
|
After Width: | Height: | Size: 234 B |
3
com.exension.hwinfo.sdPlugin/css/check.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="10" viewBox="0 0 12 10">
|
||||
<polygon fill="#FFF" points="7.2 7.5 7.2 -1.3 8.7 -1.3 8.6 9.1 2.7 8.7 2.7 7.2" transform="rotate(37 5.718 3.896)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 210 B |
24
com.exension.hwinfo.sdPlugin/css/elg_calendar.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#9C9C9C" fill-rule="nonzero" d="M1,5 L1,14 L14,14 L14,5 L1,5 Z M0,1 L15,1 L15,15 L0,15 L0,1 Z M14,4 L14,2 L1,2 L1,4 L14,4 Z"/>
|
||||
<rect width="1" height="1" x="2" fill="#9C9C9C" fill-rule="nonzero"/>
|
||||
<rect width="1" height="1" x="12" fill="#9C9C9C" fill-rule="nonzero"/>
|
||||
<g transform="translate(3 7)">
|
||||
<rect width="1" height="1" x="2" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" fill="#666"/>
|
||||
<rect width="1" height="1" x="4" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="6" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="8" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" y="2" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="2" y="2" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="4" y="2" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="6" y="2" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="8" y="2" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" y="4" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="2" y="4" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="4" y="4" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="6" y="4" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="8" y="4" fill="#666"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
7
com.exension.hwinfo.sdPlugin/css/elg_calendar_inv.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="#9C9C9C">
|
||||
<path d="M15,15 L1.77635684e-15,15 L1.77635684e-15,1 L15,1 L15,15 Z M5,7 L5,8 L6,8 L6,7 L5,7 Z M3,7 L3,8 L4,8 L4,7 L3,7 Z M7,7 L7,8 L8,8 L8,7 L7,7 Z M9,7 L9,8 L10,8 L10,7 L9,7 Z M11,7 L11,8 L12,8 L12,7 L11,7 Z M3,9 L3,10 L4,10 L4,9 L3,9 Z M5,9 L5,10 L6,10 L6,9 L5,9 Z M7,9 L7,10 L8,10 L8,9 L7,9 Z M9,9 L9,10 L10,10 L10,9 L9,9 Z M11,9 L11,10 L12,10 L12,9 L11,9 Z M3,11 L3,12 L4,12 L4,11 L3,11 Z M5,11 L5,12 L6,12 L6,11 L5,11 Z M7,11 L7,12 L8,12 L8,11 L7,11 Z M9,11 L9,12 L10,12 L10,11 L9,11 Z M11,11 L11,12 L12,12 L12,11 L11,11 Z M14,4 L14,2 L1,2 L1,4 L14,4 Z"/>
|
||||
<rect width="1" height="1" x="2"/>
|
||||
<rect width="1" height="1" x="12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 764 B |
9
com.exension.hwinfo.sdPlugin/css/elg_calendar_inv_13.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 13 13">
|
||||
<g fill="none">
|
||||
<path fill="#9C9C9C" d="M13,13 L1.77635684e-15,13 L1.77635684e-15,1 L13,1 L13,13 Z M4,6 L4,7 L5,7 L5,6 L4,6 Z M6,6 L6,7 L7,7 L7,6 L6,6 Z M8,6 L8,7 L9,7 L9,6 L8,6 Z M10,6 L10,7 L11,7 L11,6 L10,6 Z M2,8 L2,9 L3,9 L3,8 L2,8 Z M4,8 L4,9 L5,9 L5,8 L4,8 Z M6,8 L6,9 L7,9 L7,8 L6,8 Z M8,8 L8,9 L9,9 L9,8 L8,8 Z M10,8 L10,9 L11,9 L11,8 L10,8 Z M2,10 L2,11 L3,11 L3,10 L2,10 Z M4,10 L4,11 L5,11 L5,10 L4,10 Z M6,10 L6,11 L7,11 L7,10 L6,10 Z M8,10 L8,11 L9,11 L9,10 L8,10 Z M12,4 L12,2 L1,2 L1,4 L12,4 Z"/>
|
||||
<polygon fill="#3D3D3D" points="2 6 2 7 3 7 3 6"/>
|
||||
<polygon fill="#3D3D3D" points="10 10 10 11 11 11 11 10"/>
|
||||
<rect width="1" height="1" x="2" fill="#9C9C9C"/>
|
||||
<rect width="1" height="1" x="10" fill="#9C9C9C"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 844 B |
18
com.exension.hwinfo.sdPlugin/css/local.css
Normal file
@@ -0,0 +1,18 @@
|
||||
body,
|
||||
.localbody {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
margin: 0;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.localbody {
|
||||
width: 350px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: block;
|
||||
}
|
||||
3
com.exension.hwinfo.sdPlugin/css/pi_required.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="9" height="9" viewBox="0 0 9 9">
|
||||
<path fill="#D8D8D8" d="M4.5,0 C6.98528137,-4.56538782e-16 9,2.01471863 9,4.5 C9,6.98528137 6.98528137,9 4.5,9 C2.01471863,9 3.04359188e-16,6.98528137 0,4.5 C-3.04359188e-16,2.01471863 2.01471863,4.56538782e-16 4.5,0 Z M4,1 L4,6 L5,6 L5,1 L4,1 Z M4.5,8 C4.77614237,8 5,7.77614237 5,7.5 C5,7.22385763 4.77614237,7 4.5,7 C4.22385763,7 4,7.22385763 4,7.5 C4,7.77614237 4.22385763,8 4.5,8 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 479 B |
3
com.exension.hwinfo.sdPlugin/css/pi_required_ok.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="9" height="9" viewBox="0 0 9 9">
|
||||
<polygon fill="#D8D8D8" points="5.2 1 6.2 1 6.2 7 3.2 7 3.2 6 5.2 6" transform="rotate(40 4.677 4)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 191 B |
3
com.exension.hwinfo.sdPlugin/css/rcheck.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="6" height="6" viewBox="0 0 6 6">
|
||||
<circle cx="3" cy="3" r="3" fill="#FFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 131 B |
43
com.exension.hwinfo.sdPlugin/css/reset.min.css
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote,
|
||||
pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd,
|
||||
q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt,
|
||||
dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot,
|
||||
thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption,
|
||||
footer, header, hgroup, menu, nav, output, ruby, section, summary, time,
|
||||
mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline
|
||||
}
|
||||
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup,
|
||||
menu, nav, section {
|
||||
display: block
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: none
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after, q:before, q:after {
|
||||
content: '';
|
||||
content: none
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0
|
||||
}
|
||||
|
||||
|
||||
1747
com.exension.hwinfo.sdPlugin/css/sdpi.css
Normal file
1176
com.exension.hwinfo.sdPlugin/css/xsdpi.css
Normal file
BIN
com.exension.hwinfo.sdPlugin/defaultImage.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
com.exension.hwinfo.sdPlugin/defaultImage@2x.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
com.exension.hwinfo.sdPlugin/icon.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
com.exension.hwinfo.sdPlugin/icon@2x.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
169
com.exension.hwinfo.sdPlugin/index_pi.html
Normal file
@@ -0,0 +1,169 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport"
|
||||
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui,viewport-fit=cover" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<title>Property Inspector Samples PI</title>
|
||||
<link rel="stylesheet" href="css/sdpi.css" />
|
||||
<!--link rel="stylesheet"
|
||||
media="screen and (max-width: 1025px)"
|
||||
href="css/local.css" -->
|
||||
<link rel="stylesheet" href="css/local.css" />
|
||||
<style>
|
||||
#error {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sensorSelect {
|
||||
max-width: 226px;
|
||||
padding-right: 25px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#sensorSelect option {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#readingSelect {
|
||||
max-width: 226px;
|
||||
padding-right: 25px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#readingSelect option {
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="error" class="sdpi-wrapper localbody hiddenx">
|
||||
<div class="sdpi-heading">Plugin Error</div>
|
||||
<div class="sdpi-item">
|
||||
<details open class="message caution">
|
||||
<summary>Unable To Communicate With HWiNFO64</summary>
|
||||
<p>
|
||||
The plugin is unable to communicate with HWiNFO64
|
||||
</p>
|
||||
<p>Make sure it's running and configured properly</p>
|
||||
<p>
|
||||
For help on how to properly setup HWiNFO64, refer to the
|
||||
<a class="info" target="_blank"
|
||||
href="https://github.com/exension/hwinfo-streamdeck/blob/master/README.md#hwinfo-stream-deck-plugin">
|
||||
documentation
|
||||
</a>
|
||||
</p>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ui" class="sdpi-wrapper localbody hiddenx">
|
||||
<div class="sdpi-heading">Font Sizes</div>
|
||||
|
||||
<div type="range" class="sdpi-item" id="titleFontSize">
|
||||
<div class="sdpi-item-label">Title</div>
|
||||
<div class="sdpi-item-value">
|
||||
<span value="8">8</span>
|
||||
<input type="range" min="8" max="20" step="0.5" value="10.5" list="steplist" />
|
||||
<span value="20">20</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div type="range" class="sdpi-item" id="valueFontSize">
|
||||
<div class="sdpi-item-label">Value</div>
|
||||
<div class="sdpi-item-value">
|
||||
<span value="8">8</span>
|
||||
<input type="range" min="8" max="20" step="0.5" value="10.5" />
|
||||
<span value="20">20</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sdpi-heading">HWiNFO Sensors</div>
|
||||
|
||||
<div class="sdpi-item">
|
||||
<div class="sdpi-item-label">Sensor</div>
|
||||
<select class="sdpi-item-value select" id="sensorSelect" disabled="disabled">
|
||||
<option>Loading...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="sdpi-item" id="readingSelectContainer">
|
||||
<div class="sdpi-item-label">Reading</div>
|
||||
<select class="sdpi-item-value select" id="readingSelect" disabled="disabled">
|
||||
<option></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="sdpi-heading">Value Params</div>
|
||||
|
||||
<div type="sdpi-item" class="sdpi-item" id="paramsgroup">
|
||||
<div class="sdpi-item-label">Min/Max</div>
|
||||
|
||||
<div class="sdpi-item" id="minmax" style="margin-left: -4px">
|
||||
<input class="sdpi-item-value" style="width:4em" placeholder="Min" inputmode="numeric" pattern="[0-9]*"
|
||||
type="number" id="min" name="min" />
|
||||
<input class="sdpi-item-value" style="margin-left: -7px; width:4em" placeholder=" Max" inputmode="numeric"
|
||||
pattern="[0-9]*" type="number" id="max" name="max" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details id="advanced_details">
|
||||
<summary>Advanced</summary>
|
||||
<div class="sdpi-item" id="format">
|
||||
<div class="sdpi-item-label">Format</div>
|
||||
<input class="sdpi-item-value" placeholder="%.0f (no decimals)" type="text" name="format" value="" />
|
||||
</div>
|
||||
<div class="sdpi-item">
|
||||
<details open class="message question noInnerMargins">
|
||||
<summary>Help</summary>
|
||||
<p>Format can be used to modify format of the value.</p>
|
||||
<p>
|
||||
For more information on how to use this field,
|
||||
<a target="_BLANK" href="#"
|
||||
onclick="openUrl('https://gobyexample.com/string-formatting'); return false;">click here</a>.
|
||||
</p>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="sdpi-item" id="divisor">
|
||||
<div class="sdpi-item-label">Divisor</div>
|
||||
<input class="sdpi-item-value" placeholder="e.g. 125 (for bytes to megabits)" inputmode="numeric"
|
||||
pattern="[0-9]*" min="1" type="number" name="divisor" />
|
||||
</div>
|
||||
<div class="sdpi-item">
|
||||
<details open class="message question noInnerMargins">
|
||||
<summary>Help</summary>
|
||||
<p>Divisor can be used to convert the value.</p>
|
||||
<p>
|
||||
For example, converting bytes to megabits, set the divisor to:
|
||||
"125"
|
||||
</p>
|
||||
</details>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="sdpi-heading">Graph Colors</div>
|
||||
|
||||
<div type="color" class="sdpi-item" id="colorselection">
|
||||
<div class="sdpi-item-label">Background</div>
|
||||
<input type="color" class="sdpi-item-value" id="background" value="#000000" />
|
||||
<div class="sdpi-item-label">Value Text</div>
|
||||
<input type="color" class="sdpi-item-value" id="valuetext" value="#ffffff" />
|
||||
</div>
|
||||
|
||||
<div type="color" class="sdpi-item" id="colorselection">
|
||||
<div class="sdpi-item-label">Foreground</div>
|
||||
<input type="color" class="sdpi-item-value" id="foreground" value="#005128" />
|
||||
<div class="sdpi-item-label">Highlight</div>
|
||||
<input type="color" class="sdpi-item-value" id="highlight" value="#009e00" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- <script src="echomd.js"></script> -->
|
||||
<script src="index_pi.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
571
com.exension.hwinfo.sdPlugin/index_pi.js
Normal file
@@ -0,0 +1,571 @@
|
||||
// this is our global websocket, used to communicate from/to Stream Deck software
|
||||
// and some info about our plugin, as sent by Stream Deck software
|
||||
var websocket = null,
|
||||
uuid = null,
|
||||
actionInfo = {},
|
||||
inInfo = {},
|
||||
runningApps = [],
|
||||
isQT = navigator.appVersion.includes("QtWebEngine"),
|
||||
onchangeevt = "onchange"; // 'oninput'; // change this, if you want interactive elements act on any change, or while they're modified
|
||||
|
||||
function connectElgatoStreamDeckSocket(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo) {
|
||||
uuid = inUUID;
|
||||
// please note: the incoming arguments are of type STRING, so
|
||||
// in case of the inActionInfo, we must parse it into JSON first
|
||||
actionInfo = JSON.parse(inActionInfo); // cache the info
|
||||
inInfo = JSON.parse(inInfo);
|
||||
websocket = new WebSocket("ws://localhost:" + inPort);
|
||||
|
||||
/** Since the PI doesn't have access to native settings
|
||||
* Stream Deck sends some color settings to PI
|
||||
* We use these to adjust some styles (e.g. highlight-colors for checkboxes)
|
||||
*/
|
||||
addDynamicStyles(inInfo.colors, "connectSocket");
|
||||
initPropertyInspector(5);
|
||||
|
||||
// if connection was established, the websocket sends
|
||||
// an 'onopen' event, where we need to register our PI
|
||||
websocket.onopen = function () {
|
||||
var json = {
|
||||
event: inRegisterEvent,
|
||||
uuid: inUUID,
|
||||
};
|
||||
// register property inspector to Stream Deck
|
||||
websocket.send(JSON.stringify(json));
|
||||
sendValueToPlugin("propertyInspectorConnected", "property_inspector");
|
||||
};
|
||||
|
||||
websocket.onmessage = function (evt) {
|
||||
// Received message from Stream Deck
|
||||
var jsonObj = JSON.parse(evt.data);
|
||||
var event = jsonObj["event"];
|
||||
if (
|
||||
"boolean" === typeof getPropFromString(jsonObj, "payload.error") &&
|
||||
event === "sendToPropertyInspector"
|
||||
) {
|
||||
if (jsonObj.payload.error === true) {
|
||||
document.querySelector("#ui").style = "display:none";
|
||||
document.querySelector("#error").style = "display:block";
|
||||
} else if (jsonObj.payload.message === "show_ui") {
|
||||
document.querySelector("#ui").style = "display:block";
|
||||
document.querySelector("#error").style = "display:none";
|
||||
sendValueToPlugin("propertyInspectorConnected", "property_inspector");
|
||||
}
|
||||
}
|
||||
if (
|
||||
getPropFromString(jsonObj, "payload.sensors") &&
|
||||
event === "sendToPropertyInspector"
|
||||
) {
|
||||
addSensors(
|
||||
document.querySelector("#sensorSelect"),
|
||||
jsonObj.payload.sensors,
|
||||
jsonObj.payload.settings
|
||||
);
|
||||
}
|
||||
if (
|
||||
getPropFromString(jsonObj, "payload.readings") &&
|
||||
event === "sendToPropertyInspector"
|
||||
) {
|
||||
addReadings(
|
||||
document.querySelector("#readingSelect"),
|
||||
jsonObj.payload.readings,
|
||||
jsonObj.payload.settings
|
||||
);
|
||||
}
|
||||
if (getPropFromString(jsonObj, "payload.settings")) {
|
||||
var settings = jsonObj.payload.settings;
|
||||
if (settings.min === 0 && settings.max === 0) {
|
||||
// don't show 0, 0 min/max
|
||||
} else {
|
||||
document.querySelector("#min").value = settings.min;
|
||||
document.querySelector("#max").value = settings.max;
|
||||
}
|
||||
document.querySelector("#format input").value = settings.format;
|
||||
document.querySelector("#divisor input").value = settings.divisor || "";
|
||||
if (
|
||||
settings.format.length > 0 ||
|
||||
(settings.divisor && settings.divisor.length > 0)
|
||||
) {
|
||||
var attr = document.createAttribute("open");
|
||||
attr.value = "open";
|
||||
document
|
||||
.querySelector("#advanced_details")
|
||||
.attributes.setNamedItem(attr);
|
||||
}
|
||||
if (settings.foregroundColor !== "") {
|
||||
document.querySelector("#foreground").value = settings.foregroundColor;
|
||||
}
|
||||
if (settings.backgroundColor !== "") {
|
||||
document.querySelector("#background").value = settings.backgroundColor;
|
||||
}
|
||||
if (settings.highlightColor !== "") {
|
||||
document.querySelector("#highlight").value = settings.highlightColor;
|
||||
}
|
||||
if (settings.valueTextColor !== "") {
|
||||
document.querySelector("#valuetext").value = settings.valueTextColor;
|
||||
}
|
||||
if (settings.titleFontSize !== "") {
|
||||
document.querySelector("#titleFontSize input").value =
|
||||
settings.titleFontSize || 10.5;
|
||||
}
|
||||
if (settings.valueFontSize !== "") {
|
||||
document.querySelector("#valueFontSize input").value =
|
||||
settings.valueFontSize || 10.5;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function sortBy(key) {
|
||||
return function (a, b) {
|
||||
if (a[key] > b[key]) return 1;
|
||||
if (b[key] > a[key]) return -1;
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
function addSensors(el, sensors, settings) {
|
||||
var i;
|
||||
for (i = el.options.length - 1; i >= 0; i--) {
|
||||
el.remove(i);
|
||||
}
|
||||
|
||||
el.removeAttribute("disabled");
|
||||
|
||||
var option = document.createElement("option");
|
||||
option.text = "Choose a sensor";
|
||||
option.disabled = true;
|
||||
if (settings.isValid !== true) {
|
||||
option.selected = true;
|
||||
}
|
||||
el.add(option);
|
||||
var sortByName = sortBy("name");
|
||||
sensors.sort(sortByName).forEach((s) => {
|
||||
var option = document.createElement("option");
|
||||
option.text = s.name;
|
||||
option.value = s.uid;
|
||||
if (settings.isValid === true && settings.sensorUid === s.uid) {
|
||||
option.selected = true;
|
||||
setTimeout(function () {
|
||||
var event = new Event("change");
|
||||
el.dispatchEvent(event);
|
||||
}, 0);
|
||||
}
|
||||
el.add(option);
|
||||
});
|
||||
}
|
||||
|
||||
function addReadings(el, readings, settings) {
|
||||
var i;
|
||||
for (i = el.options.length - 1; i >= 0; i--) {
|
||||
el.remove(i);
|
||||
}
|
||||
|
||||
el.removeAttribute("disabled");
|
||||
|
||||
var option = document.createElement("option");
|
||||
option.text = "Choose a reading";
|
||||
option.disabled = true;
|
||||
if (settings.isValid !== true) {
|
||||
option.selected = true;
|
||||
}
|
||||
el.add(option);
|
||||
|
||||
var sortByLabel = sortBy("label");
|
||||
var maxL = 0;
|
||||
readings.sort(sortByLabel).forEach((r) => {
|
||||
var l = r.prefix.length;
|
||||
if (l > maxL) {
|
||||
maxL = l;
|
||||
}
|
||||
});
|
||||
readings.sort(sortByLabel).forEach((r) => {
|
||||
var option = document.createElement("option");
|
||||
option.style = "white-space: pre";
|
||||
var spaces = " ";
|
||||
for (i = 0; i < maxL - r.prefix.length; ++i) {
|
||||
spaces += " ";
|
||||
}
|
||||
option.innerHTML = `${r.prefix}${spaces}${r.label}`;
|
||||
option.value = r.id;
|
||||
if (settings.isValid === true && settings.readingId === r.id) {
|
||||
option.selected = true;
|
||||
}
|
||||
el.add(option);
|
||||
});
|
||||
}
|
||||
|
||||
function initPropertyInspector(initDelay) {
|
||||
prepareDOMElements(document);
|
||||
}
|
||||
|
||||
function revealSdpiWrapper() {
|
||||
const el = document.querySelector(".sdpi-wrapper");
|
||||
el && el.classList.remove("hidden");
|
||||
}
|
||||
|
||||
// openUrl in default browser
|
||||
function openUrl(url) {
|
||||
if (websocket && websocket.readyState === 1) {
|
||||
const json = {
|
||||
event: "openUrl",
|
||||
payload: {
|
||||
url: url,
|
||||
},
|
||||
};
|
||||
websocket.send(JSON.stringify(json));
|
||||
}
|
||||
}
|
||||
|
||||
// our method to pass values to the plugin
|
||||
function sendValueToPlugin(value, param) {
|
||||
if (websocket && websocket.readyState === 1) {
|
||||
const json = {
|
||||
action: actionInfo["action"],
|
||||
event: "sendToPlugin",
|
||||
context: uuid,
|
||||
payload: {
|
||||
[param]: value,
|
||||
},
|
||||
};
|
||||
websocket.send(JSON.stringify(json));
|
||||
}
|
||||
}
|
||||
|
||||
if (!isQT) {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
initPropertyInspector(100);
|
||||
});
|
||||
}
|
||||
|
||||
/** the beforeunload event is fired, right before the PI will remove all nodes */
|
||||
window.addEventListener("beforeunload", function (e) {
|
||||
e.preventDefault();
|
||||
sendValueToPlugin("propertyInspectorWillDisappear", "property_inspector");
|
||||
// Don't set a returnValue to the event, otherwise Chromium with throw an error. // e.returnValue = '';
|
||||
});
|
||||
|
||||
/** the pagehide event is fired, when the view disappears */
|
||||
/*
|
||||
window.addEventListener('pagehide', function (event) {
|
||||
console.log('%c%s','background: green; font-size: 22px; font-weight: bold;','window --->> pagehide.');
|
||||
sendValueToPlugin('propertyInspectorPagehide', 'property_inspector');
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
/** the unload event is fired, when the PI will finally disappear */
|
||||
/*
|
||||
window.addEventListener('unload', function (event) {
|
||||
console.log('%c%s','background: orange; font-size: 22px; font-weight: bold;','window --->> onunload.');
|
||||
sendValueToPlugin('propertyInspectorDisconnected', 'property_inspector');
|
||||
});
|
||||
*/
|
||||
|
||||
/** if you prefer, you can apply these listeners to PI's body, like so:
|
||||
*
|
||||
* <body onpagehide="sendValueToPlugin('propertyInspectorPagehide', 'property_inspector');">
|
||||
*
|
||||
* <body onunload="sendValueToPlugin('propertyInspectorDisconnected', 'property_inspector');">
|
||||
*/
|
||||
|
||||
/** CREATE INTERACTIVE HTML-DOM
|
||||
* where elements can be clicked or act on their 'change' event.
|
||||
* Messages are then processed using the 'handleSdpiItemClick' method below.
|
||||
*/
|
||||
|
||||
function prepareDOMElements(baseElement) {
|
||||
baseElement = baseElement || document;
|
||||
Array.from(baseElement.querySelectorAll(".sdpi-item-value")).forEach(
|
||||
(el, i) => {
|
||||
const elementsToClick = [
|
||||
"BUTTON",
|
||||
"OL",
|
||||
"UL",
|
||||
"TABLE",
|
||||
"METER",
|
||||
"PROGRESS",
|
||||
"CANVAS",
|
||||
].includes(el.tagName);
|
||||
const evt = elementsToClick ? "onclick" : onchangeevt || "onchange";
|
||||
// console.log(el.type, el.tagName, elementsToClick, el, evt);
|
||||
|
||||
/** Look for <input><span> combinations, where we consider the span as label for the input
|
||||
* we don't use `labels` for that, because a range could have 2 labels.
|
||||
*/
|
||||
const inputGroup = el.querySelectorAll("input, span");
|
||||
if (inputGroup.length === 2) {
|
||||
const offs = inputGroup[0].tagName === "INPUT" ? 1 : 0;
|
||||
inputGroup[offs].innerText = inputGroup[1 - offs].value;
|
||||
inputGroup[1 - offs]["oninput"] = function () {
|
||||
inputGroup[offs].innerText = inputGroup[1 - offs].value;
|
||||
};
|
||||
}
|
||||
/** We look for elements which have an 'clickable' attribute
|
||||
* we use these e.g. on an 'inputGroup' (<span><input type="range"><span>) to adjust the value of
|
||||
* the corresponding range-control
|
||||
*/
|
||||
Array.from(el.querySelectorAll(".clickable")).forEach((subel, subi) => {
|
||||
subel["onclick"] = function (e) {
|
||||
handleSdpiItemClick(e.target, subi);
|
||||
};
|
||||
});
|
||||
el[evt] = function (e) {
|
||||
handleSdpiItemClick(e.target, i);
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
baseElement.querySelectorAll("textarea").forEach((e) => {
|
||||
const maxl = e.getAttribute("maxlength");
|
||||
e.targets = baseElement.querySelectorAll(`[for='${e.id}']`);
|
||||
if (e.targets.length) {
|
||||
let fn = () => {
|
||||
for (let x of e.targets) {
|
||||
x.innerText = maxl
|
||||
? `${e.value.length}/${maxl}`
|
||||
: `${e.value.length}`;
|
||||
}
|
||||
};
|
||||
fn();
|
||||
e.onkeyup = fn;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleSdpiItemClick(e, idx) {
|
||||
/** Following items are containers, so we won't handle clicks on them */
|
||||
if (["OL", "UL", "TABLE"].includes(e.tagName)) {
|
||||
return;
|
||||
}
|
||||
// console.log('--- handleSdpiItemClick ---', e, `type: ${e.type}`, e.tagName, `inner: ${e.innerText}`);
|
||||
|
||||
/** SPANS are used inside a control as 'labels'
|
||||
* If a SPAN element calls this function, it has a class of 'clickable' set and is thereby handled as
|
||||
* clickable label.
|
||||
*/
|
||||
|
||||
if (e.tagName === "SPAN") {
|
||||
const inp = e.parentNode.querySelector("input");
|
||||
if (e.getAttribute("value")) {
|
||||
return inp && (inp.value = e.getAttribute("value"));
|
||||
}
|
||||
}
|
||||
|
||||
const selectedElements = [];
|
||||
const isList = ["LI", "OL", "UL", "DL", "TD"].includes(e.tagName);
|
||||
const sdpiItem = e.closest(".sdpi-item");
|
||||
const sdpiItemGroup = e.closest(".sdpi-item-group");
|
||||
let sdpiItemChildren = isList
|
||||
? sdpiItem.querySelectorAll(e.tagName === "LI" ? "li" : "td")
|
||||
: sdpiItem.querySelectorAll(".sdpi-item-child > input");
|
||||
|
||||
if (isList) {
|
||||
const siv = e.closest(".sdpi-item-value");
|
||||
if (!siv.classList.contains("multi-select")) {
|
||||
for (let x of sdpiItemChildren) x.classList.remove("selected");
|
||||
}
|
||||
if (!siv.classList.contains("no-select")) {
|
||||
e.classList.toggle("selected");
|
||||
}
|
||||
}
|
||||
|
||||
if (sdpiItemGroup && !sdpiItemChildren.length) {
|
||||
for (let x of ["input", "meter", "progress"]) {
|
||||
sdpiItemChildren = sdpiItemGroup.querySelectorAll(x);
|
||||
if (sdpiItemChildren.length) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.selectedIndex) {
|
||||
idx = e.selectedIndex;
|
||||
} else {
|
||||
sdpiItemChildren.forEach((ec, i) => {
|
||||
if (ec.classList.contains("selected")) {
|
||||
selectedElements.push(ec.innerText);
|
||||
}
|
||||
if (ec === e) idx = i;
|
||||
});
|
||||
}
|
||||
|
||||
const returnValue = {
|
||||
key: e.id || sdpiItem.id,
|
||||
value: isList
|
||||
? e.innerText
|
||||
: e.value
|
||||
? e.type === "file"
|
||||
? decodeURIComponent(e.value.replace(/^C:\\fakepath\\/, ""))
|
||||
: e.value
|
||||
: e.getAttribute("value"),
|
||||
group: sdpiItemGroup ? sdpiItemGroup.id : false,
|
||||
index: idx,
|
||||
selection: selectedElements,
|
||||
checked: e.checked,
|
||||
};
|
||||
|
||||
/** Just simulate the original file-selector:
|
||||
* If there's an element of class '.sdpi-file-info'
|
||||
* show the filename there
|
||||
*/
|
||||
if (e.type === "file") {
|
||||
const info = sdpiItem.querySelector(".sdpi-file-info");
|
||||
if (info) {
|
||||
const s = returnValue.value.split("/").pop();
|
||||
info.innerText =
|
||||
s.length > 28
|
||||
? s.substr(0, 10) + "..." + s.substr(s.length - 10, s.length)
|
||||
: s;
|
||||
}
|
||||
}
|
||||
|
||||
sendValueToPlugin(returnValue, "sdpi_collection");
|
||||
}
|
||||
|
||||
function updateKeyForDemoCanvas(cnv) {
|
||||
sendValueToPlugin(
|
||||
{
|
||||
key: "your_canvas",
|
||||
value: cnv.toDataURL(),
|
||||
},
|
||||
"sdpi_collection"
|
||||
);
|
||||
}
|
||||
|
||||
/** Stream Deck software passes system-highlight color information
|
||||
* to Property Inspector. Here we 'inject' the CSS styles into the DOM
|
||||
* when we receive this information. */
|
||||
|
||||
function addDynamicStyles(clrs, fromWhere) {
|
||||
const node =
|
||||
document.getElementById("#sdpi-dynamic-styles") ||
|
||||
document.createElement("style");
|
||||
if (!clrs.mouseDownColor)
|
||||
clrs.mouseDownColor = fadeColor(clrs.highlightColor, -100);
|
||||
const clr = clrs.highlightColor.slice(0, 7);
|
||||
const clr1 = fadeColor(clr, 100);
|
||||
const clr2 = fadeColor(clr, 60);
|
||||
const metersActiveColor = fadeColor(clr, -60);
|
||||
|
||||
node.setAttribute("id", "sdpi-dynamic-styles");
|
||||
node.innerHTML = `
|
||||
|
||||
input[type="radio"]:checked + label span,
|
||||
input[type="checkbox"]:checked + label span {
|
||||
background-color: ${clrs.highlightColor};
|
||||
}
|
||||
|
||||
input[type="radio"]:active:checked + label span,
|
||||
input[type="radio"]:active + label span,
|
||||
input[type="checkbox"]:active:checked + label span,
|
||||
input[type="checkbox"]:active + label span {
|
||||
background-color: ${clrs.mouseDownColor};
|
||||
}
|
||||
|
||||
input[type="radio"]:active + label span,
|
||||
input[type="checkbox"]:active + label span {
|
||||
background-color: ${clrs.buttonPressedBorderColor};
|
||||
}
|
||||
|
||||
td.selected,
|
||||
td.selected:hover,
|
||||
li.selected:hover,
|
||||
li.selected {
|
||||
color: white;
|
||||
background-color: ${clrs.highlightColor};
|
||||
}
|
||||
|
||||
.sdpi-file-label > label:active,
|
||||
.sdpi-file-label.file:active,
|
||||
label.sdpi-file-label:active,
|
||||
label.sdpi-file-info:active,
|
||||
input[type="file"]::-webkit-file-upload-button:active,
|
||||
button:active {
|
||||
background-color: ${clrs.buttonPressedBackgroundColor};
|
||||
color: ${clrs.buttonPressedTextColor};
|
||||
border-color: ${clrs.buttonPressedBorderColor};
|
||||
}
|
||||
|
||||
::-webkit-progress-value,
|
||||
meter::-webkit-meter-optimum-value {
|
||||
background: linear-gradient(${clr2}, ${clr1} 20%, ${clr} 45%, ${clr} 55%, ${clr2})
|
||||
}
|
||||
|
||||
::-webkit-progress-value:active,
|
||||
meter::-webkit-meter-optimum-value:active {
|
||||
background: linear-gradient(${clr}, ${clr2} 20%, ${metersActiveColor} 45%, ${metersActiveColor} 55%, ${clr})
|
||||
}
|
||||
`;
|
||||
document.body.appendChild(node);
|
||||
}
|
||||
|
||||
/** UTILITIES */
|
||||
|
||||
/** Helper function to construct a list of running apps
|
||||
* from a template string.
|
||||
* -> information about running apps is received from the plugin
|
||||
*/
|
||||
|
||||
function sdpiCreateList(el, obj, cb) {
|
||||
if (el) {
|
||||
el.style.display = obj.value.length ? "block" : "none";
|
||||
Array.from(document.querySelectorAll(`.${el.id}`)).forEach((subel, i) => {
|
||||
subel.style.display = obj.value.length ? "flex" : "none";
|
||||
});
|
||||
if (obj.value.length) {
|
||||
el.innerHTML = `<div class="sdpi-item" ${obj.type ? `class="${obj.type}"` : ""
|
||||
} id="${obj.id || window.btoa(new Date().getTime().toString()).substr(0, 8)
|
||||
}">
|
||||
<div class="sdpi-item-label">${obj.label || ""}</div>
|
||||
<ul class="sdpi-item-value ${obj.selectionType ? obj.selectionType : ""
|
||||
}">
|
||||
${obj.value.map((e) => `<li>${e.name}</li>`).join("")}
|
||||
</ul>
|
||||
</div>`;
|
||||
setTimeout(function () {
|
||||
prepareDOMElements(el);
|
||||
if (cb) cb();
|
||||
}, 10);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (cb) cb();
|
||||
}
|
||||
|
||||
/** get a JSON property from a (dot-separated) string
|
||||
* Works on nested JSON, e.g.:
|
||||
* jsn = {
|
||||
* propA: 1,
|
||||
* propB: 2,
|
||||
* propC: {
|
||||
* subA: 3,
|
||||
* subB: {
|
||||
* testA: 5,
|
||||
* testB: 'Hello'
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* getPropFromString(jsn,'propC.subB.testB') will return 'Hello';
|
||||
*/
|
||||
const getPropFromString = (jsn, str, sep = ".") => {
|
||||
const arr = str.split(sep);
|
||||
return arr.reduce(
|
||||
(obj, key) => (obj && obj.hasOwnProperty(key) ? obj[key] : undefined),
|
||||
jsn
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
Quick utility to lighten or darken a color (doesn't take color-drifting, etc. into account)
|
||||
Usage:
|
||||
fadeColor('#061261', 100); // will lighten the color
|
||||
fadeColor('#200867'), -100); // will darken the color
|
||||
*/
|
||||
function fadeColor(col, amt) {
|
||||
const min = Math.min,
|
||||
max = Math.max;
|
||||
const num = parseInt(col.replace(/#/g, ""), 16);
|
||||
const r = min(255, max((num >> 16) + amt, 0));
|
||||
const g = min(255, max((num & 0x0000ff) + amt, 0));
|
||||
const b = min(255, max(((num >> 8) & 0x00ff) + amt, 0));
|
||||
return "#" + (g | (b << 8) | (r << 16)).toString(16).padStart(6, 0);
|
||||
}
|
||||
BIN
com.exension.hwinfo.sdPlugin/launch-hwinfo.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
41
com.exension.hwinfo.sdPlugin/manifest.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"SDKVersion": 2,
|
||||
"Software": {
|
||||
"MinimumVersion": "4.1"
|
||||
},
|
||||
"Actions": [
|
||||
{
|
||||
"Icon": "icon",
|
||||
"Name": "HWiNFO",
|
||||
"States": [
|
||||
{
|
||||
"Image": "defaultImage",
|
||||
"TitleAlignment": "top",
|
||||
"FontSize": "9",
|
||||
"TitleColor": "#b7b7b7",
|
||||
"ShowTitle": false
|
||||
}
|
||||
],
|
||||
"SupportedInMultiActions": false,
|
||||
"Tooltip": "Display sensor readings from HWiNFO",
|
||||
"UUID": "com.exension.hwinfo.reading"
|
||||
}
|
||||
],
|
||||
"Author": "shayne",
|
||||
"CodePathWin": "hwinfo.exe",
|
||||
"PropertyInspectorPath": "index_pi.html",
|
||||
"Description": "Display sensor readings from HWiNFO64. This plugin is not affiliated with HWiNFO64, for more information and to download HWiNFO64 visit https://www.hwinfo.com",
|
||||
"Name": "HWiNFO",
|
||||
"Icon": "pluginIcon",
|
||||
"URL": "https://github.com/shayne/hwinfo-streamdeck",
|
||||
"Version": "2.0.5",
|
||||
"ApplicationsToMonitor": {
|
||||
"windows": ["HWiNFO64.EXE", "HWiNFO64.exe"]
|
||||
},
|
||||
"OS": [
|
||||
{
|
||||
"Platform": "windows",
|
||||
"MinimumVersion": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
com.exension.hwinfo.sdPlugin/pluginIcon.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
com.exension.hwinfo.sdPlugin/pluginIcon@2x.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |