add adb functionality

This commit is contained in:
Cloudburst 2022-09-18 12:07:07 +02:00
parent 55b673f4c5
commit dc4c6731f6
6 changed files with 271 additions and 14 deletions

160
package-lock.json generated
View file

@ -9,6 +9,9 @@
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@noriginmedia/norigin-spatial-navigation": "^1.0.5", "@noriginmedia/norigin-spatial-navigation": "^1.0.5",
"@yume-chan/adb": "^0.0.16",
"@yume-chan/adb-backend-webusb": "^0.0.16",
"@yume-chan/adb-credential-web": "^0.0.16",
"daisyui": "^2.24.0", "daisyui": "^2.24.0",
"gatsby": "^4.21.1", "gatsby": "^4.21.1",
"gatsby-plugin-canonical-urls": "^4.22.0", "gatsby-plugin-canonical-urls": "^4.22.0",
@ -4173,6 +4176,11 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
}, },
"node_modules/@types/w3c-web-usb": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.6.tgz",
"integrity": "sha512-cSjhgrr8g4KbPnnijAr/KJDNKa/bBa+ixYkywFRvrhvi9n1WEl7yYbtRyzE6jqNQiSxxJxoAW3STaOQwJHndaw=="
},
"node_modules/@types/websocket": { "node_modules/@types/websocket": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.2.tgz",
@ -4543,6 +4551,73 @@
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
}, },
"node_modules/@yume-chan/adb": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/adb/-/adb-0.0.16.tgz",
"integrity": "sha512-+5q4d3q+rP8rbtv8pqfMX0Ln749TjHmJ75a/yZiEdlNdYIV7Oi+ZeEs43hd70dJs3wHnlwM/uLUaz93wdz4eSA==",
"dependencies": {
"@yume-chan/async": "^2.1.4",
"@yume-chan/dataview-bigint-polyfill": "^0.0.16",
"@yume-chan/event": "^0.0.16",
"@yume-chan/struct": "^0.0.16",
"tslib": "^2.3.1",
"web-streams-polyfill": "^4.0.0-beta.3"
}
},
"node_modules/@yume-chan/adb-backend-webusb": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/adb-backend-webusb/-/adb-backend-webusb-0.0.16.tgz",
"integrity": "sha512-BJ9gUKXaYrXG9rxW3kbI8yBFVSnQuIkUgPUs4GDvXRxtiEn0Snidqw1HhJBF78LPvqZSAcxfiU8mfB61s2ERWw==",
"dependencies": {
"@types/w3c-web-usb": "^1.0.4",
"@yume-chan/adb": "^0.0.16",
"@yume-chan/struct": "^0.0.16",
"tslib": "^2.3.1"
}
},
"node_modules/@yume-chan/adb-credential-web": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/adb-credential-web/-/adb-credential-web-0.0.16.tgz",
"integrity": "sha512-W2Gfq/KoUhlHQc8joIWcEfGu/AGKTlZ+EW+AwVCB9tK7u3iMjJEwYsFdNwciAzwGpJAjUiiCSFs6H5+Sa/4ODQ==",
"dependencies": {
"@yume-chan/adb": "^0.0.16",
"tslib": "^2.3.1"
}
},
"node_modules/@yume-chan/async": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@yume-chan/async/-/async-2.2.0.tgz",
"integrity": "sha512-jatCtX1/3DsR9Vt3EB8CGFy0MNrXP5f+eNiRGHLH+LkYz7MPLzpqL/DnvXSip+Z0EKBCDnzuNuELjsKEEzcdQA==",
"dependencies": {
"tslib": "^2.3.1"
}
},
"node_modules/@yume-chan/dataview-bigint-polyfill": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/dataview-bigint-polyfill/-/dataview-bigint-polyfill-0.0.16.tgz",
"integrity": "sha512-fvo4fclUgoPwO8dkRCEjce6efV5mnyJBNjiq3VYCUkXcuzb2anvbedIihuFpajhlDQ31GAKTnkQYFHpSOhzHqA==",
"dependencies": {
"tslib": "^2.3.1"
}
},
"node_modules/@yume-chan/event": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/event/-/event-0.0.16.tgz",
"integrity": "sha512-bZ8B1oM2s4nKRtG2O2rQIRbiLBSl6HMeJnFqKdZ1in6tDNq3t9NJopOwzR/DUUvadCaa8KjEHIcyC2E2XnEEpQ==",
"dependencies": {
"@yume-chan/async": "^2.1.4",
"tslib": "^2.3.1"
}
},
"node_modules/@yume-chan/struct": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/struct/-/struct-0.0.16.tgz",
"integrity": "sha512-RNEn3KPk6i0NkkoQE1xAPUYDp6Afqes1VYkmJIW6fGCmZqWTHUy0tH8qa6qMmfYaTK5sdcH77M0EyvifDxmzUA==",
"dependencies": {
"@yume-chan/dataview-bigint-polyfill": "^0.0.16",
"tslib": "^2.3.1"
}
},
"node_modules/abort-controller": { "node_modules/abort-controller": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@ -21399,6 +21474,14 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/web-streams-polyfill": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
"engines": {
"node": ">= 14"
}
},
"node_modules/webidl-conversions": { "node_modules/webidl-conversions": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
@ -24870,6 +24953,11 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
}, },
"@types/w3c-web-usb": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.6.tgz",
"integrity": "sha512-cSjhgrr8g4KbPnnijAr/KJDNKa/bBa+ixYkywFRvrhvi9n1WEl7yYbtRyzE6jqNQiSxxJxoAW3STaOQwJHndaw=="
},
"@types/websocket": { "@types/websocket": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.2.tgz",
@ -25148,6 +25236,73 @@
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
}, },
"@yume-chan/adb": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/adb/-/adb-0.0.16.tgz",
"integrity": "sha512-+5q4d3q+rP8rbtv8pqfMX0Ln749TjHmJ75a/yZiEdlNdYIV7Oi+ZeEs43hd70dJs3wHnlwM/uLUaz93wdz4eSA==",
"requires": {
"@yume-chan/async": "^2.1.4",
"@yume-chan/dataview-bigint-polyfill": "^0.0.16",
"@yume-chan/event": "^0.0.16",
"@yume-chan/struct": "^0.0.16",
"tslib": "^2.3.1",
"web-streams-polyfill": "^4.0.0-beta.3"
}
},
"@yume-chan/adb-backend-webusb": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/adb-backend-webusb/-/adb-backend-webusb-0.0.16.tgz",
"integrity": "sha512-BJ9gUKXaYrXG9rxW3kbI8yBFVSnQuIkUgPUs4GDvXRxtiEn0Snidqw1HhJBF78LPvqZSAcxfiU8mfB61s2ERWw==",
"requires": {
"@types/w3c-web-usb": "^1.0.4",
"@yume-chan/adb": "^0.0.16",
"@yume-chan/struct": "^0.0.16",
"tslib": "^2.3.1"
}
},
"@yume-chan/adb-credential-web": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/adb-credential-web/-/adb-credential-web-0.0.16.tgz",
"integrity": "sha512-W2Gfq/KoUhlHQc8joIWcEfGu/AGKTlZ+EW+AwVCB9tK7u3iMjJEwYsFdNwciAzwGpJAjUiiCSFs6H5+Sa/4ODQ==",
"requires": {
"@yume-chan/adb": "^0.0.16",
"tslib": "^2.3.1"
}
},
"@yume-chan/async": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@yume-chan/async/-/async-2.2.0.tgz",
"integrity": "sha512-jatCtX1/3DsR9Vt3EB8CGFy0MNrXP5f+eNiRGHLH+LkYz7MPLzpqL/DnvXSip+Z0EKBCDnzuNuELjsKEEzcdQA==",
"requires": {
"tslib": "^2.3.1"
}
},
"@yume-chan/dataview-bigint-polyfill": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/dataview-bigint-polyfill/-/dataview-bigint-polyfill-0.0.16.tgz",
"integrity": "sha512-fvo4fclUgoPwO8dkRCEjce6efV5mnyJBNjiq3VYCUkXcuzb2anvbedIihuFpajhlDQ31GAKTnkQYFHpSOhzHqA==",
"requires": {
"tslib": "^2.3.1"
}
},
"@yume-chan/event": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/event/-/event-0.0.16.tgz",
"integrity": "sha512-bZ8B1oM2s4nKRtG2O2rQIRbiLBSl6HMeJnFqKdZ1in6tDNq3t9NJopOwzR/DUUvadCaa8KjEHIcyC2E2XnEEpQ==",
"requires": {
"@yume-chan/async": "^2.1.4",
"tslib": "^2.3.1"
}
},
"@yume-chan/struct": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@yume-chan/struct/-/struct-0.0.16.tgz",
"integrity": "sha512-RNEn3KPk6i0NkkoQE1xAPUYDp6Afqes1VYkmJIW6fGCmZqWTHUy0tH8qa6qMmfYaTK5sdcH77M0EyvifDxmzUA==",
"requires": {
"@yume-chan/dataview-bigint-polyfill": "^0.0.16",
"tslib": "^2.3.1"
}
},
"abort-controller": { "abort-controller": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@ -37249,6 +37404,11 @@
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz",
"integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==" "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw=="
}, },
"web-streams-polyfill": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="
},
"webidl-conversions": { "webidl-conversions": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",

View file

@ -16,6 +16,9 @@
}, },
"dependencies": { "dependencies": {
"@noriginmedia/norigin-spatial-navigation": "^1.0.5", "@noriginmedia/norigin-spatial-navigation": "^1.0.5",
"@yume-chan/adb": "^0.0.16",
"@yume-chan/adb-backend-webusb": "^0.0.16",
"@yume-chan/adb-credential-web": "^0.0.16",
"daisyui": "^2.24.0", "daisyui": "^2.24.0",
"gatsby": "^4.21.1", "gatsby": "^4.21.1",
"gatsby-plugin-canonical-urls": "^4.22.0", "gatsby-plugin-canonical-urls": "^4.22.0",

View file

@ -0,0 +1,83 @@
import React, { useState, useEffect } from "react";
import { Adb } from '@yume-chan/adb';
import AdbWebCredentialStore from '@yume-chan/adb-credential-web';
import AdbWebUsbBackend from '@yume-chan/adb-backend-webusb';
import CompatBtn from "./compatbtn";
import {MdAdb} from "react-icons/md"
const isBrowser = typeof window !== "undefined"
const CredentialStore = new AdbWebCredentialStore();
const AdbConnect = () => {
const [status, setStatus] = useState("disconnected")
const [supported, setSupported] = useState(true);
useEffect(() => {
if (!isBrowser) return;
setSupported(AdbWebUsbBackend.isSupported())
}, [])
function connect() {
if (!isBrowser) return;
AdbWebUsbBackend.requestDevice()
.then(req => {
setStatus(`loading/Connecting to ${req.name}`)
req.connect()
.then(conn => {
setStatus(`loading/Authenticating ${req.serial}`)
Adb.authenticate(conn, CredentialStore, undefined)
.then(dev => {
setStatus(`connected/${dev.device}`)
window.AdbConnection = dev
})
.catch(err => {
setStatus(`error/${err}`)
})
})
})
}
if (!supported) return <></>
let color
if (status.startsWith("connected")) {
color = "alert-success"
} else if (status.startsWith("error")) {
color = "alert-error"
} else if (status.startsWith("loading")) {
color = "alert-info"
} else {
color = ""
}
return <div class={`alert shadow-lg w-full mx-10 md:w-2/3 mb-5 ${color}`}>
<div>
<MdAdb />
<div>
<h3 class="font-bold">Connect to the device via ADB (via USB)</h3>
{!status.startsWith("error") &&
<div class="text-xs">Useful if you do not have a web browser on your device.</div>
}
{status.startsWith("error") &&
<div class="text-xs">Failed to connect. ${status.split("/").at(1)}</div>
}
</div>
</div>
<div class="flex-none">
{status === "disconnected" &&
<CompatBtn className="btn-sm btn-primary" onClick={connect}>Connect</CompatBtn>
}
{status.startsWith("loading") &&
<button class="btn btn-sm loading btn-info no-animation">{status.split("/").at(1) || "Loading"}</button>
}
{status.startsWith("connected") &&
<button class="btn btn-sm btn-success no-animation">Connected to {status.split("/").at(1) || "device"}</button>
}
</div>
</div>
}
export default AdbConnect

View file

@ -3,6 +3,16 @@ import React, { useState, useEffect } from "react";
import CompatBtn from "../compatbtn"; import CompatBtn from "../compatbtn";
import { GoVerified } from "react-icons/go"; import { GoVerified } from "react-icons/go";
function installRepo(url) {
if (window.AdbConnection !== undefined) {
window.AdbConnection.subprocess.shell(`am start -a android.intent.action.VIEW -d "cloudstreamrepo://${url.replace(/^https?:\/\//, "")}"`)
} else if (window.RepoApi !== undefined) {
window.RepoApi.installRepo(url)
} else {
window.open(`cloudstreamrepo://${url.replace(/^https?:\/\//, "")}`)
}
}
const RepoCard = ({ repoData, isFirst }) => { const RepoCard = ({ repoData, isFirst }) => {
const [data, setData] = useState(null) const [data, setData] = useState(null)
@ -41,11 +51,7 @@ const RepoCard = ({ repoData, isFirst }) => {
group={true} group={true}
className="btn-primary" className="btn-primary"
onClick={() => { onClick={() => {
if (window.RepoApi !== undefined) { installRepo(url)
window.RepoApi.installRepo(url)
} else {
window.open(`cloudstreamrepo://${url.replace(/^https?:\/\//, "")}`)
}
}} }}
>Install</CompatBtn> >Install</CompatBtn>
<CompatBtn group={true} <CompatBtn group={true}

View file

@ -19,15 +19,18 @@ function CompatBtn({autoFocus, href, onClick, group, target, children, className
ref.current?.focus() ref.current?.focus()
} }
if (isBrowser) { useEffect(() => {
window.addEventListener("keyup", (ev) => { if (isBrowser) {
if (!focused) return; window.addEventListener("keyup", (ev) => {
if (document.activeElement !== ref.current) return; if (!focused) return;
if (ev.key === "Enter" || ev.key === " ") { if (document.activeElement !== ref.current) return;
ref.current?.click() if (ev.key === "Enter" || ev.key === " ") {
} ref.current?.click()
}) }
} })
}
}, [])
if (target !== "_blank" && !group && !onClick) { if (target !== "_blank" && !group && !onClick) {
return <Link to={href} className={`btn ${className||""}`} ref={ref} {...props}>{children}</Link> return <Link to={href} className={`btn ${className||""}`} ref={ref} {...props}>{children}</Link>

View file

@ -2,6 +2,7 @@ import React, {useEffect, useState} from "react"
import Layout from "../components/layout" import Layout from "../components/layout"
import RepoCard from "../components/cards/repo" import RepoCard from "../components/cards/repo"
import AdbConnect from "../components/adbconnect"
import bgImage from "../media/phones.png" import bgImage from "../media/phones.png"
import { TiWarning } from "react-icons/ti"; import { TiWarning } from "react-icons/ti";
@ -28,6 +29,7 @@ const IndexPage = () => {
</div> </div>
</div> </div>
</div> </div>
<AdbConnect />
{repos && {repos &&
repos.map((it, index) => <RepoCard repoData={it} key={index} isFirst={index===0}/>) repos.map((it, index) => <RepoCard repoData={it} key={index} isFirst={index===0}/>)
} }