diff --git a/Build.sh b/Build.sh index 38bc9d1..da1d670 100755 --- a/Build.sh +++ b/Build.sh @@ -1,6 +1,15 @@ #!/bin/sh SourceApps="SpiderADB WuppiMini" -HubSdkApps="${SourceApps} Ecoji MatrixStickerHelper" +HubSdkApps="${SourceApps} MatrixStickerHelper" + +quoteVar(){ echo '"'"$1"'"' ;} + +getMetaAttr(){ + file="$1" + name="$2" + key="$([ -n "$3" ] && echo "$3" || echo "property")" + grep '' | cut -d '"' -f4 +} rm -vrf ./public || true cp -vr ./static ./public @@ -8,10 +17,10 @@ cp -vr ./shared ./public/shared for App in ${SourceApps} do - mkdir -p ./public/${App} - cd ./source/${App} + mkdir -p "./public/${App}" + cd "./source/${App}" sh ./Requirements.sh - cp -r $(sh ./Build.sh) ../../public/${App}/ + cp -vr $(sh ./Build.sh) "../../public/${App}/" cd ../.. done @@ -20,5 +29,18 @@ node ../WriteRedirectPages.js for App in ${HubSdkApps} do - echo # TODO write manifest.json files + file="./${App}/index.html" + name="$(getMetaAttr "${file}" og:title)" + description="$(getMetaAttr "${file}" og:description property)" + url="$(getMetaAttr "${file}" Url OctoSpaccHubSdk)" #"$(getMetaAttr "${file}" og:url property)" + cat << [OctoSpaccHubSdk-WebManifest-EOF] > "./${App}/WebManifest.json" + { + $(getMetaAttr "${file}" WebManifestExtra OctoSpaccHubSdk | sed s/\'/\"/g) + $([ -n "${description}" ] && echo "$(quoteVar description): $(quoteVar "${description}"),") + "start_url": "${url}", + "scope": "${url}", + "name": "${name}" + } +[OctoSpaccHubSdk-WebManifest-EOF] + sed -i 's||
WebUSB is not supported in this browser, so the app cannot work. @@ -70,7 +58,7 @@ if (!UsbManager) { return; // kill the app } -new AdbDaemonWebUsb.AdbDaemonWebUsbDeviceWatcher((async function(connectedDevice){ +new AdbDaemonWebUsbDeviceWatcher((async function(connectedDevice){ if (!connectedDevice) { await disconnectDevice(); } @@ -82,8 +70,8 @@ async function connectAuthorizeDevice () { 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); + Device.transport = await AdbDaemonTransport.authenticate({ connection: Device.connection, credentialStore: CredentialStore }); + Device.adb = new Adb(Device.transport); } catch (err) { $('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.'; } @@ -144,7 +132,6 @@ async function refreshDeviceInfo () { //$('$deviceInfo$').hidden = false; if (Device.adb) { $('$deviceStatus$').innerHTML = null; - // $('$devicePropDump$').innerHTML = null; $('$deviceCpuAbis$').innerHTML = `CPU ABIs: ${await Device.adb.getProp('ro.system.product.cpu.abilist')}`; $('$androidVersion$').innerHTML = `Android version: ${await Device.adb.getProp('ro.build.version.release')}`; $('$androidApi$').innerHTML = `SDK API version: ${await Device.adb.getProp('ro.build.version.sdk')}`; @@ -156,11 +143,6 @@ async function refreshDeviceInfo () { terminalOutput.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 { onDevice = false; } @@ -175,8 +157,13 @@ async function refreshDeviceInfo () { function toggleDeviceElems (enabled) { $('$deviceInfo$').hidden = !enabled; $('button$apkInstall$').disabled = !enabled; + $('button$packagesUninstall$').disabled = true; + $('button$packagesInvertSelect$').disabled = !enabled; $('input$terminalInput$').disabled = !enabled; resizeTerminal(); + if (!enabled) { + $('ul$packageList$').innerHTML = null; + } } async function refreshDeviceSection () { @@ -228,25 +215,86 @@ $('button$wrapTerminal$').onclick = (function(){ terminalOutput.scrollTop = terminalOutput.scrollHeight; }); +$('button$apkInstall$').onclick = (async function(){ + // TODO allow installing via drag&drop on packages section + const fileInput = this.querySelector('input'); + fileInput.onchange = (async function(event){ + const count = event.target.files.length; + if (!count > 0) { + return; + } + popupBox(`Installing ${count} package(s)...`); + const pm = new PackageManager(Device.adb); + for (const index in Object.keys(event.target.files)) { + const file = event.target.files[index]; + try { + await pm.installStream(file.size, (new WrapReadableStream(file.stream())).pipeThrough(new WrapConsumableStream())); + popupBox(`Successfully installed package ${Number(index) + 1} of ${count}.`); + refreshPackagesList(); + } catch (err) { + popupBox('Operation has failed:' + err); + break; + } + } + }); + fileInput.click(); +}); + +$('button$packagesUninstall$').onclick = (async function(event){ + const checkedPackagesElems = $('ul$packageList$').querySelectorAll('input[type="checkbox"]:checked'); + const count = checkedPackagesElems.length; + if (!confirm(`Confirm uninstalling ${count} packages? (Currently only works on user packages, will fail on system ones.)`)) { + return; + } + $('button$packagesUninstall$').disabled = true; + const pm = new PackageManager(Device.adb); + for (const index in Object.keys(checkedPackagesElems)) { + try { + const packageElem = checkedPackagesElems[index].parentElement; + const packageName = packageElem.textContent.trim(); + await pm.uninstall(packageName); + popupBox(`Successfully uninstalled package ${Number(index) + 1} of ${count}.`); + refreshPackagesList(); + } catch(err) { + popupBox('Operation has failed:' + err); + break; + } + } + $('button$packagesUninstall$').disabled = false; + refreshPackagesList(); +}) + +$('button$packagesInvertSelect$').onclick = (function(){ + Array.from($('ul$packageList$').querySelectorAll('input[type="checkbox"]')).forEach(function(packageElem){ + packageElem.checked = !packageElem.checked; + }); +}); + async function refreshPackagesList () { $('ul$packageList$').innerHTML = null; + $('button$packagesUninstall$').disabled = true; const pm = new PackageManager(Device.adb); const list = await pm.listPackages(); + const checkedList = {}; + let index = 0; let result = await list.next(); while (!result.done) { var packageElem = document.createElement('li'); - packageElem.innerHTML = `${result.value.packageName}`; - /* 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 - }); */ + packageElem.index = index; + packageElem.innerHTML = `${result.value.packageName} `; + packageElem.querySelector('input').onchange = (function(){ + checkedList[this.parentElement.index] = this.checked; + $('button$packagesUninstall$').disabled = !Object.values(checkedList).includes(true); + }); $('ul$packageList$').appendChild(packageElem); + index++; 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 */) { + if (Device.adb && sectionHash === 'packages') { refreshPackagesList(); } })); diff --git a/source/SpiderADB/holo-web/holo-extra-octt.css b/source/SpiderADB/holo-web/holo-extra-octt.css index c850159..7a99e49 100644 --- a/source/SpiderADB/holo-web/holo-extra-octt.css +++ b/source/SpiderADB/holo-web/holo-extra-octt.css @@ -27,7 +27,7 @@ a[data-action-section] { /* width: 60%; */ height: 100vh; z-index: 1; - background: rgba(0, 0, 0, 0.6); + background: rgba(0, 0, 0, 0.65); } .holo-sidebar[data-open="open"], .holo-sideBar[data-open="open"] { @@ -37,10 +37,10 @@ a[data-action-section] { .holo-sidebar .holo-list, .holo-sideBar .holo-list { width: 60%; height: 100vh; - background: rgba(0, 0, 0, 0.9); + background: rgba(0, 0, 0, 0.80); } -.actionBar .holo-title.holo-menu, .holo-actionBar .holo-title.holo-menu { +.actionbar .holo-title.holo-menu, .holo-actionbar .holo-title.holo-menu, .actionBar .holo-title.holo-menu, .holo-actionBar .holo-title.holo-menu { background-position: 0 16px; background-repeat: no-repeat; background-image: url(./holo-menu.png); @@ -52,12 +52,42 @@ a[data-action-section] { box-sizing: content-box; } +.holo-sidebar > .holo-list, .holo-sideBar > .holo-list { + overflow-y: auto; +} + +.holo-actionbar .holo-list, .holo-actionBar .holo-list { + position: absolute; + top: -2px; + right: 0; +} + +.holo-actionbar .holo-list.collapsible, .holo-actionBar .holo-list.collapsible { + top: 47px; + background: rgba(16, 16, 16, 0.95); + display: none; +} + +.holo-actionbar .holo-list > div, .holo-actionBar .holo-list > div, +.holo-actionbar .holo-list:not(.collapsible) li, .holo-actionBar .holo-list:not(.collapsible) li { + display: inline-block; +} + +.holo-actionbar .holo-list li > button, .holo-actionBar ul.holo-list li > button { + font-size: revert; +} + +.holo-actionbar .holo-list:not(.collapsible) *[data-collapsed="true"], .holo-actionBar .holo-list:not(.collapsible) *[data-collapsed="true"], +.holo-actionbar .holo-list.collapsible *[data-collapsed="false"], .holo-actionBar .holo-list.collapsible *[data-collapsed="false"] { + display: none !important; +} + /* https://github.com/ZMYaro/holo-web/issues/1#issuecomment-12778881 */ input[type="text"] { background: transparent; color: white; border-width: 0 0 1px; - border-color: #7F7F7F; + border-color: /* #4AB3E4; */ #7F7F7F; border-style: solid; line-height: 36px; padding: 0px 4px; @@ -72,7 +102,7 @@ textarea { background: transparent; color: white; border-width: 0 0 1px; - border-color: #7F7F7F; + border-color: /* #4AB3E4; */ #7F7F7F; border-style: solid; padding: 4px 4px; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; diff --git a/source/SpiderADB/holo-web/holo-extra-octt.js b/source/SpiderADB/holo-web/holo-extra-octt.js index 5edd016..4785695 100644 --- a/source/SpiderADB/holo-web/holo-extra-octt.js +++ b/source/SpiderADB/holo-web/holo-extra-octt.js @@ -1,7 +1,39 @@ window.addEventListener('load', (function() { +//function getElemPrototype (elem) { return elem.outerHTML.split('>') } + +/* https://stackoverflow.com/a/47932848 */ +//function camelToDash(str){ return str.replace(/([A-Z])/g, function($1){return "-"+$1.toLowerCase();}) } + +/* function elemToQuery (elem) { + var query = elem.tagName; + if (elem.id) { + query += `[id="${elem.id}"]`; + } + if (elem.className) { + query += `[class="${elem.className}"]`; + } + for (var key in elem.dataset) { + query += `[data-${camelToDash(key)}="${elem.dataset[key]}"]`; + } + return query; +} */ + var initialSectionName = $('[data-section][data-open]').dataset.section; +$(':: .holo-actionbar > .holo-list, .holo-actionBar > .holo-list').forEach(function(actionListElem){ + var actionListElemNew = actionListElem.cloneNode(true); + actionListElemNew.classList.add('collapsible'); + actionListElemNew.querySelector('[data-collapser]').remove(); + arrayFrom(actionListElemNew.querySelectorAll('.holo-list li')).forEach(function(itemElem){ + itemElem.remove(); + }); + actionListElem.insertAdjacentElement('afterend', actionListElemNew); + actionListElem.querySelector('button[data-collapser], [data-collapser] > button').onclick = (function(){ + actionListElemNew.style.display = (actionListElemNew.style.display ? null : 'revert'); + }); +}); + $('::[data-action-sidebar]').forEach(function(actionSidebarElem){ var sidebarElem = $('[data-sidebar="' + actionSidebarElem.dataset.actionSidebar + '"]'); function toggleSidebar () { @@ -41,6 +73,7 @@ function refreshDisplaySections (sectionTargetName) { displaySectionsElem.style.display = 'none'; } }); + reorderActionBar(); } refreshDisplaySections(); @@ -51,4 +84,52 @@ function hashChange () { window.addEventListener('hashchange', hashChange); hashChange(); +function reorderActionBar () { + $(':: .holo-actionbar, .holo-actionBar').forEach(function(actionBarElem){ + var childrenWidth = 0; + var collapsedChildren = 0; + childrenWidth += actionBarElem.querySelector('button.holo-title').clientWidth; + arrayFrom(actionBarElem.querySelectorAll('.holo-list.collapsible li')).forEach(function(itemElem){ + var destParentElem = actionBarElem.querySelector('.holo-list:not(.collapsible)'); + //if (!destParentElem.className.includes('holo-list')) { + //if (getElemPrototype(itemElem.parentElement) !== getElemPrototype(destParentElem)) { + // destParentElem = actionBarElem.querySelector(`.holo-list:not(.collapsible) > ${elemToQuery(itemElem.parentElement)}`); + //} + destParentElem.insertBefore(itemElem, destParentElem.lastElementChild); + }); + arrayFrom(actionBarElem.querySelectorAll('.holo-list:not(.collapsible) li')).forEach(function(itemElem){ + itemElem.dataset.collapsed = false; + childrenWidth += itemElem.clientWidth; + }); + //arrayFrom(actionBarElem.querySelectorAll('.holo-list.collapsible li')).forEach(function(itemElem){ + // itemElem.dataset.collapsed = false; + //}); + if (childrenWidth <= actionBarElem.clientWidth) { + actionBarElem.querySelector('[data-collapser]').style.display = 'none'; + } + while (childrenWidth > actionBarElem.clientWidth) { + var itemElem = arrayFrom(actionBarElem.querySelectorAll('.holo-list:not(.collapsible) li:not([data-collapsed="true"]):not([data-collapser])')).slice(-1)[0]; + if (!itemElem) { + return; + } + collapsedChildren++; + childrenWidth -= itemElem.clientWidth; + itemElem.dataset.collapsed = true; + var destParentElem = actionBarElem.querySelector('.holo-list.collapsible'); + //if (!destParentElem.className.includes('holo-list')) { + // destParentElem = actionBarElem.querySelector(`.holo-list.collapsible > ${elemToQuery(itemElem.parentElement)}`); + //} + destParentElem.insertBefore(itemElem, destParentElem.firstElementChild); + actionBarElem.querySelector('[data-collapser]').style.display = null; + } + //if (collapsedChildren > 0) { + // arrayFrom(actionBarElem.querySelectorAll('.holo-list.collapsible li:not([data-collapsed="true"]):not([data-collapser])')).slice(-collapsedChildren).forEach(function(itemElem){ + // itemElem.dataset.collapsed = true; + // }); + //} + }); +} +window.addEventListener('resize', reorderActionBar); +reorderActionBar(); + })); diff --git a/source/SpiderADB/index.html b/source/SpiderADB/index.html index 8242663..8be50dd 100644 --- a/source/SpiderADB/index.html +++ b/source/SpiderADB/index.html @@ -3,7 +3,9 @@
-