Update site structure, update global js to add domain warning, update SpiderADB
|
@ -1,6 +1,3 @@
|
|||
*.bak
|
||||
node_modules/
|
||||
/public/a/
|
||||
/public/s/
|
||||
/public/SpiderADB/
|
||||
/public/WuppiMini/
|
||||
/public/
|
||||
|
|
18
Build.sh
|
@ -1,12 +1,24 @@
|
|||
#!/bin/sh
|
||||
for App in SpiderADB WuppiMini
|
||||
SourceApps="SpiderADB WuppiMini"
|
||||
HubSdkApps="$(SourceApps) Ecoji MatrixStickerHelper"
|
||||
|
||||
rm -vrf ./public || true
|
||||
cp -vr ./static ./public
|
||||
cp -vr ./shared ./public/shared
|
||||
|
||||
for App in $(SourceApps)
|
||||
do
|
||||
mkdir -p ./public/${App}
|
||||
cd ./src/${App}
|
||||
cd ./source/${App}
|
||||
sh ./Requirements.sh
|
||||
cp -r $(sh ./Build.sh) ../../public/${App}/
|
||||
cd ../..
|
||||
done
|
||||
cp -r ./shared ./public/shared
|
||||
|
||||
cd ./public
|
||||
node ../WriteRedirectPages.js
|
||||
|
||||
for App in $(HubSdkApps)
|
||||
do
|
||||
echo # TODO write manifest.json files
|
||||
done
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
window.addEventListener('load', (function(){
|
||||
|
||||
if (!['', 'hub.octt.eu.org'].includes(location.host)) {
|
||||
var noticeElem = document.createElement('p');
|
||||
noticeElem.style = `
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
color: black;
|
||||
background-color: thistle;
|
||||
font-size: initial;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
`;
|
||||
noticeElem.innerHTML = `You are viewing this page on the secondary/backup domain. <a style="color: darkblue;" href="https://hub.octt.eu.org${location.pathname}">Open it on hub.octt.eu.org</a>.
|
||||
<button style="
|
||||
float: right;
|
||||
height: 1.25em;
|
||||
margin: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
" onclick="this.parentElement.remove()">X</button>`;
|
||||
document.body.appendChild(noticeElem);
|
||||
}
|
||||
|
||||
}));
|
|
@ -1,48 +1,54 @@
|
|||
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';
|
||||
import { DecodeUtf8Stream, WrapReadableStream, WrapConsumableStream } from '@yume-chan/stream-extra';
|
||||
import { PackageManager } from '@yume-chan/android-bin';
|
||||
|
||||
// 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?
|
||||
// * logs for Packages section?
|
||||
|
||||
(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;
|
||||
};
|
||||
}));
|
||||
$('button$apkInstall$').onclick = (async function(){
|
||||
// TODO show info popup before actually installing, also allow installing via drag&drop on packages section
|
||||
const fileInput = $('button$apkInstall$').querySelector('input');
|
||||
fileInput.onchange = (function(event){
|
||||
const count = event.target.files.length;
|
||||
if (!count > 0) {
|
||||
return;
|
||||
}
|
||||
alert(`Installing ${count} package(s)...`);
|
||||
const pm = new PackageManager(Device.adb);
|
||||
Array.from(event.target.files).forEach(async function(file, index){
|
||||
try {
|
||||
await pm.installStream(file.size, (new WrapReadableStream(file.stream())).pipeThrough(new WrapConsumableStream()));
|
||||
alert(`Successfully installed package ${index + 1} of ${count}.`);
|
||||
refreshPackagesList();
|
||||
} catch (err) {
|
||||
alert(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
fileInput.click();
|
||||
});
|
||||
|
||||
let Device = {};
|
||||
const CredentialStore = new AdbWebCredentialStore();
|
||||
|
||||
function resizeTerminal () {
|
||||
const divider = (Device.adb ? 2 : 3);
|
||||
terminalOutput.style.height = `${window.innerHeight - ((48 + 8) * divider)}px`;
|
||||
}
|
||||
window.addEventListener('resize', resizeTerminal);
|
||||
resizeTerminal();
|
||||
|
||||
const UsbManager = AdbDaemonWebUsb.AdbDaemonWebUsbDeviceManager.BROWSER;
|
||||
if (!UsbManager) {
|
||||
$('div$browserWarning$').innerHTML = `<p>
|
||||
|
@ -79,8 +85,10 @@ async function connectAuthorizeDevice () {
|
|||
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.';
|
||||
$('p$deviceStatus$').textContent = '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.';
|
||||
}
|
||||
} else {
|
||||
$('p$deviceStatus$').textContent = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,15 +111,18 @@ async function refreshDeviceSelect () {
|
|||
deviceSelect.innerHTML = null;
|
||||
const devices = await UsbManager.getDevices();
|
||||
if (devices.length) {
|
||||
$('p$deviceStatus$').textContent = null;
|
||||
deviceSelect.innerHTML = '<option>[📲️ Select a connected device]</option>';
|
||||
devices.forEach(function(device, index){
|
||||
var deviceOption = document.createElement('option');
|
||||
const deviceOption = document.createElement('option');
|
||||
deviceOption.textContent = `${device.raw.productName} [${device.raw.serialNumber}]`;
|
||||
deviceSelect.appendChild(deviceOption);
|
||||
});
|
||||
deviceSelect.onchange = onSwitchDevice;
|
||||
deviceSelect.disabled = false;
|
||||
} else {
|
||||
// TODO probably put this warning elsewhere? because it seems like the browser can see even Androids with ADB disabled, obviously they won't be able to connect
|
||||
$('p$deviceStatus$').innerHTML = 'Connect a debuggable Android device via USB to continue. (Read "<a target="_blank" href="https://www.lifewire.com/enable-usb-debugging-android-4690927#toc-how-to-enable-usb-debugging-on-android">How to Enable USB Debugging on Android</a>" for help).';
|
||||
deviceSelect.innerHTML = '<option>[📵️ No connected devices]</option>';
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +134,8 @@ async function onSwitchDevice () {
|
|||
}
|
||||
|
||||
async function refreshDeviceInfo () {
|
||||
if (deviceSelect.selectedIndex > 0) {
|
||||
let onDevice = (deviceSelect.selectedIndex > 0);
|
||||
if (onDevice) {
|
||||
const device = await getDevice();
|
||||
$('$deviceOem$').innerHTML = `<b>Brand</b>: ${device.raw.manufacturerName}`;
|
||||
$('$deviceModel$').innerHTML = `<b>Model</b>: ${device.raw.productName}`;
|
||||
|
@ -133,29 +145,38 @@ async function refreshDeviceInfo () {
|
|||
if (Device.adb) {
|
||||
$('$deviceStatus$').innerHTML = null;
|
||||
// $('$devicePropDump$').innerHTML = null;
|
||||
$('$deviceCpuAbis$').innerHTML = `<b>CPU ABIs</b>: ${await Device.adb.getProp('ro.system.product.cpu.abilist')}`;
|
||||
$('$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')}`;
|
||||
$('$androidApi$').innerHTML = `<b>SDK API version</b>: ${await Device.adb.getProp('ro.build.version.sdk')}`;
|
||||
//$('$androidNickname$').innerHTML = `<b>Device name</b>: ${await Device.adb.getProp('persist.sys.device_name')}`;
|
||||
$('$androidBuildDate$').innerHTML = `<b>Build date</b>: ${await Device.adb.getProp('ro.vendor.build.date')}`;
|
||||
$('$androidBuildFingerprint$').innerHTML = `<b>Build fingerprint</b>: ${await Device.adb.getProp('ro.vendor.build.fingerprint')}`;
|
||||
$('$androidInfo$').hidden = false;
|
||||
$('$connectReminder$').hidden = true;
|
||||
terminalOutput.disabled = false;
|
||||
terminalOutput.textContent += '> ';
|
||||
$('input$terminalInput$').disabled = false;
|
||||
terminalOutput.textContent += (terminalOutput.textContent ? '\n> ' : '> ');
|
||||
$('button$clearTerminal$').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;
|
||||
onDevice = false;
|
||||
}
|
||||
$('$deviceInfo$').hidden = false;
|
||||
} else {
|
||||
$('$deviceStatus$').innerHTML = null;
|
||||
//$('$deviceStatus$').innerHTML = null;
|
||||
$('$connectReminder$').hidden = false;
|
||||
terminalOutput.disabled = true;
|
||||
$('input$terminalInput$').disabled = true;
|
||||
$('$deviceInfo$').hidden = true;
|
||||
}
|
||||
toggleDeviceElems(onDevice);
|
||||
}
|
||||
|
||||
function toggleDeviceElems (enabled) {
|
||||
$('$deviceInfo$').hidden = !enabled;
|
||||
$('button$apkInstall$').disabled = !enabled;
|
||||
$('input$terminalInput$').disabled = !enabled;
|
||||
resizeTerminal();
|
||||
}
|
||||
|
||||
async function refreshDeviceSection () {
|
||||
|
@ -164,7 +185,7 @@ async function refreshDeviceSection () {
|
|||
}
|
||||
refreshDeviceSection();
|
||||
|
||||
deviceConnect.onclick = (async function(){
|
||||
$('button$deviceConnect$').onclick = (async function(){
|
||||
const device = await UsbManager.requestDevice();
|
||||
if (!device) {
|
||||
return;
|
||||
|
@ -174,6 +195,60 @@ deviceConnect.onclick = (async function(){
|
|||
deviceSelect.selectedIndex = (deviceSelect.children.length - 1);
|
||||
deviceSelect.onchange();
|
||||
});
|
||||
deviceConnect.disabled = false;
|
||||
$('button$deviceConnect$').disabled = false;
|
||||
|
||||
$('input$terminalInput$').addEventListener('keydown', (async function(event){
|
||||
if (event.keyCode == 13) { // Enter
|
||||
const cmd = $('input$terminalInput$').value;
|
||||
if (!terminalOutput.textContent) {
|
||||
terminalOutput.textContent += '> ';
|
||||
}
|
||||
terminalOutput.textContent += (cmd + '\n');
|
||||
const process = await Device.adb.subprocess.spawn(cmd);
|
||||
const processWriteToTerminal = () => new WritableStream({ write(chunk) {
|
||||
terminalOutput.textContent += chunk;
|
||||
terminalOutput.scrollTop = terminalOutput.scrollHeight;
|
||||
$('button$clearTerminal$').disabled = false;
|
||||
} });
|
||||
await process.stdout.pipeThrough(new DecodeUtf8Stream()).pipeTo(processWriteToTerminal());
|
||||
await process.stderr.pipeThrough(new DecodeUtf8Stream()).pipeTo(processWriteToTerminal());
|
||||
terminalOutput.textContent += '\n> ';
|
||||
terminalOutput.scrollTop = terminalOutput.scrollHeight;
|
||||
$('input$terminalInput$').value = null;
|
||||
};
|
||||
}));
|
||||
|
||||
$('button$clearTerminal$').onclick = (function(){
|
||||
terminalOutput.textContent = '';
|
||||
$('button$clearTerminal$').disabled = true;
|
||||
});
|
||||
|
||||
$('button$wrapTerminal$').onclick = (function(){
|
||||
terminalOutput.style.textWrap = (terminalOutput.style.textWrap ? '' : 'nowrap');
|
||||
terminalOutput.scrollTop = terminalOutput.scrollHeight;
|
||||
});
|
||||
|
||||
async function refreshPackagesList () {
|
||||
$('ul$packageList$').innerHTML = null;
|
||||
const pm = new PackageManager(Device.adb);
|
||||
const list = await pm.listPackages();
|
||||
let result = await list.next();
|
||||
while (!result.done) {
|
||||
var packageElem = document.createElement('li');
|
||||
packageElem.innerHTML = `${result.value.packageName}<!-- <input type="checkbox" class="floatRight"/>-->`;
|
||||
/* packageElem.querySelector('input').onclick = (function(){
|
||||
// TODO: hide or show action buttons that do actions on selected elements if there is none or at least one
|
||||
}); */
|
||||
$('ul$packageList$').appendChild(packageElem);
|
||||
result = await list.next();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('hashchange', (async function(){
|
||||
const sectionHash = location.hash.slice(2).split('/')[0];
|
||||
if (Device.adb && sectionHash === 'packages' /* && !$('ul$packageList$').innerHTML */) {
|
||||
refreshPackagesList();
|
||||
}
|
||||
}));
|
||||
|
||||
})();
|
|
@ -27,7 +27,7 @@ a[data-action-section] {
|
|||
/* width: 60%; */
|
||||
height: 100vh;
|
||||
z-index: 1;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.holo-sidebar[data-open="open"], .holo-sideBar[data-open="open"] {
|
||||
|
@ -37,7 +37,7 @@ a[data-action-section] {
|
|||
.holo-sidebar .holo-list, .holo-sideBar .holo-list {
|
||||
width: 60%;
|
||||
height: 100vh;
|
||||
background: black;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
|
||||
.actionBar .holo-title.holo-menu, .holo-actionBar .holo-title.holo-menu {
|
|
@ -1,13 +1,17 @@
|
|||
window.addEventListener('load', (function() {
|
||||
|
||||
var initialSectionName = $('[data-section][data-open]').dataset.section;
|
||||
|
||||
$('::[data-action-sidebar]').forEach(function(actionSidebarElem){
|
||||
var sidebarElem = $('[data-sidebar="' + actionSidebarElem.dataset.actionSidebar + '"]');
|
||||
actionSidebarElem.onclick = sidebarElem.onclick = (function(){
|
||||
function toggleSidebar () {
|
||||
sidebarElem.dataset.open = (sidebarElem.dataset.open !== 'open' ? 'open' : false);
|
||||
});
|
||||
sidebarElem.querySelector('.holo-list').onclick = (function(event){
|
||||
}
|
||||
actionSidebarElem.addEventListener('click', toggleSidebar);
|
||||
sidebarElem.addEventListener('click', toggleSidebar);
|
||||
sidebarElem.querySelector('.holo-list').addEventListener('click', (function(event){
|
||||
event.stopPropagation();
|
||||
});
|
||||
}));
|
||||
arrayFrom(sidebarElem.querySelectorAll('.holo-list li button, .holo-list li [role="button"]')).forEach(function(buttonElem){
|
||||
buttonElem.addEventListener('click', (function(){
|
||||
sidebarElem.dataset.open = false;
|
||||
|
@ -40,9 +44,11 @@ function refreshDisplaySections (sectionTargetName) {
|
|||
}
|
||||
refreshDisplaySections();
|
||||
|
||||
var sectionHash = location.hash.slice(2).split('/')[0];
|
||||
if (sectionHash) {
|
||||
$(`[data-action-section="${sectionHash}"]`).click();
|
||||
function hashChange () {
|
||||
var sectionHash = location.hash.slice(2).split('/')[0];
|
||||
$(`[data-action-section="${sectionHash || initialSectionName}"]`).click();
|
||||
}
|
||||
window.addEventListener('hashchange', hashChange);
|
||||
hashChange();
|
||||
|
||||
}));
|
Before Width: | Height: | Size: 98 B After Width: | Height: | Size: 98 B |
|
@ -14,8 +14,16 @@
|
|||
<script src="./holo-web/holo-touch.js"></script>
|
||||
<script src="../../shared/OctoHub-Global.js"></script>
|
||||
<style>
|
||||
body { overflow-x: hidden; }
|
||||
.floatRight { float: right; }
|
||||
body { overflow-x: hidden; padding-bottom: 0; }
|
||||
ul.holo-list li input[type="checkbox"].floatRight { margin-top: 0; }
|
||||
section.holo-sideBar > ul.holo-list { overflow-y: auto; }
|
||||
[name="terminalInput"], [name="terminalOutput"] {
|
||||
width: 100% !important;
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
resize: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -26,6 +34,16 @@
|
|||
<!-- <button class="floatRight" data-display-sections="terminal">
|
||||
Tabs
|
||||
</button> -->
|
||||
<button class="floatRight" data-display-sections="terminal" name="clearTerminal" disabled="true">
|
||||
Clear
|
||||
</button>
|
||||
<button class="floatRight" data-display-sections="terminal" name="wrapTerminal">
|
||||
Wrap
|
||||
</button>
|
||||
<button class="floatRight" data-display-sections="packages" name="apkInstall">
|
||||
<input type="file" hidden="true" multiple="true" accept=".apk, application/vnd.android.package-archive"/>
|
||||
Install APK(s)
|
||||
</button>
|
||||
</header>
|
||||
<section class="holo-sideBar" data-sidebar="sidebar">
|
||||
<ul class="holo-list">
|
||||
|
@ -38,9 +56,9 @@
|
|||
<!-- <li><button data-action-section="files">
|
||||
📄 Files
|
||||
</button></li> -->
|
||||
<!-- <li><button data-action-section="packages">
|
||||
📦 Packages
|
||||
</button></li> -->
|
||||
<li><button data-action-section="packages">
|
||||
📦 Packages <small>(WIP)</small>
|
||||
</button></li>
|
||||
<li><button data-action-section="about">
|
||||
❓️ About
|
||||
</button></li>
|
||||
|
@ -54,15 +72,31 @@
|
|||
You must <a data-action-section="devices">connect and authorize a device</a> first.
|
||||
</p>
|
||||
<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>
|
||||
<p>SpiderADB is an user-friendly webapp for connecting to devices via the Android Debug Bridge, straight from a browser.</p>
|
||||
<!-- TODO features -->
|
||||
<p>Here are some additional tips and tricks you might find useful to make the most out of this app:</p><ul>
|
||||
<li><a target="_blank" href="https://dev.to/larsonzhong/most-complete-adb-commands-4pcg">Most complete ADB command manual</a></li>
|
||||
</ul>
|
||||
<h3>Open Source and Credits</h3>
|
||||
<p>
|
||||
This app is open-source and made with mostly-vanilla web technologies. You can find the full source code on my Git repo: <a href="https://gitlab.com/octospacc/octospacc.gitlab.io/-/tree/master/source/SpiderADB/">https://gitlab.com/octospacc/octospacc.gitlab.io/-/tree/master/source/SpiderADB/</a>.
|
||||
<p>Also, this app wouldn't have been possible without these third-party components, of which the license is specified in brackets:</p><ul>
|
||||
<li><a target="_blank" href="https://github.com/yume-chan/ya-webadb">Tango</a> [MIT]: ADB port for the web</li>
|
||||
<li><a target="_blank" href="https://github.com/tango-adb/old-demo">Tango Demo (Old)</a> [MIT]: the previous official Tango demo webapp, helpful for writing my app since the Tango documentation is pretty lacking</li>
|
||||
<li><a target="_blank" href="https://github.com/zmyaro/holo-web">Holo Web</a> [MIT]: stylesheets for recreating the Android Holo theme on the web</li>
|
||||
</ul>
|
||||
<h3>Changelog</h3>
|
||||
<h4>2024-04-18</h4><ul>
|
||||
<li>Improve Terminal logic, which now also shows stdout, scaling, and add a Clear feature.</li>
|
||||
<li>Introduce Packages menu, listing all installed packages' names, and allow installing (multiple) APKs files.</li>
|
||||
</ul>
|
||||
<h4>2024-04-16</h4><ul>
|
||||
<li>Introduced the basic Terminal.</li>
|
||||
<li>Introduce 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>
|
||||
<li>Introduce sections: Devices, About.</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="holo-section" data-section="devices" data-open="open">
|
||||
|
@ -81,6 +115,10 @@
|
|||
<div name="androidInfo" hidden="true">
|
||||
<li name="androidVersion"></li>
|
||||
<li name="androidApi"></li>
|
||||
<!-- <li name="androidNickname"></li> -->
|
||||
<li name="androidBuildDate"></li>
|
||||
<li name="androidBuildFingerprint"></li>
|
||||
<li name="deviceCpuAbis"></li>
|
||||
</div>
|
||||
</ul>
|
||||
<!-- <details>
|
||||
|
@ -90,14 +128,12 @@
|
|||
</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;"/>
|
||||
<textarea name="terminalOutput" readonly="true" disabled="true" placeholder="Terminal output will be displayed here."></textarea>
|
||||
<input name="terminalInput" type="text" disabled="true" placeholder="> Input any command..."/>
|
||||
</section>
|
||||
<section class="holo-section" data-section="packages">
|
||||
<!-- TODO buttons -->
|
||||
<ul class="holo-list" name="packageList">
|
||||
<li>Test <input type="checkbox"/></li>
|
||||
</ul>
|
||||
<ul class="holo-list" name="packageList"></ul><!--<li>Test <input type="checkbox" class="floatRight"/></li><!--<label><li>Test <input type="checkbox"/></li></label>-->
|
||||
<section class="holo-subsection" name="packageInfo">
|
||||
|
||||
</section>
|
|
@ -8,6 +8,7 @@
|
|||
"@yume-chan/adb": "^0.0.23",
|
||||
"@yume-chan/adb-credential-web": "^0.0.23",
|
||||
"@yume-chan/adb-daemon-webusb": "^0.0.23",
|
||||
"@yume-chan/android-bin": "^0.0.23",
|
||||
"@yume-chan/stream-extra": "^0.0.23"
|
||||
}
|
||||
},
|
||||
|
@ -50,6 +51,17 @@
|
|||
"tslib": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@yume-chan/android-bin": {
|
||||
"version": "0.0.23",
|
||||
"resolved": "https://registry.npmjs.org/@yume-chan/android-bin/-/android-bin-0.0.23.tgz",
|
||||
"integrity": "sha512-yOhErwfD7oe8piG/kboHbYGLQJU/eJE81yUzQFJbXtI0guR8j9baeyVYuTHzSVyvFTlBqsd5cd68bYGT6o3yAw==",
|
||||
"dependencies": {
|
||||
"@yume-chan/adb": "^0.0.23",
|
||||
"@yume-chan/stream-extra": "^0.0.23",
|
||||
"@yume-chan/struct": "^0.0.23",
|
||||
"tslib": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@yume-chan/async": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@yume-chan/async/-/async-2.2.0.tgz",
|
|
@ -3,6 +3,7 @@
|
|||
"@yume-chan/adb": "^0.0.23",
|
||||
"@yume-chan/adb-credential-web": "^0.0.23",
|
||||
"@yume-chan/adb-daemon-webusb": "^0.0.23",
|
||||
"@yume-chan/android-bin": "^0.0.23",
|
||||
"@yume-chan/stream-extra": "^0.0.23"
|
||||
}
|
||||
}
|
|
@ -260,6 +260,7 @@ const endpointInfo = [ (ctx) => (ctx.urlSections[0] === 'info' && ctx.request.me
|
|||
${isEnvServer ? `You can obtain the full source code and assets by downloading the following files:
|
||||
${resFiles.map((file) => ` • <a href="/res/${file}">${file}</a>`).join('')}.
|
||||
` : 'To get the original, unminified source code, visit this same page on the server-side version (refer to the Versions section above).'}
|
||||
Alternatively, you can also find the source code on my shared Git repo: ${A('https://gitlab.com/octospacc/octospacc.gitlab.io/-/tree/master/source/WuppiMini/')}.
|
||||
</p>
|
||||
${isEnvServer ? `<h3>Terms of Use and Privacy Policy</h3>${appTerms}` : ''}
|
||||
<h3>Changelog</h3>
|
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 226 KiB |
Before Width: | Height: | Size: 354 KiB After Width: | Height: | Size: 354 KiB |
Before Width: | Height: | Size: 581 KiB After Width: | Height: | Size: 581 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
@ -48,27 +48,31 @@
|
|||
--><a href="./HashyMagnet/">🧲 HashyMagnet</a>
|
||||
<small>(BitTorrent Hash to Magnet)</small><!--
|
||||
--></h4>
|
||||
<h4><!--
|
||||
--><a href="./Ecoji/">🦜 Ecoji v1</a>
|
||||
<small>(webapp fork)</small><!--
|
||||
--></h4>
|
||||
<h4><!--
|
||||
--><a href="./FramesBrowser/">🪟️ Frames Browser</a>
|
||||
<small>(<i>yo dawg, i heard you...</i>)</small><!--
|
||||
--></h4>
|
||||
<h4><a href="./MatrixStickerHelper/">🃏️ [Matrix] Sticker Helper</a></h4>
|
||||
<h4><!--
|
||||
--><a href="./MBViewer/">👁️🗨️️ MBViewer</a>
|
||||
<small>(WordPress/RSS/... chat-like UI)</small><!--
|
||||
--><a href="./SpiderADB/">🕷️ SpiderADB</a>
|
||||
<small>(Android debugging for Web)</small><!--
|
||||
--></h4>
|
||||
<h4><!--
|
||||
--><a href="./WuppiMini/">☘️ WuppìMini</a>
|
||||
<small>(basic-HTML posting client)</small><!--
|
||||
--></h4>
|
||||
<h4><!--
|
||||
--><a href="./MBViewer/">👁️🗨️️ MBViewer</a>
|
||||
<small>(WordPress/RSS/... chat-like UI)</small><!--
|
||||
--></h4>
|
||||
<h4><!--
|
||||
--><a href="./Ecoji/">🦜 Ecoji v1</a>
|
||||
<small>(webapp fork)</small><!--
|
||||
--></h4>
|
||||
<br/>
|
||||
<h4><a href="https://octospacc.gitlab.io/FumoPrisms">🔺️ Fumo Prisms (!)</a></h4>
|
||||
<h4><a href="https://octospacc.gitlab.io/FumoPrisms/">🔺️ Fumo Prisms (!)</a></h4>
|
||||
<h4><a href="./Collections/">🎀 My Collections</a> <small>(of posts/pages)</small></h4>
|
||||
<h4><a href="./Userscripts/">⚙️ My Userscripts</a></h4>
|
||||
<h4><a href="./Userscripts/">⚙️ My Userscripts</a> <small>for a nicer web</small></h4>
|
||||
<h4>Nice <a href="https://addons.mozilla.org/firefox/collections/18049170/octollection/">🦊 Firefox Add-ons</a>
|
||||
<small>(<a href="https://addons.mozilla.org/firefox/user/18049170/">mine</a> + suggestions)</small></h4>
|
||||
</div></div>
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |