Update SpiderADB, fix site build
This commit is contained in:
parent
aced3385f1
commit
eecdf1f2fd
|
@ -1 +1,6 @@
|
|||
*.bak
|
||||
node_modules/
|
||||
/public/a/
|
||||
/public/s/
|
||||
/public/SpiderADB/
|
||||
/public/WuppiMini/
|
||||
|
|
15
Build.sh
15
Build.sh
|
@ -1,21 +1,12 @@
|
|||
#!/bin/sh
|
||||
for App in WuppiMini
|
||||
for App in SpiderADB WuppiMini
|
||||
do
|
||||
mkdir -p ./public/${App}
|
||||
cd ./src/${App}
|
||||
npm update
|
||||
npm install
|
||||
node ./index.js html
|
||||
cp ./index.js ./index.html ./node_modules/SpaccDotWeb/SpaccDotWeb.Server.js ../../public/${App}/
|
||||
cd ../..
|
||||
done
|
||||
for App in SpiderADB
|
||||
do
|
||||
mkdir -p ./public/${App}
|
||||
cd ./src/${App}
|
||||
sh ./Prepare.sh
|
||||
sh ./Requirements.sh
|
||||
cp -r $(sh ./Build.sh) ../../public/${App}/
|
||||
cd ../..
|
||||
done
|
||||
cp -r ./shared ./public/shared
|
||||
cd ./public
|
||||
node ../WriteRedirectPages.js
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
*.bak
|
|
@ -13,7 +13,7 @@
|
|||
<link rel="shortcut icon" href="../favicon.png" type="image/x-icon"/>
|
||||
<link href="../Assets/CSS/Dark.css" rel="stylesheet"/>
|
||||
<script src="../Assets/JS/RandomGIF.js"></script>
|
||||
<script src="../Assets/JS/Global.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
<style>
|
||||
.form > * { margin: 4px; }
|
||||
#SitesList, #PostsListMain { text-align: left; }
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<script src="../Assets/JS/Global.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
<style>
|
||||
@Media (Prefers-Color-Scheme: Light) {
|
||||
Body, TextArea {
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
<script src="../Assets/JS/Global.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="BtnFullscreen" onclick="ToggleFullscreen()">🎞️ Menu</button>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<link href="Bubbles.css" rel="stylesheet"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="../favicon.png"/>
|
||||
<link rel="manifest" href="./manifest.json"/>
|
||||
<script src="../Assets/JS/Global.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
<style>
|
||||
Body {
|
||||
Color: #FFFFFF;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<link rel="stylesheet" media="screen" href="css/telegram-web.css"/>
|
||||
<link rel="stylesheet" media="screen" href="css/MBViewer.css"/>
|
||||
<link rel="stylesheet" media="print" href="css/print.css"/>
|
||||
<script src="../Assets/JS/Global.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
</head>
|
||||
<body class="widget_frame_base tgme_webpreview emoji_image thin_box_shadow tme_mode no_transitions">
|
||||
<div class="tgme_background_wrap">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>🃏️ [Matrix] Sticker Helper</title>
|
||||
|
||||
<script src="../Assets/JS/Global.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
<script src="../../../SpaccDotWeb/SpaccDotWeb.Alt.js" module="SpaccDotWeb"></script><!-- offline -->
|
||||
<script src="//SpaccInc.gitlab.io/SpaccDotWeb/SpaccDotWeb.Alt.js" module="SpaccDotWeb"></script><!-- online -->
|
||||
<link rel="stylesheet" href="./paper.min.css"/>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<link rel="shortcut icon" href="../favicon.png" type="image/x-icon"/>
|
||||
<link href="../Assets/CSS/Dark.css" rel="stylesheet"/>
|
||||
<script src="../Assets/JS/RandomGIF.js"></script>
|
||||
<script src="../Assets/JS/Global.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="Content" style="text-align: center;">
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<link href="./Assets/CSS/Dark.css" rel="stylesheet"/>
|
||||
<script src="./Assets/JS/RandomGIF.js"></script>
|
||||
<script src="./Assets/JS/CurrentAge.js"></script>
|
||||
<script src="./Assets/JS/Global.js"></script>
|
||||
<script src="../shared/OctoHub-Global.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="ConfettiCanvas"></div>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
npm update
|
||||
npm install
|
||||
yes | npx esbuild
|
|
@ -1,13 +1,46 @@
|
|||
import * as Adb from "../../node_modules/@yume-chan/adb/esm/index.js";
|
||||
import * as AdbDaemonWebUsb from "../../node_modules/@yume-chan/adb-daemon-webusb/esm/index.js";
|
||||
import AdbWebCredentialStore from "../../node_modules/@yume-chan/adb-credential-web/esm/index.js";
|
||||
//window.WebADB = { Adb, AdbDaemonWebUsb, AdbWebCredentialStore };
|
||||
import * as Adb from '@yume-chan/adb';
|
||||
import * as AdbDaemonWebUsb from '@yume-chan/adb-daemon-webusb';
|
||||
import AdbWebCredentialStore from '@yume-chan/adb-credential-web';
|
||||
import { DecodeUtf8Stream } from '@yume-chan/stream-extra';
|
||||
|
||||
// TODO:
|
||||
// * warning on fail to claim USB interface (it may be because of other tabs, or a local adb server)
|
||||
// * warn or gracefully handle debug permission not granted
|
||||
// * package manager with install/uninstall/dump, debloat tool with default list and import/export
|
||||
// * fastboot shell and tools? possible?
|
||||
|
||||
(async function(){
|
||||
|
||||
const deviceSelect = $('select$deviceSelect$');
|
||||
const deviceConnect = $('button$deviceConnect$');
|
||||
const terminalOutput = $('textarea$terminalOutput$');
|
||||
|
||||
function resizeTerminal () {
|
||||
terminalOutput.style.height = `${window.innerHeight - ((48 + 8) * 4)}px`;
|
||||
}
|
||||
resizeTerminal();
|
||||
|
||||
window.addEventListener('resize', (function(){
|
||||
resizeTerminal();
|
||||
}));
|
||||
|
||||
$('input$terminalInput$').addEventListener('keydown', (async function(event){
|
||||
if (event.keyCode == 13) { // Enter
|
||||
const cmd = $('input$terminalInput$').value;
|
||||
terminalOutput.textContent += (cmd + '\n');
|
||||
const process = await Device.adb.subprocess.spawn(cmd);
|
||||
await process.stdout.pipeThrough(new DecodeUtf8Stream()).pipeTo(
|
||||
new WritableStream({ write(chunk) {
|
||||
terminalOutput.textContent += chunk;
|
||||
terminalOutput.scrollTop = terminalOutput.scrollHeight;
|
||||
} }),
|
||||
);
|
||||
terminalOutput.textContent += '\n> ';
|
||||
$('input$terminalInput$').value = null;
|
||||
};
|
||||
}));
|
||||
|
||||
let Device = {};
|
||||
const CredentialStore = new AdbWebCredentialStore();
|
||||
|
||||
const UsbManager = AdbDaemonWebUsb.AdbDaemonWebUsbDeviceManager.BROWSER;
|
||||
|
@ -16,7 +49,7 @@ if (!UsbManager) {
|
|||
<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/USB#browser_compatibility">WebUSB is not supported</a> in this browser, so the app cannot work.
|
||||
Consider using an <a target="_blank" href="https://chromium.woolyss.com">up-to-date Chromium-based</a> one.
|
||||
</p><p>
|
||||
Alternatively, these alternative ADB solutions might work for you:
|
||||
Otherwise, the following alternative ADB solutions might work for you:
|
||||
</p><ul>
|
||||
<li><a target="_blank" href="https://www.makeuseof.com/use-adb-over-wifi-android/">
|
||||
How to Set Up and Use ADB Wirelessly With Android
|
||||
|
@ -28,17 +61,41 @@ if (!UsbManager) {
|
|||
LADB — Local ADB Shell
|
||||
</a></li>
|
||||
</ul>`;
|
||||
return;
|
||||
return; // kill the app
|
||||
}
|
||||
|
||||
new AdbDaemonWebUsb.AdbDaemonWebUsbDeviceWatcher(refreshDeviceSection, navigator.usb);
|
||||
new AdbDaemonWebUsb.AdbDaemonWebUsbDeviceWatcher((async function(connectedDevice){
|
||||
if (!connectedDevice) {
|
||||
await disconnectDevice();
|
||||
}
|
||||
await refreshDeviceSection();
|
||||
}), navigator.usb);
|
||||
|
||||
async function connectAuthorizeDevice () {
|
||||
if (deviceSelect.selectedIndex > 0) {
|
||||
Device.device = await getDevice();
|
||||
try {
|
||||
Device.connection = await Device.device.connect();
|
||||
Device.transport = await Adb.AdbDaemonTransport.authenticate({ connection: Device.connection, credentialStore: CredentialStore });
|
||||
Device.adb = new Adb.Adb(Device.transport);
|
||||
} catch (err) {
|
||||
$('[name="deviceStatus"]').innerHTML = 'An error occurred while trying to establish a device connection. Please ensure that no other processes or browser tabs on this system are currently using the device, then retry.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getDevice () {
|
||||
const devices = await UsbManager.getDevices();
|
||||
const connection = await devices[deviceSelect.selectedIndex - 1].connect();
|
||||
const transport = await Adb.AdbDaemonTransport.authenticate({ connection, credentialStore: CredentialStore });
|
||||
const adb = new Adb.Adb(transport);
|
||||
$('$androidVersion$').innerHTML = `<b>Android version</b>: ${await adb.getProp("ro.build.version.release")}`;
|
||||
const device = devices[deviceSelect.selectedIndex - 1];
|
||||
return device;
|
||||
}
|
||||
|
||||
function disconnectDevice () {
|
||||
const connection = (Device.adb || Device.transport || Device.connection);
|
||||
if (connection) {
|
||||
Device = {};
|
||||
return connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshDeviceSelect () {
|
||||
|
@ -52,24 +109,51 @@ async function refreshDeviceSelect () {
|
|||
deviceOption.textContent = `${device.raw.productName} [${device.raw.serialNumber}]`;
|
||||
deviceSelect.appendChild(deviceOption);
|
||||
});
|
||||
deviceSelect.onchange = refreshDeviceInfo;
|
||||
deviceSelect.onchange = onSwitchDevice;
|
||||
deviceSelect.disabled = false;
|
||||
} else {
|
||||
deviceSelect.innerHTML = '<option>[📵️ No connected devices]</option>';
|
||||
}
|
||||
}
|
||||
|
||||
async function onSwitchDevice () {
|
||||
await disconnectDevice();
|
||||
await connectAuthorizeDevice();
|
||||
await refreshDeviceInfo();
|
||||
}
|
||||
|
||||
async function refreshDeviceInfo () {
|
||||
if (deviceSelect.selectedIndex > 0) {
|
||||
const devices = await UsbManager.getDevices();
|
||||
const device = devices[deviceSelect.selectedIndex - 1];
|
||||
const device = await getDevice();
|
||||
$('$deviceOem$').innerHTML = `<b>Brand</b>: ${device.raw.manufacturerName}`;
|
||||
$('$deviceModel$').innerHTML = `<b>Model</b>: ${device.raw.productName}`;
|
||||
$('$deviceSerial$').innerHTML = `<b>Serial number</b>: ${device.raw.serialNumber}`;
|
||||
//$('[name="deviceStatus"]').innerHTML = 'Connected to device.';
|
||||
//$('$deviceInfo$').hidden = false;
|
||||
if (Device.adb) {
|
||||
$('$deviceStatus$').innerHTML = null;
|
||||
// $('$devicePropDump$').innerHTML = null;
|
||||
$('$androidVersion$').innerHTML = `<b>Android version</b>: ${await Device.adb.getProp('ro.build.version.release')}`;
|
||||
$('$androidApi$').innerHTML = `<b>API version</b>: ${await Device.adb.getProp('ro.build.version.sdk')}`;
|
||||
$('$androidInfo$').hidden = false;
|
||||
$('$connectReminder$').hidden = true;
|
||||
terminalOutput.disabled = false;
|
||||
terminalOutput.textContent += '> ';
|
||||
$('input$terminalInput$').disabled = false;
|
||||
/* for (const line of (await Device.adb.getProp()).split('\n')) {
|
||||
const elem = document.createElement('li');
|
||||
elem.textContent = line;
|
||||
$('$devicePropDump$').appendChild(elem);
|
||||
} */
|
||||
} else {
|
||||
$('$deviceInfo$').hidden = true;
|
||||
}
|
||||
$('$deviceInfo$').hidden = false;
|
||||
} else {
|
||||
//$('[name="deviceStatus"]').innerHTML = null;
|
||||
$('$deviceStatus$').innerHTML = null;
|
||||
$('$connectReminder$').hidden = false;
|
||||
terminalOutput.disabled = true;
|
||||
$('input$terminalInput$').disabled = true;
|
||||
$('$deviceInfo$').hidden = true;
|
||||
}
|
||||
}
|
||||
|
@ -85,10 +169,10 @@ deviceConnect.onclick = (async function(){
|
|||
if (!device) {
|
||||
return;
|
||||
}
|
||||
await disconnectDevice();
|
||||
await refreshDeviceSection();
|
||||
deviceSelect.selectedIndex = (deviceSelect.children.length - 1);
|
||||
deviceSelect.onchange();
|
||||
await connectAuthorizeDevice();
|
||||
});
|
||||
deviceConnect.disabled = false;
|
||||
|
||||
|
|
|
@ -54,28 +54,30 @@ a[data-action-section] {
|
|||
|
||||
/* https://github.com/ZMYaro/holo-web/issues/1#issuecomment-12778881 */
|
||||
input[type="text"] {
|
||||
background: transparent;
|
||||
border-width: 0 0 1px;
|
||||
border-color: #7F7F7F;
|
||||
border-style: solid;
|
||||
line-height: 36px;
|
||||
padding: 0px 4px;
|
||||
box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;
|
||||
width: 200px;
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 32px;
|
||||
margin: 6px;
|
||||
background: transparent;
|
||||
color: white;
|
||||
border-width: 0 0 1px;
|
||||
border-color: #7F7F7F;
|
||||
border-style: solid;
|
||||
line-height: 36px;
|
||||
padding: 0px 4px;
|
||||
box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;
|
||||
width: 200px;
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 32px;
|
||||
margin: 6px;
|
||||
}
|
||||
textarea {
|
||||
background: transparent;
|
||||
border-width: 0 0 1px;
|
||||
border-color: #7F7F7F;
|
||||
border-style: solid;
|
||||
padding: 4px 4px;
|
||||
box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;
|
||||
width: 250px;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
margin: 6px;
|
||||
background: transparent;
|
||||
color: white;
|
||||
border-width: 0 0 1px;
|
||||
border-color: #7F7F7F;
|
||||
border-style: solid;
|
||||
padding: 4px 4px;
|
||||
box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;
|
||||
width: 250px;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
margin: 6px;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ $('::[data-action-section]').forEach(function(actionSectionElem){
|
|||
sectionElem.dataset.open = false;
|
||||
});
|
||||
sectionTargetElem.dataset.open = 'open';
|
||||
location.hash = `/${sectionTargetName}`;
|
||||
refreshDisplaySections(sectionTargetName);
|
||||
}));
|
||||
});
|
||||
|
@ -39,4 +40,9 @@ function refreshDisplaySections (sectionTargetName) {
|
|||
}
|
||||
refreshDisplaySections();
|
||||
|
||||
var sectionHash = location.hash.slice(2).split('/')[0];
|
||||
if (sectionHash) {
|
||||
$(`[data-action-section="${sectionHash}"]`).click();
|
||||
}
|
||||
|
||||
}));
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
<script src="./util.js"></script>
|
||||
<script src="./holo-web/holo-extra-octt.js"></script>
|
||||
<script src="./holo-web/holo-touch.js"></script>
|
||||
<script src="../Assets/JS/Global.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
<style>
|
||||
body { overflow-x: hidden; }
|
||||
.floatRight { float: right; }
|
||||
</style>
|
||||
</head>
|
||||
|
@ -31,47 +32,76 @@
|
|||
<li><button data-action-section="devices">
|
||||
📱️ Devices
|
||||
</button></li>
|
||||
<!-- <li><button data-action-section="terminal">
|
||||
<li><button data-action-section="terminal">
|
||||
⌨️ Terminal
|
||||
</button></li>
|
||||
<!-- <li><button data-action-section="files">
|
||||
📄 Files
|
||||
</button></li> -->
|
||||
<!-- <li><button data-action-section="packages">
|
||||
📦 Packages
|
||||
</button></li> -->
|
||||
<li><button data-action-section="about">
|
||||
❓️ About
|
||||
</button></li>
|
||||
<li>
|
||||
<i><!--More-->Actual features coming soon!</i>
|
||||
<i>More features coming soon!</i>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="holo-body">
|
||||
<p name="connectReminder" data-display-sections="terminal">
|
||||
<p name="connectReminder" data-display-sections="terminal packages">
|
||||
You must <a data-action-section="devices">connect and authorize a device</a> first.
|
||||
</p>
|
||||
<section class="holo-section" data-section="devices" data-open="open">
|
||||
<div name="browserWarning"><p></p></div>
|
||||
<select name="deviceSelect" disabled="true"></select>
|
||||
<button name="deviceConnect" disabled="true">
|
||||
Connect New Device
|
||||
</button>
|
||||
<p name="deviceStatus"></p>
|
||||
<ul name="deviceInfo" hidden="true">
|
||||
<li name="deviceOem"></li>
|
||||
<li name="deviceModel"></li>
|
||||
<li name="deviceSerial"></li>
|
||||
<li name="androidVersion"></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="holo-section" data-section="terminal">
|
||||
<textarea readonly="true" disabled="true" style="width: 100%; margin-left: 0; margin-right: 0;"></textarea>
|
||||
<input type="text" disabled="true" style="width: 100%; margin-left: 0; margin-right: 0;"/>
|
||||
</section>
|
||||
<section class="holo-section" data-section="about">
|
||||
<p>SpiderADB is an user-friendly webapp for connecting to devices via the Android Debug Bridge, straight from a browser. More infos coming soon.</p>
|
||||
<h3>Changelog</h3>
|
||||
<h4>2024-04-16</h4><ul>
|
||||
<li>Introduced the basic Terminal.</li>
|
||||
<li>Slight improvements to the user experience with better error handling.</li>
|
||||
</ul>
|
||||
<h4>2024-04-14</h4><ul>
|
||||
<li>First WIP version, with Android ICS Holo UI, allows simply connecting to devices and shows basic info.</li>
|
||||
<li>Introduced sections: Devices, About.</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="holo-section" data-section="devices" data-open="open">
|
||||
<div name="browserWarning"><p></p></div>
|
||||
<p name="deviceStatus"></p>
|
||||
<select name="deviceSelect" disabled="true"></select>
|
||||
<button name="deviceConnect" disabled="true">
|
||||
Connect New Device
|
||||
</button>
|
||||
<!-- <button>Connect via Network</button> -->
|
||||
<section name="deviceInfo" hidden="true">
|
||||
<ul>
|
||||
<li name="deviceOem"></li>
|
||||
<li name="deviceModel"></li>
|
||||
<li name="deviceSerial"></li>
|
||||
<div name="androidInfo" hidden="true">
|
||||
<li name="androidVersion"></li>
|
||||
<li name="androidApi"></li>
|
||||
</div>
|
||||
</ul>
|
||||
<!-- <details>
|
||||
<summary><code>getprop</code> Info dump</summary>
|
||||
<ul name="devicePropDump"></ul>
|
||||
</details> -->
|
||||
</section>
|
||||
</section>
|
||||
<section class="holo-section" data-section="terminal">
|
||||
<textarea name="terminalOutput" readonly="true" disabled="true" placeholder="Terminal output will be displayed here." style="width: 100%; margin-left: 0; margin-right: 0;"></textarea>
|
||||
<input name="terminalInput" type="text" disabled="true" placeholder="> Input any command..." style="width: 100%; margin-left: 0; margin-right: 0;"/>
|
||||
</section>
|
||||
<section class="holo-section" data-section="packages">
|
||||
<!-- TODO buttons -->
|
||||
<ul class="holo-list" name="packageList">
|
||||
<li>Test <input type="checkbox"/></li>
|
||||
</ul>
|
||||
<section class="holo-subsection" name="packageInfo">
|
||||
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<script src="./bundle.js"></script>
|
||||
</body>
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
"dependencies": {
|
||||
"@yume-chan/adb": "^0.0.23",
|
||||
"@yume-chan/adb-credential-web": "^0.0.23",
|
||||
"@yume-chan/adb-daemon-webusb": "^0.0.23"
|
||||
"@yume-chan/adb-daemon-webusb": "^0.0.23",
|
||||
"@yume-chan/stream-extra": "^0.0.23"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/w3c-web-usb": {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
"dependencies": {
|
||||
"@yume-chan/adb": "^0.0.23",
|
||||
"@yume-chan/adb-credential-web": "^0.0.23",
|
||||
"@yume-chan/adb-daemon-webusb": "^0.0.23"
|
||||
"@yume-chan/adb-daemon-webusb": "^0.0.23",
|
||||
"@yume-chan/stream-extra": "^0.0.23"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
node ./index.js html > /dev/null
|
||||
echo index.js index.html node_modules/SpaccDotWeb/SpaccDotWeb.Server.js
|
|
@ -36,6 +36,7 @@ const newHtmlPage = (content, title) => `<!DOCTYPE html><html><head>
|
|||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>${title ? `${title} — ` : ''}${appName}</title>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
|
|
Loading…
Reference in New Issue