mirror of
https://github.com/recloudstream/website.git
synced 2024-08-15 03:18:45 +00:00
add adb functionality
This commit is contained in:
parent
55b673f4c5
commit
dc4c6731f6
6 changed files with 271 additions and 14 deletions
160
package-lock.json
generated
160
package-lock.json
generated
|
@ -9,6 +9,9 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@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",
|
||||
"gatsby": "^4.21.1",
|
||||
"gatsby-plugin-canonical-urls": "^4.22.0",
|
||||
|
@ -4173,6 +4176,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||
|
@ -21399,6 +21474,14 @@
|
|||
"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": {
|
||||
"version": "3.0.1",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "3.0.0",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@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",
|
||||
"gatsby": "^4.21.1",
|
||||
"gatsby-plugin-canonical-urls": "^4.22.0",
|
||||
|
|
83
src/components/adbconnect.jsx
Normal file
83
src/components/adbconnect.jsx
Normal 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
|
|
@ -3,6 +3,16 @@ import React, { useState, useEffect } from "react";
|
|||
import CompatBtn from "../compatbtn";
|
||||
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 [data, setData] = useState(null)
|
||||
|
||||
|
@ -41,11 +51,7 @@ const RepoCard = ({ repoData, isFirst }) => {
|
|||
group={true}
|
||||
className="btn-primary"
|
||||
onClick={() => {
|
||||
if (window.RepoApi !== undefined) {
|
||||
window.RepoApi.installRepo(url)
|
||||
} else {
|
||||
window.open(`cloudstreamrepo://${url.replace(/^https?:\/\//, "")}`)
|
||||
}
|
||||
installRepo(url)
|
||||
}}
|
||||
>Install</CompatBtn>
|
||||
<CompatBtn group={true}
|
||||
|
|
|
@ -19,6 +19,7 @@ function CompatBtn({autoFocus, href, onClick, group, target, children, className
|
|||
ref.current?.focus()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isBrowser) {
|
||||
window.addEventListener("keyup", (ev) => {
|
||||
if (!focused) return;
|
||||
|
@ -28,6 +29,8 @@ function CompatBtn({autoFocus, href, onClick, group, target, children, className
|
|||
}
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
||||
if (target !== "_blank" && !group && !onClick) {
|
||||
return <Link to={href} className={`btn ${className||""}`} ref={ref} {...props}>{children}</Link>
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, {useEffect, useState} from "react"
|
|||
|
||||
import Layout from "../components/layout"
|
||||
import RepoCard from "../components/cards/repo"
|
||||
import AdbConnect from "../components/adbconnect"
|
||||
import bgImage from "../media/phones.png"
|
||||
|
||||
import { TiWarning } from "react-icons/ti";
|
||||
|
@ -28,6 +29,7 @@ const IndexPage = () => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AdbConnect />
|
||||
{repos &&
|
||||
repos.map((it, index) => <RepoCard repoData={it} key={index} isFirst={index===0}/>)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue