diff --git a/.gitignore b/.gitignore index 20fb3088b..15fda4fd7 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ bin !.yarn/sdks !.yarn/versions .build +.wrangler diff --git a/hack/latest-worker.js b/hack/latest-worker.js new file mode 100644 index 000000000..dd52ee5cd --- /dev/null +++ b/hack/latest-worker.js @@ -0,0 +1,83 @@ +/**aquareum + * Welcome to Cloudflare Workers! This is your first worker. + * + * - Run `npm run dev` in your terminal to start a development server + * - Open a browser tab at http://localhost:8787/ to see your worker in action + * - Run `npm run deploy` to publish your worker + * + * Learn more at https://developers.cloudflare.com/workers/ + */ + +const re = new RegExp( + `^aquareum-(v[0-9]\.[0-9]\.[0-9])-([0-9a-f]+)-([0-9a-z]+)-([0-9a-z]+)\.(.+)$`, +); +const inputRe = new RegExp(`^aquareum-([0-9a-z]+)-([0-9a-z]+)\.(.+)$`); + +const CI_API_V4_URL = "https://git.aquareum.tv/api/v4"; +const DOWNLOAD_BASE_URL = + "https://git.aquareum.tv/aquareum-tv/aquareum/-/package_files"; +const PROJECT_ID = "1"; + +// Export a default object containing event handlers +export default { + // The fetch handler is invoked when this worker receives a HTTP(S) request + // and should return a Response (optionally wrapped in a Promise) + async fetch(req, env, ctx) { + const { pathname } = new URL(req.url); + const [_, dl, branch, file] = pathname.split("/"); + if (!branch || !file) { + return new Response("usage: /dl/latest/aquareum-linux-arm64.tar.gz", { + status: 400, + }); + } + const inputPieces = inputRe.exec(file); + { + if (!inputPieces) { + return new Response(`could not parse filename ${file}`); + } + } + const [full, inputPlatform, inputArch, inputExt] = inputPieces; + const packageUrl = `${CI_API_V4_URL}/projects/${PROJECT_ID}/packages?order_by=created_at&sort=desc&package_name=${branch}`; + const packageReq = await fetch(packageUrl, { + headers: { + "user-agent": "aquareum-dl", + }, + }); + const packages = await packageReq.json(); + const pkg = packages[0]; + if (!pkg) { + return new Response(`package for branch ${branch} not found`, { + status: 404, + }); + } + const fileUrl = `${CI_API_V4_URL}/projects/${PROJECT_ID}/packages/${pkg.id}/package_files`; + console.log(fileUrl); + const fileReq = await fetch(fileUrl); + const files = await fileReq.json(); + let foundFile; + for (const f of files) { + const pieces = re.exec(f.file_name); + if (!pieces) { + console.error(`could not parse filename ${f.file_name}`); + continue; + } + const [full, ver, hash, platform, arch, ext] = pieces; + console.log({ full, ver, hash, platform, arch, ext }); + if ( + platform === inputPlatform && + arch === inputArch && + ext === inputExt + ) { + foundFile = f; + break; + } + } + if (!foundFile) { + throw new Error( + `could not find a file for platform=${inputPlatform} arch=${inputArch} ext=${inputExt})`, + ); + } + const outUrl = `${DOWNLOAD_BASE_URL}/${foundFile.id}/download`; + return Response.redirect(outUrl, 302); + }, +}; diff --git a/js/app/app/(tabs)/index.tsx b/js/app/app/(tabs)/index.tsx index 81e7c330b..6a46bce7e 100644 --- a/js/app/app/(tabs)/index.tsx +++ b/js/app/app/(tabs)/index.tsx @@ -46,6 +46,7 @@ import { Countdown } from "components"; import { ImageBackground } from "react-native"; import * as env from "constants/env"; import { useState } from "react"; +import GetApps from "components/get-apps"; const WebviewIframe = ({ src }) => { if (isWeb) { @@ -111,6 +112,9 @@ export default function TabOneScreen() { Aquareum: The Video Layer for Everything + + + diff --git a/js/app/assets/images/appstore.svg b/js/app/assets/images/appstore.svg new file mode 100644 index 000000000..4c06b31a9 --- /dev/null +++ b/js/app/assets/images/appstore.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js/app/assets/images/playstore.svg b/js/app/assets/images/playstore.svg new file mode 100644 index 000000000..f4758a39d --- /dev/null +++ b/js/app/assets/images/playstore.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js/app/components/get-apps.native.tsx b/js/app/components/get-apps.native.tsx new file mode 100644 index 000000000..8e9254cd9 --- /dev/null +++ b/js/app/components/get-apps.native.tsx @@ -0,0 +1,5 @@ +import { View } from "tamagui"; + +export default function GetApps() { + return ; +} diff --git a/js/app/components/get-apps.tsx b/js/app/components/get-apps.tsx new file mode 100644 index 000000000..c57885b77 --- /dev/null +++ b/js/app/components/get-apps.tsx @@ -0,0 +1,31 @@ +import { XStack, Image, Anchor } from "tamagui"; + +const RATIO = 3.39741547176; +const WIDTH = 200; +const HEIGHT = 200 / RATIO; + +export default function GetApps() { + return ( + + + + + + + + + ); +}