@hot-updater/console 1.2.0-rc.0 → 1.2.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/StoreSubmission-ViTkW4eJ.js +1 -0
- package/.output/public/assets/{index-PQ3UCeQV.js → index-DH9-mB8D.js} +2 -2
- package/.output/public/assets/{native-builds-c4BpOLAe.js → native-builds-BGgFQTDW.js} +2 -2
- package/.output/public/assets/native-builds-CxomzFqe.js +1 -0
- package/.output/public/assets/native-builds_._buildId-DD58_Phd.js +1 -0
- package/.output/public/assets/{native-builds_._buildId-9p4FFpa4.js → native-builds_._buildId-DvQDKnUQ.js} +2 -2
- package/.output/public/assets/{styles-Ccxthuz1.css → styles-uK-0vUMk.css} +1 -1
- package/.output/server/{__23tanstack-start-server-fn-resolver-nWkGzoo3.mjs → __23tanstack-start-server-fn-resolver-ClYi5o3F.mjs} +46 -46
- package/.output/server/_chunks/ssr-renderer.mjs +2 -2
- package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +1 -1
- package/.output/server/_ssr/{BundleIdDisplay-C2YJNpHa.mjs → BundleIdDisplay-DwXVKZD1.mjs} +2 -2
- package/.output/server/_ssr/{ConsoleFeatureUnavailable-Co4rDns4.mjs → ConsoleFeatureUnavailable-a0YZjfJt.mjs} +6 -6
- package/.output/server/_ssr/{EventDetails-CTvni55k.mjs → EventDetails-DLmuxP2p.mjs} +6 -6
- package/.output/server/_ssr/{HashValueDisplay-BBswr65a.mjs → HashValueDisplay-BArRgHY9.mjs} +2 -2
- package/.output/server/_ssr/{InsightsPageHeader-ueG4Pkov.mjs → InsightsPageHeader-Cpfe3N74.mjs} +6 -6
- package/.output/server/_ssr/{NotFoundPage-BES4AfvN.mjs → NotFoundPage-DZVJdjfb.mjs} +2 -2
- package/.output/server/_ssr/{RolloutPercentageBadge-Bkl0uDbV.mjs → RolloutPercentageBadge-D5cg9FC7.mjs} +3 -3
- package/.output/server/_ssr/{StoreSubmission-0TLWxjym.mjs → StoreSubmission-DVr58WKm.mjs} +5 -5
- package/.output/server/_ssr/{alert-dialog-Cn0L__fU.mjs → alert-dialog-CnEvXwFO.mjs} +1 -1
- package/.output/server/_ssr/{api-qUMT9H2M.mjs → api-BrkiPYff.mjs} +3 -3
- package/.output/server/_ssr/{api-keys-Dt6_6uWi.mjs → api-keys-B0gWgJ1z.mjs} +8 -8
- package/.output/server/_ssr/{api-keys-DgiwJvLW.mjs → api-keys-DZIeUKDy.mjs} +2 -2
- package/.output/server/_ssr/{api-keys-rpc-BqbL9Iyl.mjs → api-keys-rpc-BExzs1qj.mjs} +3 -3
- package/.output/server/_ssr/{api-rpc-CzZPviuV.mjs → api-rpc-Bp6d62Jh.mjs} +3 -3
- package/.output/server/_ssr/{auth-rpc-CPZyE2Rz.mjs → auth-rpc-Bjf1L5Ff.mjs} +4 -4
- package/.output/server/_ssr/{auth.server-C2hyK1tQ.mjs → auth.server-CfBpqOaJ.mjs} +2 -2
- package/.output/server/_ssr/{badge-C4HK6j63.mjs → badge-ldxZp5-5.mjs} +1 -1
- package/.output/server/_ssr/{config.server-CwjEf3S5.mjs → config.server-CLxGGSJG.mjs} +3 -3
- package/.output/server/_ssr/{console-access-B2mUKj3_.mjs → console-access-Cpzb2uTH.mjs} +2 -2
- package/.output/server/_ssr/{console-features-api-X8ItTwxM.mjs → console-features-api-BTeS0zof.mjs} +5 -5
- package/.output/server/_ssr/{console-features-rpc-BRTvGLBV.mjs → console-features-rpc-Cf6Nm0Tm.mjs} +3 -3
- package/.output/server/_ssr/{dialog-L9IrT3sY.mjs → dialog-n7lSfirt.mjs} +1 -1
- package/.output/server/_ssr/{empty-CkTC2uZd.mjs → empty-yUHeIvWw.mjs} +2 -2
- package/.output/server/_ssr/{field-W7Ikmzjb.mjs → field-DI4GVjB2.mjs} +2 -2
- package/.output/server/_ssr/{input-group-BFnD9l_p.mjs → input-group-D2NsIUQe.mjs} +1 -1
- package/.output/server/_ssr/{insights-api-Cuz8lmZx.mjs → insights-api-dRPjuTC6.mjs} +3 -3
- package/.output/server/_ssr/{insights-failures-rpc-CxI071Ew.mjs → insights-failures-rpc-B3sIkMZL.mjs} +4 -4
- package/.output/server/_ssr/{insights-CtPYme4Q.mjs → insights-hQsGvChW.mjs} +19 -19
- package/.output/server/_ssr/{insights-Dz42GlcZ.mjs → insights-pDzs-nig.mjs} +2 -2
- package/.output/server/_ssr/{insights-recovery-rpc-B-9bs9Gz.mjs → insights-recovery-rpc-BEKMGqnd.mjs} +3 -3
- package/.output/server/_ssr/{insights-rpc-5NfC16-Q.mjs → insights-rpc-4Ua-Rrkb.mjs} +3 -3
- package/.output/server/_ssr/{insights-search-CtQj0m7f.mjs → insights-search-B46dHNwI.mjs} +2 -2
- package/.output/server/_ssr/{insights-usage-rpc-CFWx4_pK.mjs → insights-usage-rpc-C1Kd9bIa.mjs} +3 -3
- package/.output/server/_ssr/{insights-usage-rpc-Qnyviyah.mjs → insights-usage-rpc-vSM27rBC.mjs} +3 -3
- package/.output/server/_ssr/{insights-C9KDOFcN.mjs → insights-y7OKDFkt.mjs} +5 -5
- package/.output/server/_ssr/{insights_.distribution-CXItWbX1.mjs → insights_.distribution-COe2wJ5u.mjs} +13 -13
- package/.output/server/_ssr/{insights_.distribution-BamrEztu.mjs → insights_.distribution-Dhzmd8Nc.mjs} +5 -5
- package/.output/server/_ssr/{insights_.distribution-Czd0Jtle.mjs → insights_.distribution-y-zG-kBD.mjs} +2 -2
- package/.output/server/_ssr/{installations-BaHA_zCp.mjs → installations-Bi9QnC2R.mjs} +2 -2
- package/.output/server/_ssr/{installations-Q6t6CEZ8.mjs → installations-CoY4Usdk.mjs} +11 -11
- package/.output/server/_ssr/{installations-Dy8zAJI_.mjs → installations-CtcBn-oO.mjs} +4 -4
- package/.output/server/_ssr/{native-builds-BWTUWJUF.mjs → native-builds-CNY5cOzi.mjs} +2 -2
- package/.output/server/_ssr/{native-builds-Cuw87Y51.mjs → native-builds-CY_3E2YI.mjs} +24 -83
- package/.output/server/_ssr/{native-builds_._buildId-Dr3Mc32p.mjs → native-builds_._buildId-BwqRJrtG.mjs} +2 -2
- package/.output/server/_ssr/{native-builds_._buildId-CbhHK93c.mjs → native-builds_._buildId-DBFNbZbW.mjs} +50 -26
- package/.output/server/_ssr/{release-adoption-rpc-BHxQWHWw.mjs → release-adoption-rpc-DTGL6Iq8.mjs} +5 -5
- package/.output/server/_ssr/{remote-config-Bmh0t1FQ.mjs → remote-config-BMBuTQ8-.mjs} +17 -17
- package/.output/server/_ssr/{remote-config-DWlhe-Nu.mjs → remote-config-BS7gD-T2.mjs} +2 -2
- package/.output/server/_ssr/{remote-config-CrVQfJ9y.mjs → remote-config-BkRETRdL.mjs} +2 -2
- package/.output/server/_ssr/{remote-config-rpc-BYJbiG9k.mjs → remote-config-rpc-iaISfgVV.mjs} +3 -3
- package/.output/server/_ssr/{router-Bg_TI2qP.mjs → router-CskHODBx.mjs} +54 -32
- package/.output/server/_ssr/{routes-Do9CHvbC.mjs → routes-Cc0tMcVR.mjs} +17 -17
- package/.output/server/_ssr/{routes-fs827NQ-.mjs → routes-OvkN78Fv.mjs} +10 -10
- package/.output/server/_ssr/{schema-migration-rpc-vH6ZlJgo.mjs → schema-migration-rpc-BM0ONBoH.mjs} +3 -3
- package/.output/server/_ssr/{select-BoRQ8ytA.mjs → select-Wr3C9fFR.mjs} +1 -1
- package/.output/server/_ssr/{server-DtM4lJ0t.mjs → server-B6NM23G9.mjs} +3 -3
- package/.output/server/_ssr/{sidebar-D1AgCVIN.mjs → sidebar-DLSnkI8V.mjs} +2 -2
- package/.output/server/_ssr/ssr.mjs +1 -1
- package/.output/server/_ssr/{switch-CY0ZEeD2.mjs → switch-A-ACWcS7.mjs} +2 -2
- package/.output/server/_ssr/{table-ClsVe-Mz.mjs → table-BIKD-aZQ.mjs} +1 -1
- package/.output/server/_ssr/{tabs-BJacHKeX.mjs → tabs-DRHoxI4L.mjs} +2 -2
- package/.output/server/{_tanstack-start-manifest_v-CF4kCd6q.mjs → _tanstack-start-manifest_v-uhJWytDm.mjs} +9 -9
- package/.output/server/index.mjs +138 -138
- package/package.json +7 -7
- package/src/components/ConsoleAccessPage.tsx +36 -6
- package/src/components/features/native-builds/CopyableText.tsx +5 -2
- package/src/components/features/native-builds/ImportBuild.tsx +7 -31
- package/src/components/features/native-builds/InstallCard.tsx +47 -24
- package/src/components/features/native-builds/NativeBuildsTable.tsx +4 -6
- package/src/routes/api/native-builds/$buildId/download.ts +9 -4
- package/.output/public/assets/StoreSubmission-JpngSvHS.js +0 -1
- package/.output/public/assets/native-builds-BswZazmc.js +0 -1
- package/.output/public/assets/native-builds_._buildId-BRiNTN3j.js +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/console",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.0-rc.
|
|
4
|
+
"version": "1.2.0-rc.10",
|
|
5
5
|
"files": [
|
|
6
6
|
".output",
|
|
7
7
|
"lib",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"tw-animate-css": "^1.4.0",
|
|
60
60
|
"uqr": "^0.1.3",
|
|
61
61
|
"verkit": "0.4.0",
|
|
62
|
-
"@hot-updater/bsdiff": "1.2.0-rc.
|
|
63
|
-
"@hot-updater/
|
|
64
|
-
"@hot-updater/
|
|
65
|
-
"@hot-updater/server": "1.2.0-rc.
|
|
62
|
+
"@hot-updater/bsdiff": "1.2.0-rc.10",
|
|
63
|
+
"@hot-updater/protocol": "1.2.0-rc.10",
|
|
64
|
+
"@hot-updater/plugin-core": "1.2.0-rc.10",
|
|
65
|
+
"@hot-updater/server": "1.2.0-rc.10"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@tanstack/devtools-vite": "^0.6.0",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"vite-tsconfig-paths": "^6.1.1",
|
|
88
88
|
"vitest": "4.1.4",
|
|
89
89
|
"web-vitals": "^5.1.0",
|
|
90
|
-
"@hot-updater/
|
|
91
|
-
"@hot-updater/
|
|
90
|
+
"@hot-updater/mock": "1.2.0-rc.10",
|
|
91
|
+
"@hot-updater/cli-tools": "1.2.0-rc.10"
|
|
92
92
|
},
|
|
93
93
|
"description": "React Native OTA solution for self-hosted",
|
|
94
94
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { HotUpdaterLogo } from "@/components/HotUpdaterLogo";
|
|
4
4
|
import { Button } from "@/components/ui/button";
|
|
@@ -15,19 +15,40 @@ const providerLabel: Record<ConsoleAuthProvider, string> = {
|
|
|
15
15
|
google: "Google",
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
/** A path on this console, or the root for anything that could leave it. */
|
|
19
|
+
const consolePath = (target: string) =>
|
|
20
|
+
target.startsWith("/") && !/^\/[/\\]/.test(target) ? target : "/";
|
|
21
|
+
|
|
18
22
|
/**
|
|
19
23
|
* Where sign-in returns to: the page that asked for it, as a path on this
|
|
20
|
-
* console, so a link to a build lands on that build.
|
|
21
|
-
*
|
|
24
|
+
* console, so a link to a build lands on that build. A page a route sent
|
|
25
|
+
* here names its own target in `returnTo`, relative to the page, as the
|
|
26
|
+
* native build download does: sign-in returns there instead, when it is on
|
|
27
|
+
* this console's origin. Anything that could leave the console, such as
|
|
28
|
+
* `//host` or `/\host`, returns to the page, or to the root.
|
|
22
29
|
*/
|
|
23
30
|
export const signInCallbackURL = (location: {
|
|
31
|
+
readonly href: string;
|
|
24
32
|
readonly pathname: string;
|
|
25
33
|
readonly search: string;
|
|
26
34
|
}): string => {
|
|
27
|
-
const
|
|
28
|
-
|
|
35
|
+
const page = consolePath(`${location.pathname}${location.search}`);
|
|
36
|
+
const returnTo = new URLSearchParams(location.search).get("returnTo");
|
|
37
|
+
if (returnTo === null) return page;
|
|
38
|
+
try {
|
|
39
|
+
const target = new URL(returnTo, location.href);
|
|
40
|
+
return target.origin === new URL(location.href).origin
|
|
41
|
+
? consolePath(`${target.pathname}${target.search}`)
|
|
42
|
+
: page;
|
|
43
|
+
} catch {
|
|
44
|
+
return page;
|
|
45
|
+
}
|
|
29
46
|
};
|
|
30
47
|
|
|
48
|
+
/** Whether sign-in returns to a native build's download. */
|
|
49
|
+
const returnsToDownload = (callbackURL: string) =>
|
|
50
|
+
/\/api\/native-builds\/[^/]+\/download$/.test(callbackURL);
|
|
51
|
+
|
|
31
52
|
export function ConsoleAccessPage({
|
|
32
53
|
access,
|
|
33
54
|
providers,
|
|
@@ -35,6 +56,13 @@ export function ConsoleAccessPage({
|
|
|
35
56
|
const [pendingProvider, setPendingProvider] =
|
|
36
57
|
useState<ConsoleAuthProvider | null>(null);
|
|
37
58
|
const [signingOut, setSigningOut] = useState(false);
|
|
59
|
+
// Read after the page mounts: the server renders it without a location.
|
|
60
|
+
const [downloadAfterSignIn, setDownloadAfterSignIn] = useState(false);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
setDownloadAfterSignIn(
|
|
63
|
+
returnsToDownload(signInCallbackURL(window.location)),
|
|
64
|
+
);
|
|
65
|
+
}, []);
|
|
38
66
|
const [error, setError] = useState<string | null>(null);
|
|
39
67
|
|
|
40
68
|
const signIn = async (provider: ConsoleAuthProvider) => {
|
|
@@ -87,7 +115,9 @@ export function ConsoleAccessPage({
|
|
|
87
115
|
<div>
|
|
88
116
|
<h1 className="text-lg font-semibold">Hot Updater Console</h1>
|
|
89
117
|
<p className="text-muted-foreground text-sm">
|
|
90
|
-
|
|
118
|
+
{downloadAfterSignIn
|
|
119
|
+
? "Sign in to download the build. It starts once you're in."
|
|
120
|
+
: "Sign in to manage OTA bundles."}
|
|
91
121
|
</p>
|
|
92
122
|
</div>
|
|
93
123
|
</div>
|
|
@@ -12,7 +12,10 @@ export function CopyableText({
|
|
|
12
12
|
/** What the copy button copies, such as "the install command". */
|
|
13
13
|
readonly label: string;
|
|
14
14
|
readonly value: string;
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Whether a value too wide for a phone breaks at its spaces there instead
|
|
17
|
+
* of scrolling, so all of it shows: one line from `sm` up.
|
|
18
|
+
*/
|
|
16
19
|
readonly wrap?: boolean;
|
|
17
20
|
}) {
|
|
18
21
|
const copy = async () => {
|
|
@@ -28,7 +31,7 @@ export function CopyableText({
|
|
|
28
31
|
<code
|
|
29
32
|
className={
|
|
30
33
|
wrap
|
|
31
|
-
? "min-w-0 flex-1 text-left font-mono text-xs
|
|
34
|
+
? "min-w-0 flex-1 text-left font-mono text-xs whitespace-normal sm:whitespace-nowrap"
|
|
32
35
|
: "min-w-0 flex-1 overflow-x-auto text-left font-mono text-xs whitespace-nowrap"
|
|
33
36
|
}
|
|
34
37
|
>
|
|
@@ -13,42 +13,18 @@ import {
|
|
|
13
13
|
import { CopyableText } from "./CopyableText";
|
|
14
14
|
|
|
15
15
|
/** The command that tracks a build made elsewhere. */
|
|
16
|
-
export const IMPORT_COMMAND =
|
|
17
|
-
"npx hot-updater native-build import <path-to-.ipa|.aab|.apk|.app|.app.zip>";
|
|
16
|
+
export const IMPORT_COMMAND = "npx hot-updater native-build import <file>";
|
|
18
17
|
|
|
19
18
|
/** `native-build import`'s section of the native build guide. */
|
|
20
19
|
export const IMPORT_GUIDE_URL =
|
|
21
20
|
"https://hot-updater.dev/docs/guides/native-build#import-a-build-made-elsewhere";
|
|
22
21
|
|
|
23
22
|
/**
|
|
24
|
-
*
|
|
25
|
-
* artifact on the machine that has it
|
|
26
|
-
* host may cap a request's body far below an `.ipa`.
|
|
23
|
+
* The toolbar's "Import a build" button and the command it shows: the CLI
|
|
24
|
+
* reads the artifact on the machine that has it, so the Console uploads
|
|
25
|
+
* nothing, since a host may cap a request's body far below an `.ipa`. The
|
|
26
|
+
* guide has the rest, such as `--channel`.
|
|
27
27
|
*/
|
|
28
|
-
export function ImportBuildSteps() {
|
|
29
|
-
return (
|
|
30
|
-
<div className="flex min-w-0 flex-col gap-2">
|
|
31
|
-
<p className="text-xs text-muted-foreground">
|
|
32
|
-
Track an <code className="font-mono">.ipa</code>,{" "}
|
|
33
|
-
<code className="font-mono">.aab</code>,{" "}
|
|
34
|
-
<code className="font-mono">.apk</code> or simulator{" "}
|
|
35
|
-
<code className="font-mono">.app</code> (or its{" "}
|
|
36
|
-
<code className="font-mono">.app.zip</code>) built elsewhere, such as by
|
|
37
|
-
EAS, Xcode Cloud or Fastlane, so the OTAs you deploy after it patch from
|
|
38
|
-
its built-in bundle. Run in the app's project:
|
|
39
|
-
</p>
|
|
40
|
-
<CopyableText label="the import command" value={IMPORT_COMMAND} wrap />
|
|
41
|
-
<p className="text-xs text-muted-foreground">
|
|
42
|
-
Add <code className="font-mono">-c <channel></code> (
|
|
43
|
-
<code className="font-mono">--channel</code>) when the app reports
|
|
44
|
-
another channel than the one it was built with, such as one its code
|
|
45
|
-
sets or switches to at runtime.
|
|
46
|
-
</p>
|
|
47
|
-
</div>
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** The toolbar's "Import a build" button and the command it shows. */
|
|
52
28
|
export function ImportBuildDialog() {
|
|
53
29
|
return (
|
|
54
30
|
<Dialog>
|
|
@@ -69,10 +45,10 @@ export function ImportBuildDialog() {
|
|
|
69
45
|
<DialogHeader>
|
|
70
46
|
<DialogTitle>Import a build</DialogTitle>
|
|
71
47
|
<DialogDescription>
|
|
72
|
-
|
|
48
|
+
Track an .ipa, .aab, .apk or .app built elsewhere as a patch base.
|
|
73
49
|
</DialogDescription>
|
|
74
50
|
</DialogHeader>
|
|
75
|
-
<
|
|
51
|
+
<CopyableText label="the import command" value={IMPORT_COMMAND} wrap />
|
|
76
52
|
<a
|
|
77
53
|
className={buttonVariants({
|
|
78
54
|
className: "min-h-11 w-full sm:min-h-8 sm:w-fit",
|
|
@@ -17,12 +17,25 @@ import {
|
|
|
17
17
|
import { CopyableText } from "./CopyableText";
|
|
18
18
|
import { isSubmitted } from "./StoreSubmission";
|
|
19
19
|
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* What an artifact installs on, where the file alone isn't enough: the card
|
|
22
|
+
* says it once, under the QR code, or without one, in its place.
|
|
23
|
+
*/
|
|
24
|
+
const INSTALL_LIMITS: Partial<Record<NativeBuildRow["artifact_kind"], string>> =
|
|
25
|
+
{
|
|
26
|
+
ipa: "The .ipa installs only on devices its signing profile allows (development or ad hoc); an App Store export reaches testers through TestFlight.",
|
|
27
|
+
aab: "The .aab installs through Google Play or bundletool, not from the file.",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* What scanning a build's QR code gets, by its artifact. The install steps
|
|
32
|
+
* beside it add only what this doesn't say, so the card says each thing once.
|
|
33
|
+
*/
|
|
21
34
|
const QR_CAPTIONS: Record<NativeBuildRow["artifact_kind"], string> = {
|
|
22
35
|
apk: "Scan with an Android phone's camera, then open the APK to install it.",
|
|
23
|
-
ipa:
|
|
24
|
-
aab:
|
|
25
|
-
app: "Scan to download the .app.zip on a Mac
|
|
36
|
+
ipa: `Scan to download. ${INSTALL_LIMITS.ipa}`,
|
|
37
|
+
aab: `Scan to download. ${INSTALL_LIMITS.aab}`,
|
|
38
|
+
app: "Scan to download the .app.zip on a Mac.",
|
|
26
39
|
};
|
|
27
40
|
|
|
28
41
|
/**
|
|
@@ -36,12 +49,16 @@ function DownloadQrCode({ build }: { readonly build: NativeBuildRow }) {
|
|
|
36
49
|
// A storage without download URLs serves the build only through the
|
|
37
50
|
// console, which a phone that scans isn't signed in to.
|
|
38
51
|
if (url === null) {
|
|
52
|
+
const limits = INSTALL_LIMITS[build.artifact_kind];
|
|
39
53
|
return (
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
54
|
+
<div className="flex flex-col gap-2 text-xs text-muted-foreground">
|
|
55
|
+
<p>
|
|
56
|
+
This storage gives no download link a phone can open without signing
|
|
57
|
+
in, so there is no QR code. Download the build here, or open this page
|
|
58
|
+
on the phone signed in to the console.
|
|
59
|
+
</p>
|
|
60
|
+
{limits ? <p>{limits}</p> : null}
|
|
61
|
+
</div>
|
|
45
62
|
);
|
|
46
63
|
}
|
|
47
64
|
|
|
@@ -80,7 +97,10 @@ function SubmittedVersion({ build }: { readonly build: NativeBuildRow }) {
|
|
|
80
97
|
);
|
|
81
98
|
}
|
|
82
99
|
|
|
83
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* How else the artifact installs, beside its QR code's caption and its
|
|
102
|
+
* download: none of it repeats the caption.
|
|
103
|
+
*/
|
|
84
104
|
function InstallSteps({ build }: { readonly build: NativeBuildRow }) {
|
|
85
105
|
switch (build.artifact_kind) {
|
|
86
106
|
case "apk":
|
|
@@ -99,8 +119,7 @@ function InstallSteps({ build }: { readonly build: NativeBuildRow }) {
|
|
|
99
119
|
return (
|
|
100
120
|
<div className="flex min-w-0 flex-col gap-2">
|
|
101
121
|
<p className="text-xs text-muted-foreground">
|
|
102
|
-
|
|
103
|
-
archive, then install it on the booted simulator:
|
|
122
|
+
It runs only in the iOS Simulator. Install it on the booted one:
|
|
104
123
|
</p>
|
|
105
124
|
<CopyableText
|
|
106
125
|
label="the install command"
|
|
@@ -112,27 +131,30 @@ function InstallSteps({ build }: { readonly build: NativeBuildRow }) {
|
|
|
112
131
|
return isSubmitted(build) ? (
|
|
113
132
|
<p className="text-xs text-muted-foreground">
|
|
114
133
|
Submitted to Google Play internal testing as{" "}
|
|
115
|
-
<SubmittedVersion build={build} />. Testers
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
<SubmittedVersion build={build} />. Testers get it once its release is
|
|
135
|
+
rolled out; on an app Play Console hasn't published, the release is a
|
|
136
|
+
draft you roll out in Play Console.
|
|
118
137
|
</p>
|
|
119
138
|
) : (
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
139
|
+
<div className="flex min-w-0 flex-col gap-2">
|
|
140
|
+
<p className="text-xs text-muted-foreground">
|
|
141
|
+
For testers, build and release to internal testing:
|
|
142
|
+
</p>
|
|
143
|
+
<CopyableText
|
|
144
|
+
label="the Google Play command"
|
|
145
|
+
value="npx hot-updater google-play upload"
|
|
146
|
+
/>
|
|
147
|
+
</div>
|
|
124
148
|
);
|
|
125
149
|
case "ipa":
|
|
126
150
|
return isSubmitted(build) ? (
|
|
127
151
|
<p className="text-xs text-muted-foreground">
|
|
128
|
-
On TestFlight as <SubmittedVersion build={build}
|
|
129
|
-
it from TestFlight.
|
|
152
|
+
On TestFlight as <SubmittedVersion build={build} />.
|
|
130
153
|
</p>
|
|
131
154
|
) : (
|
|
132
155
|
<div className="flex min-w-0 flex-col gap-2">
|
|
133
156
|
<p className="text-xs text-muted-foreground">
|
|
134
|
-
|
|
135
|
-
Configurator. For testers, upload it to TestFlight:
|
|
157
|
+
Over USB, Xcode or Apple Configurator installs it. For testers:
|
|
136
158
|
</p>
|
|
137
159
|
<CopyableText
|
|
138
160
|
label="the TestFlight command"
|
|
@@ -146,7 +168,8 @@ function InstallSteps({ build }: { readonly build: NativeBuildRow }) {
|
|
|
146
168
|
/**
|
|
147
169
|
* Installs one native build: every artifact by a QR code of its download,
|
|
148
170
|
* which a phone scans, and by download here; an APK also with `adb`, a
|
|
149
|
-
* simulator app with `xcrun simctl`, and an IPA's testers
|
|
171
|
+
* simulator app with `xcrun simctl`, and an IPA's or an AAB's testers through
|
|
172
|
+
* its store.
|
|
150
173
|
*/
|
|
151
174
|
export function InstallCard({ build }: { readonly build: NativeBuildRow }) {
|
|
152
175
|
const fileName = nativeBuildFileName(build);
|
|
@@ -47,7 +47,7 @@ import { ShortHash } from "./ShortHash";
|
|
|
47
47
|
import { StoreSubmissionBadge } from "./StoreSubmission";
|
|
48
48
|
|
|
49
49
|
export const NATIVE_BUILD_GUIDE_URL =
|
|
50
|
-
"https://hot-updater.dev/docs/guides/native-build#
|
|
50
|
+
"https://hot-updater.dev/docs/guides/native-build#how-a-build-is-tracked";
|
|
51
51
|
|
|
52
52
|
const COLUMNS = 6;
|
|
53
53
|
|
|
@@ -104,12 +104,10 @@ function EmptyRow({
|
|
|
104
104
|
<>
|
|
105
105
|
<p className="font-medium text-foreground">No native builds</p>
|
|
106
106
|
<p>
|
|
107
|
-
Build
|
|
108
|
-
<code className="font-mono text-xs">
|
|
109
|
-
hot-updater native-build android
|
|
110
|
-
</code>{" "}
|
|
107
|
+
Build one with{" "}
|
|
108
|
+
<code className="font-mono text-xs">native-build android</code>{" "}
|
|
111
109
|
or <code className="font-mono text-xs">native-build ios</code>,
|
|
112
|
-
|
|
110
|
+
or import one built elsewhere:
|
|
113
111
|
</p>
|
|
114
112
|
<div className="w-full text-left">
|
|
115
113
|
<CopyableText
|
|
@@ -20,18 +20,23 @@ export const Route = createFileRoute("/api/native-builds/$buildId/download")({
|
|
|
20
20
|
deps = await prepareConfig(request);
|
|
21
21
|
} catch (error) {
|
|
22
22
|
// A browser without a session opens the build's page instead,
|
|
23
|
-
// where the console signs it in and returns to
|
|
24
|
-
//
|
|
25
|
-
// own path, wherever that is
|
|
23
|
+
// where the console signs it in and returns to this download
|
|
24
|
+
// (`returnTo`, relative to that page). Both paths are relative,
|
|
25
|
+
// so they stay under the console's own path, wherever that is
|
|
26
|
+
// mounted; sign-in takes `returnTo` only on the console's origin.
|
|
26
27
|
if (
|
|
27
28
|
error instanceof Response &&
|
|
28
29
|
error.status === 401 &&
|
|
29
30
|
isNavigation(request)
|
|
30
31
|
) {
|
|
32
|
+
const buildId = encodeURIComponent(params.buildId);
|
|
33
|
+
const returnTo = encodeURIComponent(
|
|
34
|
+
`../api/native-builds/${buildId}/download`,
|
|
35
|
+
);
|
|
31
36
|
return new Response(null, {
|
|
32
37
|
headers: {
|
|
33
38
|
"cache-control": "no-store",
|
|
34
|
-
location: `../../../native-builds/${
|
|
39
|
+
location: `../../../native-builds/${buildId}?returnTo=${returnTo}`,
|
|
35
40
|
},
|
|
36
41
|
status: 302,
|
|
37
42
|
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Fn as e,Wr as t,ii as n,ir as r}from"./sidebar-Di9SN47G.js";import{d as i}from"./native-builds-BOC71grI.js";import{t as a}from"./copy-DsuLj3oj.js";import{t as o}from"./badge-DWFcDWho.js";import{n as s}from"./dist-CPlO6ko9.js";import{n as c,t as l}from"./relativeTime-YQt84dYr.js";import{a as u}from"./api-P2g8dCNg.js";var d=r(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]),f=t();function p({label:t,value:n,wrap:r=!1}){let i=async()=>{try{await navigator.clipboard.writeText(n),s.success(`Copied to clipboard`)}catch{s.error(`Could not copy ${t}`)}};return(0,f.jsxs)(`div`,{className:`flex w-full min-w-0 items-center gap-2 rounded-md border bg-muted/40 py-1 pr-1 pl-3`,children:[(0,f.jsx)(`code`,{className:r?`min-w-0 flex-1 text-left font-mono text-xs break-all whitespace-pre-wrap`:`min-w-0 flex-1 overflow-x-auto text-left font-mono text-xs whitespace-nowrap`,children:n}),(0,f.jsx)(e,{"aria-label":`Copy ${t}`,className:`size-11 sm:size-7`,onClick:()=>void i(),size:`icon-sm`,variant:`ghost`,children:(0,f.jsx)(a,{"aria-hidden":`true`})})]})}function m({value:e,length:t,label:n}){let r=async()=>{try{await navigator.clipboard.writeText(e),s.success(`Copied to clipboard`,{description:e})}catch{s.error(`Could not copy the ${n}`)}};return(0,f.jsx)(`button`,{"aria-label":`Copy the ${n} ${e}`,className:`cursor-copy rounded-sm font-mono text-xs whitespace-nowrap tabular-nums underline-offset-4 hover:underline focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none`,onClick:e=>{e.stopPropagation(),r()},title:e,translate:`no`,type:`button`,children:e.slice(0,t)})}function h({hash:e}){let t=u();if(e===null)return(0,f.jsx)(`span`,{className:`text-muted-foreground`,children:`—`});let n=i(t.data?.console.gitUrl,e);return n===null?(0,f.jsx)(m,{label:`commit`,length:7,value:e}):(0,f.jsx)(`a`,{className:`font-mono text-xs whitespace-nowrap underline-offset-4 hover:underline`,href:n,onClick:e=>e.stopPropagation(),rel:`noreferrer`,target:`_blank`,title:e,translate:`no`,children:e.slice(0,7)})}var g=n(c(),1),_=n(l(),1);g.default.extend(_.default);var v={testflight:`TestFlight`,"play-internal":`Play internal`},y=e=>e.submitted_to!==null&&e.submitted_to!==void 0;function b({ms:e}){if(e===null)return null;let t=(0,g.default)(e);return(0,f.jsx)(`time`,{className:`text-xs text-muted-foreground`,dateTime:t.toISOString(),title:t.format(`YYYY-MM-DD HH:mm:ss`),children:t.fromNow()})}function x({build:e,withTime:t=!1}){return y(e)?(0,f.jsxs)(`span`,{className:`inline-flex flex-wrap items-center gap-1.5`,children:[(0,f.jsxs)(o,{className:`gap-1`,title:`Submitted to ${v[e.submitted_to]}`,variant:`secondary`,children:[(0,f.jsx)(d,{"aria-hidden":`true`,className:`size-3`}),v[e.submitted_to],e.submitted_version?(0,f.jsx)(`span`,{className:`font-mono tabular-nums`,translate:`no`,children:e.submitted_version}):null]}),t?(0,f.jsx)(b,{ms:e.submitted_at_ms}):null]}):null}export{p as a,m as i,y as n,h as r,x as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{$ as e,Fn as t,In as n,Wr as r,ir as i,p as a}from"./sidebar-Di9SN47G.js";import{t as o}from"./link-DTEyW70e.js";import{a as s}from"./preload-helper-B44EvKhG.js";import{t as c}from"./arrow-up-right-DK8Zdg40.js";import{a as l,c as u,f as d,i as ee,n as f,o as p,p as m,r as h,s as g}from"./native-builds-BOC71grI.js";import{t as _}from"./chevron-right-BoUXo82O.js";import{a as v,i as y,n as te,o as ne,r as re,t as ie}from"./select-CBIU0_M1.js";import{t as ae}from"./download-Cf24LBde.js";import{r as oe}from"./-native-builds-search-C-TGpFAm.js";import{t as b}from"./refresh-cw-B9HHjLej.js";import{a as x,i as S,r as C,t as w}from"./StoreSubmission-JpngSvHS.js";import{a as T,f as E,i as D,n as O,o as k,r as A,s as j,t as M}from"./badge-DWFcDWho.js";import{t as N}from"./native-builds-c4BpOLAe.js";import{t as P}from"./PlatformIcon-BBWQlWm9.js";import{a as F,n as I,o as L,r as R,s as z,t as se}from"./dialog-CNUPxNxH.js";import{f as B,i as V}from"./api-P2g8dCNg.js";import{a as H,i as U,n as W,o as G,r as K,t as ce}from"./table-Bpy3SvSo.js";var le=i(`file-up`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M12 12v6`,key:`3ahymv`}],[`path`,{d:`m15 15-3-3-3 3`,key:`15xj92`}]]),ue=i(`hard-drive-download`,[[`path`,{d:`M12 2v8`,key:`1q4o3n`}],[`path`,{d:`m16 6-4 4-4-4`,key:`6wukr`}],[`rect`,{width:`20`,height:`8`,x:`2`,y:`14`,rx:`2`,key:`w68u3i`}],[`path`,{d:`M6 18h.01`,key:`uhywen`}],[`path`,{d:`M10 18h.01`,key:`h775k`}]]),q=r(),J=`npx hot-updater native-build import <path-to-.ipa|.aab|.apk|.app|.app.zip>`,Y=`https://hot-updater.dev/docs/guides/native-build#import-a-build-made-elsewhere`;function de(){return(0,q.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-2`,children:[(0,q.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Track an `,(0,q.jsx)(`code`,{className:`font-mono`,children:`.ipa`}),`,`,` `,(0,q.jsx)(`code`,{className:`font-mono`,children:`.aab`}),`,`,` `,(0,q.jsx)(`code`,{className:`font-mono`,children:`.apk`}),` or simulator`,` `,(0,q.jsx)(`code`,{className:`font-mono`,children:`.app`}),` (or its`,` `,(0,q.jsx)(`code`,{className:`font-mono`,children:`.app.zip`}),`) built elsewhere, such as by EAS, Xcode Cloud or Fastlane, so the OTAs you deploy after it patch from its built-in bundle. Run in the app's project:`]}),(0,q.jsx)(x,{label:`the import command`,value:J,wrap:!0}),(0,q.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Add `,(0,q.jsx)(`code`,{className:`font-mono`,children:`-c <channel>`}),` (`,(0,q.jsx)(`code`,{className:`font-mono`,children:`--channel`}),`) when the app reports another channel than the one it was built with, such as one its code sets or switches to at runtime.`]})]})}function fe(){return(0,q.jsxs)(se,{children:[(0,q.jsxs)(z,{render:(0,q.jsx)(t,{"aria-label":`Import a build`,className:`min-h-11 sm:min-h-7`,size:`sm`,variant:`outline`}),children:[(0,q.jsx)(le,{"data-icon":`inline-start`}),(0,q.jsx)(`span`,{className:`hidden sm:inline`,children:`Import a build`})]}),(0,q.jsxs)(I,{className:`sm:max-w-lg`,children:[(0,q.jsxs)(F,{children:[(0,q.jsx)(L,{children:`Import a build`}),(0,q.jsx)(R,{children:`The build appears here once the command tracks it.`})]}),(0,q.jsx)(de,{}),(0,q.jsxs)(`a`,{className:n({className:`min-h-11 w-full sm:min-h-8 sm:w-fit`,variant:`outline`}),href:Y,rel:`noreferrer`,target:`_blank`,children:[`Import guide`,(0,q.jsx)(c,{"data-icon":`inline-end`})]})]})]})}var pe=`https://hot-updater.dev/docs/guides/native-build#register-a-build`,me=6;function he({channel:e,paged:r,onClearChannel:i,onNewest:a}){return(0,q.jsx)(G,{children:(0,q.jsx)(K,{className:`h-44 text-center text-muted-foreground`,colSpan:me,children:(0,q.jsxs)(`div`,{className:`mx-auto flex max-w-sm flex-col items-center gap-2 whitespace-normal`,children:[(0,q.jsx)(ue,{"aria-hidden":`true`,className:`size-5`}),r?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`p`,{className:`font-medium text-foreground`,children:`No more native builds`}),(0,q.jsx)(t,{className:`mt-1 min-h-11 sm:min-h-8`,onClick:a,variant:`outline`,children:`Show the newest builds`})]}):e===void 0?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`p`,{className:`font-medium text-foreground`,children:`No native builds`}),(0,q.jsxs)(`p`,{children:[`Build a release app with`,` `,(0,q.jsx)(`code`,{className:`font-mono text-xs`,children:`hot-updater native-build android`}),` `,`or `,(0,q.jsx)(`code`,{className:`font-mono text-xs`,children:`native-build ios`}),`, which tracks it here, or import one built elsewhere:`]}),(0,q.jsx)(`div`,{className:`w-full text-left`,children:(0,q.jsx)(x,{label:`the import command`,value:J,wrap:!0})}),(0,q.jsxs)(`a`,{className:n({className:`mt-1 min-h-11 sm:min-h-8`,variant:`outline`}),href:pe,rel:`noreferrer`,target:`_blank`,children:[`Native build guide`,(0,q.jsx)(c,{"data-icon":`inline-end`})]}),(0,q.jsxs)(`a`,{className:n({className:`min-h-11 sm:min-h-8`,variant:`outline`}),href:Y,rel:`noreferrer`,target:`_blank`,children:[`Import guide`,(0,q.jsx)(c,{"data-icon":`inline-end`})]})]}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`p`,{className:`font-medium text-foreground`,children:[`No native build embeds `,(0,q.jsx)(`span`,{translate:`no`,children:e})]}),(0,q.jsx)(`p`,{children:`A build embeds the channel it was built on. Build one on this channel, or list every channel's builds.`}),(0,q.jsx)(t,{className:`mt-1 min-h-11 sm:min-h-8`,onClick:i,variant:`outline`,children:`Show all channels`})]})]})})})}function ge(){return Array.from({length:3},(t,n)=>(0,q.jsxs)(G,{children:[(0,q.jsxs)(K,{className:`space-y-2 py-3`,children:[n===0?(0,q.jsx)(`span`,{className:`sr-only`,children:`Loading native builds`}):null,(0,q.jsx)(e,{className:`h-3.5 w-40`}),(0,q.jsx)(e,{className:`h-3 w-24`})]}),(0,q.jsx)(K,{className:`hidden md:table-cell`,children:(0,q.jsx)(e,{className:`h-5 w-20`})}),(0,q.jsx)(K,{className:`hidden xl:table-cell`,children:(0,q.jsx)(e,{className:`h-3.5 w-28`})}),(0,q.jsx)(K,{className:`hidden xl:table-cell`,children:(0,q.jsx)(e,{className:`h-3.5 w-14`})}),(0,q.jsx)(K,{className:`hidden sm:table-cell`,children:(0,q.jsx)(e,{className:`h-3.5 w-20`})}),(0,q.jsx)(K,{children:(0,q.jsx)(e,{className:`ml-auto h-6 w-16`})})]},n))}function X({build:e,onChannel:t}){let r=s(),i=g(e),a=ee(e),c=`${u(e.platform)} ${h[e.artifact_kind].label}`;return(0,q.jsxs)(G,{className:`cursor-pointer`,onClick:()=>void r({to:`/native-builds/$buildId`,params:{buildId:e.id}}),children:[(0,q.jsx)(K,{className:`py-3 whitespace-normal`,children:(0,q.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1`,children:[(0,q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,q.jsx)(P,{className:`size-3.5 shrink-0 text-muted-foreground`,platform:e.platform}),(0,q.jsx)(o,{className:`font-medium underline-offset-4 hover:underline`,onClick:e=>e.stopPropagation(),params:{buildId:e.id},to:`/native-builds/$buildId`,children:c}),(0,q.jsx)(`span`,{className:`text-xs text-muted-foreground tabular-nums`,children:f(e.byte_size)}),(0,q.jsx)(w,{build:e,withTime:!0})]}),(0,q.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-x-1.5 text-xs text-muted-foreground`,children:[(0,q.jsx)(`span`,{children:i.label}),e.fingerprint_hash===null?(0,q.jsx)(`span`,{className:`font-mono text-foreground`,translate:`no`,children:i.value}):(0,q.jsx)(S,{label:`fingerprint`,length:12,value:e.fingerprint_hash}),e.build_number?(0,q.jsxs)(`span`,{className:`tabular-nums`,translate:`no`,children:[`· build `,e.build_number]}):null,(0,q.jsxs)(`span`,{className:`md:hidden`,translate:`no`,children:[`· `,a]}),e.git_commit_hash===null?null:(0,q.jsxs)(`span`,{className:`inline-flex items-center gap-1 xl:hidden`,children:[`· commit `,(0,q.jsx)(C,{hash:e.git_commit_hash})]})]}),(0,q.jsxs)(`div`,{className:`text-xs text-muted-foreground xl:hidden`,children:[`Built-in bundle`,` `,(0,q.jsx)(`span`,{className:`font-mono [overflow-wrap:anywhere] text-foreground`,translate:`no`,children:e.min_bundle_id})]})]})}),(0,q.jsx)(K,{className:`hidden md:table-cell`,children:(0,q.jsx)(`button`,{"aria-label":`Show the builds that embed ${a}`,className:`rounded-md text-left focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none`,onClick:e=>{e.stopPropagation(),t(a)},type:`button`,children:(0,q.jsx)(M,{className:`whitespace-nowrap`,translate:`no`,variant:`outline`,children:a})})}),(0,q.jsx)(K,{className:`hidden xl:table-cell`,children:(0,q.jsx)(`span`,{className:`font-mono text-xs text-muted-foreground`,translate:`no`,children:e.min_bundle_id})}),(0,q.jsx)(K,{className:`hidden xl:table-cell`,children:(0,q.jsx)(C,{hash:e.git_commit_hash})}),(0,q.jsx)(K,{className:`hidden sm:table-cell`,children:(0,q.jsx)(d,{uuid:e.id})}),(0,q.jsx)(K,{className:`text-right`,children:(0,q.jsxs)(`a`,{"aria-label":`Download ${p(e)}`,className:n({className:`min-h-11 sm:min-h-7`,size:`sm`,variant:`outline`}),download:!0,href:l(e.id),onClick:e=>e.stopPropagation(),children:[(0,q.jsx)(ae,{"data-icon":`inline-start`}),`Download`]})})]})}function _e({builds:e,channel:n,paged:r,onChannel:i,onPage:a}){let o=e.data?.data,{next:s,previous:c}=e.data??{};return e.isError?(0,q.jsx)(`div`,{className:`p-4`,children:(0,q.jsxs)(O,{variant:`destructive`,children:[(0,q.jsx)(E,{}),(0,q.jsx)(T,{children:`Native builds couldn't be loaded`}),(0,q.jsx)(D,{children:`Check your connection and try again.`}),(0,q.jsx)(A,{children:(0,q.jsxs)(t,{onClick:()=>void e.refetch(),size:`xs`,variant:`outline`,children:[(0,q.jsx)(b,{"data-icon":`inline-start`}),`Retry`]})})]})}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(ce,{"aria-busy":e.isPlaceholderData,"aria-label":`Native builds`,children:[(0,q.jsx)(H,{children:(0,q.jsxs)(G,{children:[(0,q.jsx)(U,{children:`Build`}),(0,q.jsx)(U,{className:`hidden md:table-cell`,children:`Channel`}),(0,q.jsx)(U,{className:`hidden xl:table-cell`,children:`Built-in bundle`}),(0,q.jsx)(U,{className:`hidden xl:table-cell`,children:`Commit`}),(0,q.jsx)(U,{className:`hidden sm:table-cell`,children:`Created`}),(0,q.jsx)(U,{className:`text-right`,children:(0,q.jsx)(`span`,{className:`sr-only`,children:`Actions`})})]})}),(0,q.jsx)(W,{children:e.isLoading?(0,q.jsx)(ge,{}):o?.length===0?(0,q.jsx)(he,{channel:n,onClearChannel:()=>i(void 0),onNewest:()=>a({}),paged:r}):o?.map(e=>(0,q.jsx)(X,{build:e,onChannel:i},e.id))})]}),s!==void 0||c!==void 0?(0,q.jsxs)(`nav`,{"aria-label":`Native build pages`,className:`flex items-center justify-end gap-2 border-t px-4 py-2`,children:[(0,q.jsxs)(t,{className:`min-h-11 sm:min-h-7`,disabled:c===void 0||e.isPlaceholderData,onClick:()=>a({after:c}),size:`sm`,variant:`ghost`,children:[(0,q.jsx)(m,{"data-icon":`inline-start`}),`Newer`]}),(0,q.jsxs)(t,{className:`min-h-11 sm:min-h-7`,disabled:s===void 0||e.isPlaceholderData,onClick:()=>a({before:s}),size:`sm`,variant:`ghost`,children:[`Older`,(0,q.jsx)(_,{"data-icon":`inline-end`})]})]}):null]})}var Z=`all`,Q=`channel:`,$=e=>`${Q}${e}`;function ve({search:e,onSearchChange:n}){let{channel:r,before:i,after:o}=e,s=B(e),c=V(),l=c.data?.map(({name:e})=>e)??[],u=r===void 0||l.includes(r)?l:[r,...l],d=e=>n(e===void 0?{}:{channel:e});return(0,q.jsxs)(`div`,{className:`flex h-svh min-h-0 flex-col`,children:[(0,q.jsxs)(`header`,{className:`sticky top-0 z-10 flex shrink-0 flex-wrap items-center gap-x-3 gap-y-1 border-b bg-background px-3 py-3 sm:min-h-12 sm:flex-nowrap sm:bg-card/70 sm:px-4 sm:backdrop-blur-sm`,children:[(0,q.jsx)(a,{className:`-ml-1 size-11 lg:size-7`}),(0,q.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,q.jsx)(oe,{"aria-hidden":`true`,className:`size-3.5 text-muted-foreground`}),(0,q.jsx)(`h1`,{className:`text-sm font-medium`,children:`Native builds`})]}),(0,q.jsx)(`p`,{className:`basis-full pl-12 text-xs text-muted-foreground sm:basis-auto sm:pl-0`,children:`Store and test builds, each the built-in bundle its OTAs patch from.`})]}),(0,q.jsx)(`div`,{className:`min-h-0 min-w-0 flex-1 overflow-y-auto bg-muted/5 p-3 sm:p-6`,children:(0,q.jsxs)(k,{className:`mx-auto w-full max-w-6xl overflow-hidden shadow-sm`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2 border-b px-4 py-3`,children:[(0,q.jsxs)(ie,{items:[{label:`All channels`,value:Z},...u.map(e=>({label:e,value:$(e)}))],onOpenChange:e=>{e&&c.refetch()},onValueChange:e=>d(e?.startsWith(Q)?e.slice(8):void 0),value:r===void 0?Z:$(r),children:[(0,q.jsx)(v,{"aria-label":`Channel`,className:`h-11 min-w-0 flex-1 text-xs sm:h-8 sm:w-48 sm:flex-none`,children:(0,q.jsx)(ne,{})}),(0,q.jsx)(te,{children:(0,q.jsxs)(re,{children:[(0,q.jsx)(y,{value:Z,children:`All channels`}),u.map(e=>(0,q.jsx)(y,{translate:`no`,value:$(e),children:e},e))]})})]}),(0,q.jsx)(`div`,{className:`ml-auto`,children:(0,q.jsx)(fe,{})}),(0,q.jsx)(t,{"aria-label":`Refresh native builds`,className:`size-11 sm:size-7`,disabled:s.isLoading,onClick:()=>void s.refetch(),size:`icon-sm`,variant:`ghost`,children:(0,q.jsx)(b,{"aria-hidden":`true`})})]}),(0,q.jsx)(j,{className:`p-0`,children:(0,q.jsx)(_e,{builds:s,channel:r,onChannel:d,onPage:e=>n({...r===void 0?{}:{channel:r},...e}),paged:i!==void 0||o!==void 0})})]})})]})}function ye(){let e=N.useSearch(),t=N.useNavigate();return(0,q.jsx)(ve,{onSearchChange:e=>void t({search:e}),search:e})}export{ye as component};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{$ as e,Fn as t,In as n,Ln as r,Wr as i,ii as a,ir as o,p as s,ti as c}from"./sidebar-Di9SN47G.js";import{t as l}from"./link-DTEyW70e.js";import{t as u}from"./arrow-up-right-DK8Zdg40.js";import{a as d,c as f,f as p,n as m,o as h,p as ee,r as te,s as ne,t as re,u as ie}from"./native-builds-BOC71grI.js";import{t as ae}from"./chevron-right-BoUXo82O.js";import{n as oe,t as g}from"./native-builds_._buildId-9p4FFpa4.js";import{t as se}from"./download-Cf24LBde.js";import{n as ce,t as le}from"./history-DqHlgSuV.js";import{r as ue}from"./-native-builds-search-C-TGpFAm.js";import{t as de}from"./refresh-cw-B9HHjLej.js";import{a as _,i as fe,n as v,r as pe,t as me}from"./StoreSubmission-JpngSvHS.js";import{a as y,d as b,f as x,i as S,n as C,o as w,r as he,s as T,t as E,u as D}from"./badge-DWFcDWho.js";import{r as ge}from"./uuidv7-zXMtwR9Q.js";import{a as O,i as k,n as A,o as j,r as M,t as N}from"./empty-B3Uwdd6k.js";import{t as _e}from"./PlatformIcon-BBWQlWm9.js";import{d as ve,l as ye,u as be}from"./api-P2g8dCNg.js";import{a as P,i as F,n as I,o as L,r as R,t as z}from"./table-Bpy3SvSo.js";import{t as xe}from"./RolloutPercentageBadge-Cxogpi8F.js";var Se=o(`package-open`,[[`path`,{d:`M12 22v-9`,key:`x3hkom`}],[`path`,{d:`M15.17 2.21a1.67 1.67 0 0 1 1.63 0L21 4.57a1.93 1.93 0 0 1 0 3.36L8.82 14.79a1.655 1.655 0 0 1-1.64 0L3 12.43a1.93 1.93 0 0 1 0-3.36z`,key:`2ntwy6`}],[`path`,{d:`M20 13v3.87a2.06 2.06 0 0 1-1.11 1.83l-6 3.08a1.93 1.93 0 0 1-1.78 0l-6-3.08A2.06 2.06 0 0 1 4 16.87V13`,key:`1pmm1c`}],[`path`,{d:`M21 12.43a1.93 1.93 0 0 0 0-3.36L8.83 2.2a1.64 1.64 0 0 0-1.63 0L3 4.57a1.93 1.93 0 0 0 0 3.36l12.18 6.86a1.636 1.636 0 0 0 1.63 0z`,key:`12ttoo`}]]),B=i();function V({label:e,children:t}){return(0,B.jsxs)(`div`,{className:`grid gap-1 sm:grid-cols-[10rem_minmax(0,1fr)] sm:gap-4`,children:[(0,B.jsx)(`dt`,{className:`text-xs font-medium text-muted-foreground`,children:e}),(0,B.jsx)(`dd`,{className:`min-w-0 text-sm`,children:t})]})}function Ce({detail:e}){let{build:t,newestInScope:n}=e;return n===null?null:n.id===t.id?(0,B.jsxs)(`div`,{className:`flex items-start gap-2 rounded-md border bg-muted/40 p-3 text-xs`,children:[(0,B.jsx)(oe,{"aria-hidden":`true`,className:`mt-0.5 size-3.5 shrink-0 text-muted-foreground`}),(0,B.jsxs)(`p`,{children:[(0,B.jsx)(`span`,{className:`font-medium`,children:`Current baseline.`}),` New deploys to this scope add a patch from this build's bundle.`]})]}):(0,B.jsxs)(`div`,{className:`flex items-start gap-2 rounded-md border bg-muted/40 p-3 text-xs`,children:[(0,B.jsx)(le,{"aria-hidden":`true`,className:`mt-0.5 size-3.5 shrink-0 text-muted-foreground`}),(0,B.jsxs)(`p`,{children:[(0,B.jsx)(`span`,{className:`font-medium`,children:`Superseded`}),` by`,` `,(0,B.jsxs)(l,{className:`inline-flex items-center gap-0.5 font-medium underline underline-offset-4`,params:{buildId:n.id},to:`/native-builds/$buildId`,children:[f(n.platform),` `,te[n.artifact_kind].label,` ·`,` `,(0,B.jsx)(p,{uuid:n.id}),(0,B.jsx)(u,{"aria-hidden":`true`,className:`size-3`})]}),`. New deploys patch from that build, so this one gets no new patches.`]})]})}function we({detail:e}){let{build:t,builtInBundle:n,channel:r}=e,i=ne(t),a=n?.childCount??0;return(0,B.jsxs)(w,{className:`overflow-hidden shadow-sm`,children:[(0,B.jsx)(D,{className:`border-b px-4 py-3`,children:(0,B.jsx)(b,{className:`text-sm`,children:(0,B.jsx)(`h2`,{children:`Built-in bundle`})})}),(0,B.jsxs)(T,{className:`flex flex-col gap-4 p-4 sm:p-6`,children:[(0,B.jsxs)(`dl`,{className:`flex flex-col gap-3`,children:[(0,B.jsx)(V,{label:`Bundle ID`,children:(0,B.jsx)(`span`,{className:`break-all font-mono text-xs`,translate:`no`,children:t.min_bundle_id})}),(0,B.jsx)(V,{label:`OTAs patching from it`,children:(0,B.jsx)(`span`,{className:`tabular-nums`,children:a===1?`1 bundle`:`${a} bundles`})}),(0,B.jsx)(V,{label:`Scope`,children:(0,B.jsxs)(`span`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,B.jsx)(l,{"aria-label":`Show the builds that embed ${r}`,search:{channel:r},to:`/native-builds`,children:(0,B.jsx)(E,{translate:`no`,variant:`outline`,children:r})}),(0,B.jsx)(`span`,{className:`text-xs`,children:f(t.platform)}),(0,B.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[`· `,i.label]}),t.fingerprint_hash===null?(0,B.jsx)(`span`,{className:`font-mono text-xs`,translate:`no`,children:i.value}):(0,B.jsx)(fe,{label:`fingerprint`,length:12,value:t.fingerprint_hash})]})}),t.build_number?(0,B.jsx)(V,{label:`Build number`,children:(0,B.jsx)(`span`,{className:`font-mono text-xs tabular-nums`,translate:`no`,children:t.build_number})}):null,v(t)?(0,B.jsx)(V,{label:`Store`,children:(0,B.jsx)(me,{build:t,withTime:!0})}):null,(0,B.jsx)(V,{label:`Commit`,children:(0,B.jsx)(pe,{hash:t.git_commit_hash})}),(0,B.jsx)(V,{label:`Created`,children:(0,B.jsx)(p,{format:`both`,uuid:t.id})})]}),(0,B.jsx)(Ce,{detail:e}),(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`A store or test install of this build runs this bundle until its first OTA. That OTA downloads as a patch from this bundle when one exists, and as the full bundle otherwise.`})]})]})}var Te=a(c(),1),H=(e=>(e[e.Border=-1]=`Border`,e[e.Data=0]=`Data`,e[e.Function=1]=`Function`,e[e.Position=2]=`Position`,e[e.Timing=3]=`Timing`,e[e.Alignment=4]=`Alignment`,e))(H||{}),Ee=[0,1],De=[1,0],Oe=[2,3],ke=[3,2],Ae={L:Ee,M:De,Q:Oe,H:ke},je=/^\d*$/,Me=/^[A-Z0-9 $%*+./:-]*$/,U=`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:`,W=1,G=40,Ne=3,Pe=3,K=40,Fe=10,Ie=[[-1,7,10,15,20,26,18,20,24,30,18,20,24,26,30,22,24,28,30,28,28,28,28,30,30,26,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,10,16,26,18,24,16,18,22,22,26,30,22,22,24,24,28,28,26,26,26,26,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28],[-1,13,22,18,26,18,24,18,22,20,24,28,26,24,20,30,24,28,28,26,30,28,30,30,30,30,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,17,28,22,16,22,28,26,26,24,28,24,28,22,24,24,30,28,28,26,28,30,24,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30]],Le=[[-1,1,1,1,1,1,2,2,2,2,4,4,4,4,4,6,6,6,6,7,8,8,9,9,10,12,12,12,13,14,15,16,17,18,19,19,20,21,22,24,25],[-1,1,1,1,2,2,4,4,4,5,5,5,8,9,9,10,10,11,13,14,16,17,17,18,20,21,23,25,26,28,29,31,33,35,37,38,40,43,45,47,49],[-1,1,1,2,2,4,4,6,6,8,8,8,10,12,16,12,17,16,18,21,20,23,23,25,27,29,34,34,35,38,40,43,45,48,51,53,56,59,62,65,68],[-1,1,1,2,4,4,4,5,6,8,8,11,11,16,16,18,16,19,21,25,25,25,34,30,32,35,37,40,42,45,48,51,54,57,60,63,66,70,74,77,81]],Re=class{constructor(e,t,n,r){if(this.version=e,this.ecc=t,e<W||e>G)throw RangeError(`Version value out of range`);if(r<-1||r>7)throw RangeError(`Mask value out of range`);this.size=e*4+17;let i=Array.from({length:this.size}).fill(!1);for(let e=0;e<this.size;e++)this.modules.push(i.slice()),this.types.push(i.map(()=>0));this.drawFunctionPatterns();let a=this.addEccAndInterleave(n);if(this.drawCodewords(a),r===-1){let e=1e9;for(let t=0;t<8;t++){this.applyMask(t),this.drawFormatBits(t);let n=this.getPenaltyScore();n<e&&(r=t,e=n),this.applyMask(t)}}this.mask=r,this.applyMask(r),this.drawFormatBits(r)}size;mask;modules=[];types=[];getModule(e,t){return e>=0&&e<this.size&&t>=0&&t<this.size&&this.modules[t][e]}drawFunctionPatterns(){for(let e=0;e<this.size;e++)this.setFunctionModule(6,e,e%2==0,H.Timing),this.setFunctionModule(e,6,e%2==0,H.Timing);this.drawFinderPattern(3,3),this.drawFinderPattern(this.size-4,3),this.drawFinderPattern(3,this.size-4);let e=this.getAlignmentPatternPositions(),t=e.length;for(let n=0;n<t;n++)for(let r=0;r<t;r++)n===0&&r===0||n===0&&r===t-1||n===t-1&&r===0||this.drawAlignmentPattern(e[n],e[r]);this.drawFormatBits(0),this.drawVersion()}drawFormatBits(e){let t=this.ecc[1]<<3|e,n=t;for(let e=0;e<10;e++)n=n<<1^(n>>>9)*1335;let r=(t<<10|n)^21522;for(let e=0;e<=5;e++)this.setFunctionModule(8,e,J(r,e));this.setFunctionModule(8,7,J(r,6)),this.setFunctionModule(8,8,J(r,7)),this.setFunctionModule(7,8,J(r,8));for(let e=9;e<15;e++)this.setFunctionModule(14-e,8,J(r,e));for(let e=0;e<8;e++)this.setFunctionModule(this.size-1-e,8,J(r,e));for(let e=8;e<15;e++)this.setFunctionModule(8,this.size-15+e,J(r,e));this.setFunctionModule(8,this.size-8,!0)}drawVersion(){if(this.version<7)return;let e=this.version;for(let t=0;t<12;t++)e=e<<1^(e>>>11)*7973;let t=this.version<<12|e;for(let e=0;e<18;e++){let n=J(t,e),r=this.size-11+e%3,i=Math.floor(e/3);this.setFunctionModule(r,i,n),this.setFunctionModule(i,r,n)}}drawFinderPattern(e,t){for(let n=-4;n<=4;n++)for(let r=-4;r<=4;r++){let i=Math.max(Math.abs(r),Math.abs(n)),a=e+r,o=t+n;a>=0&&a<this.size&&o>=0&&o<this.size&&this.setFunctionModule(a,o,i!==2&&i!==4,H.Position)}}drawAlignmentPattern(e,t){for(let n=-2;n<=2;n++)for(let r=-2;r<=2;r++)this.setFunctionModule(e+r,t+n,Math.max(Math.abs(r),Math.abs(n))!==1,H.Alignment)}setFunctionModule(e,t,n,r=H.Function){this.modules[t][e]=n,this.types[t][e]=r}addEccAndInterleave(e){let t=this.version,n=this.ecc;if(e.length!==Z(t,n))throw RangeError(`Invalid argument`);let r=Le[n[0]][t],i=Ie[n[0]][t],a=Math.floor(X(t)/8),o=r-a%r,s=Math.floor(a/r),c=[],l=Ze(i);for(let t=0,n=0;t<r;t++){let r=e.slice(n,n+s-i+(t<o?0:1));n+=r.length;let a=Qe(r,l);t<o&&r.push(0),c.push(r.concat(a))}let u=[];for(let e=0;e<c[0].length;e++)c.forEach((t,n)=>{(e!==s-i||n>=o)&&u.push(t[e])});return u}drawCodewords(e){if(e.length!==Math.floor(X(this.version)/8))throw RangeError(`Invalid argument`);let t=0;for(let n=this.size-1;n>=1;n-=2){n===6&&(n=5);for(let r=0;r<this.size;r++)for(let i=0;i<2;i++){let a=n-i,o=n+1&2?r:this.size-1-r;!this.types[o][a]&&t<e.length*8&&(this.modules[o][a]=J(e[t>>>3],7-(t&7)),t++)}}}applyMask(e){if(e<0||e>7)throw RangeError(`Mask value out of range`);for(let t=0;t<this.size;t++)for(let n=0;n<this.size;n++){let r;switch(e){case 0:r=(n+t)%2==0;break;case 1:r=t%2==0;break;case 2:r=n%3==0;break;case 3:r=(n+t)%3==0;break;case 4:r=(Math.floor(n/3)+Math.floor(t/2))%2==0;break;case 5:r=n*t%2+n*t%3==0;break;case 6:r=(n*t%2+n*t%3)%2==0;break;case 7:r=((n+t)%2+n*t%3)%2==0;break;default:throw Error(`Unreachable`)}!this.types[t][n]&&r&&(this.modules[t][n]=!this.modules[t][n])}}getPenaltyScore(){let e=0;for(let t=0;t<this.size;t++){let n=!1,r=0,i=[0,0,0,0,0,0,0];for(let a=0;a<this.size;a++)this.modules[t][a]===n?(r++,r===5?e+=Ne:r>5&&e++):(this.finderPenaltyAddHistory(r,i),n||(e+=this.finderPenaltyCountPatterns(i)*K),n=this.modules[t][a],r=1);e+=this.finderPenaltyTerminateAndCount(n,r,i)*K}for(let t=0;t<this.size;t++){let n=!1,r=0,i=[0,0,0,0,0,0,0];for(let a=0;a<this.size;a++)this.modules[a][t]===n?(r++,r===5?e+=Ne:r>5&&e++):(this.finderPenaltyAddHistory(r,i),n||(e+=this.finderPenaltyCountPatterns(i)*K),n=this.modules[a][t],r=1);e+=this.finderPenaltyTerminateAndCount(n,r,i)*K}for(let t=0;t<this.size-1;t++)for(let n=0;n<this.size-1;n++){let r=this.modules[t][n];r===this.modules[t][n+1]&&r===this.modules[t+1][n]&&r===this.modules[t+1][n+1]&&(e+=Pe)}let t=0;for(let e of this.modules)t=e.reduce((e,t)=>e+ +!!t,t);let n=this.size*this.size,r=Math.ceil(Math.abs(t*20-n*10)/n)-1;return e+=r*Fe,e}getAlignmentPatternPositions(){if(this.version===1)return[];{let e=Math.floor(this.version/7)+2,t=this.version===32?26:Math.ceil((this.version*4+4)/(e*2-2))*2,n=[6];for(let r=this.size-7;n.length<e;r-=t)n.splice(1,0,r);return n}}finderPenaltyCountPatterns(e){let t=e[1],n=t>0&&e[2]===t&&e[3]===t*3&&e[4]===t&&e[5]===t;return(n&&e[0]>=t*4&&e[6]>=t?1:0)+(n&&e[6]>=t*4&&e[0]>=t?1:0)}finderPenaltyTerminateAndCount(e,t,n){return e&&(this.finderPenaltyAddHistory(t,n),t=0),t+=this.size,this.finderPenaltyAddHistory(t,n),this.finderPenaltyCountPatterns(n)}finderPenaltyAddHistory(e,t){t[0]===0&&(e+=this.size),t.pop(),t.unshift(e)}};function q(e,t,n){if(t<0||t>31||e>>>t)throw RangeError(`Value out of range`);for(let r=t-1;r>=0;r--)n.push(e>>>r&1)}function J(e,t){return(e>>>t&1)!=0}var Y=class{constructor(e,t,n){if(this.mode=e,this.numChars=t,this.bitData=n,t<0)throw RangeError(`Invalid argument`);this.bitData=n.slice()}getData(){return this.bitData.slice()}},ze=[1,10,12,14],Be=[2,9,11,13],Ve=[4,8,16,16];function He(e,t){return e[Math.floor((t+7)/17)+1]}function Ue(e){let t=[];for(let n of e)q(n,8,t);return new Y(Ve,e.length,t)}function We(e){if(!qe(e))throw RangeError(`String contains non-numeric characters`);let t=[];for(let n=0;n<e.length;){let r=Math.min(e.length-n,3);q(Number.parseInt(e.substring(n,n+r),10),r*3+1,t),n+=r}return new Y(ze,e.length,t)}function Ge(e){if(!Je(e))throw RangeError(`String contains unencodable characters in alphanumeric mode`);let t=[],n;for(n=0;n+2<=e.length;n+=2){let r=U.indexOf(e.charAt(n))*45;r+=U.indexOf(e.charAt(n+1)),q(r,11,t)}return n<e.length&&q(U.indexOf(e.charAt(n)),6,t),new Y(Be,e.length,t)}function Ke(e){return e===``?[]:qe(e)?[We(e)]:Je(e)?[Ge(e)]:[Ue(Xe(e))]}function qe(e){return je.test(e)}function Je(e){return Me.test(e)}function Ye(e,t){let n=0;for(let r of e){let e=He(r.mode,t);if(r.numChars>=1<<e)return 1/0;n+=4+e+r.bitData.length}return n}function Xe(e){e=encodeURI(e);let t=[];for(let n=0;n<e.length;n++)e.charAt(n)===`%`?(t.push(Number.parseInt(e.substring(n+1,n+3),16)),n+=2):t.push(e.charCodeAt(n));return t}function X(e){if(e<W||e>G)throw RangeError(`Version number out of range`);let t=(16*e+128)*e+64;if(e>=2){let n=Math.floor(e/7)+2;t-=(25*n-10)*n-55,e>=7&&(t-=36)}return t}function Z(e,t){return Math.floor(X(e)/8)-Ie[t[0]][e]*Le[t[0]][e]}function Ze(e){if(e<1||e>255)throw RangeError(`Degree out of range`);let t=[];for(let n=0;n<e-1;n++)t.push(0);t.push(1);let n=1;for(let r=0;r<e;r++){for(let e=0;e<t.length;e++)t[e]=Q(t[e],n),e+1<t.length&&(t[e]^=t[e+1]);n=Q(n,2)}return t}function Qe(e,t){let n=t.map(e=>0);for(let r of e){let e=r^n.shift();n.push(0),t.forEach((t,r)=>n[r]^=Q(t,e))}return n}function Q(e,t){if(e>>>8||t>>>8)throw RangeError(`Byte out of range`);let n=0;for(let r=7;r>=0;r--)n=n<<1^(n>>>7)*285,n^=(t>>>r&1)*e;return n}function $e(e,t,n=1,r=40,i=-1,a=!0){if(!(W<=n&&n<=r&&r<=G)||i<-1||i>7)throw RangeError(`Invalid value`);let o,s;for(o=n;;o++){let n=Z(o,t)*8,i=Ye(e,o);if(i<=n){s=i;break}if(o>=r)throw RangeError(`Data too long`)}for(let e of[De,Oe,ke])a&&s<=Z(o,e)*8&&(t=e);let c=[];for(let t of e){q(t.mode[0],4,c),q(t.numChars,He(t.mode,o),c);for(let e of t.getData())c.push(e)}let l=Z(o,t)*8;q(0,Math.min(4,l-c.length),c),q(0,(8-c.length%8)%8,c);for(let e=236;c.length<l;e^=253)q(e,8,c);let u=Array.from({length:Math.ceil(c.length/8)},()=>0);return c.forEach((e,t)=>u[t>>>3]|=e<<7-(t&7)),new Re(o,t,u,i)}function et(e,t){let{ecc:n=`L`,boostEcc:r=!1,minVersion:i=1,maxVersion:a=40,maskPattern:o=-1,border:s=1}=t||{},c=typeof e==`string`?Ke(e):Array.isArray(e)?[Ue(e)]:void 0;if(!c)throw Error(`uqr only supports encoding string and binary data, but got: ${typeof e}`);let l=$e(c,Ae[n],i,a,o,r),u=tt({version:l.version,maskPattern:l.mask,size:l.size,data:l.modules,types:l.types},s);return t?.invert&&(u.data=u.data.map(e=>e.map(e=>!e))),t?.onEncoded?.(u),u}function tt(e,t=1){if(!t)return e;let{size:n}=e,r=n+t*2;e.size=r,e.data.forEach(e=>{for(let n=0;n<t;n++)e.unshift(!1),e.push(!1)});for(let n=0;n<t;n++)e.data.unshift(Array.from({length:r},e=>!1)),e.data.push(Array.from({length:r},e=>!1));let i=H.Border;e.types.forEach(e=>{for(let n=0;n<t;n++)e.unshift(i),e.push(i)});for(let n=0;n<t;n++)e.types.unshift(Array.from({length:r},e=>i)),e.types.push(Array.from({length:r},e=>i));return e}var nt=e=>{let{data:t,size:n}=et(e,{ecc:`M`,border:4}),r=``;return t.forEach((e,t)=>e.forEach((e,n)=>{e&&(r+=`M${n} ${t}h1v1h-1z`)})),{size:n,path:r}};function rt({value:e,label:t,className:n}){let{size:i,path:a}=(0,Te.useMemo)(()=>nt(e),[e]);return(0,B.jsxs)(`svg`,{"aria-label":t,className:r(`aspect-square rounded-md`,n),role:`img`,shapeRendering:`crispEdges`,viewBox:`0 0 ${i} ${i}`,children:[(0,B.jsx)(`rect`,{fill:`#fff`,height:i,width:i}),(0,B.jsx)(`path`,{d:a,fill:`#000`})]})}var it={apk:`Scan with an Android phone's camera, then open the APK to install it.`,ipa:`Scan to download the .ipa. It installs only on devices its signing profile allows (development or ad hoc); an App Store export reaches testers through TestFlight.`,aab:`Scan to download the .aab. It installs through Google Play or bundletool, not from the file.`,app:`Scan to download the .app.zip on a Mac, then install it on a simulator.`};function at({build:t}){let n=be(t.id,!0),r=n.data?.url;return r===null?(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`This storage gives no download link a phone can open without signing in, so there is no QR code. Download the build here, or open this page on the phone signed in to the console.`}):(0,B.jsxs)(`div`,{className:`flex flex-col items-center gap-2`,children:[r===void 0?n.isError?(0,B.jsxs)(C,{variant:`destructive`,children:[(0,B.jsx)(x,{}),(0,B.jsx)(y,{children:`The download link couldn't be created`}),(0,B.jsx)(S,{children:n.error.message})]}):(0,B.jsx)(e,{className:`size-48`}):(0,B.jsx)(rt,{className:`size-48`,label:`Download ${h(t)}`,value:r}),(0,B.jsx)(`p`,{className:`max-w-56 text-center text-xs text-muted-foreground`,children:it[t.artifact_kind]})]})}function $({build:e}){return(0,B.jsx)(`span`,{className:`font-mono text-foreground`,translate:`no`,children:e.submitted_version??`this build`})}function ot({build:e}){switch(e.artifact_kind){case`apk`:return(0,B.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-2`,children:[(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`On an emulator or a phone over USB, download the APK and install it:`}),(0,B.jsx)(_,{label:`the install command`,value:re(e)})]});case`app`:return(0,B.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-2`,children:[(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`A simulator build runs only in the iOS Simulator. Download the archive, then install it on the booted simulator:`}),(0,B.jsx)(_,{label:`the install command`,value:ie(e)})]});case`aab`:return v(e)?(0,B.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Submitted to Google Play internal testing as`,` `,(0,B.jsx)($,{build:e}),`. Testers install it from Google Play once its release is rolled out; on an app Play Console hasn't published, the release is a draft you roll out in Play Console.`]}):(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`An AAB installs through Google Play or bundletool, not from a download.`});case`ipa`:return v(e)?(0,B.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`On TestFlight as `,(0,B.jsx)($,{build:e}),`: testers install it from TestFlight.`]}):(0,B.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-2`,children:[(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`An IPA installs on registered devices through Xcode or Apple Configurator. For testers, upload it to TestFlight:`}),(0,B.jsx)(_,{label:`the TestFlight command`,value:`npx hot-updater testflight`})]})}}function st({build:e}){let t=h(e);return(0,B.jsxs)(w,{className:`overflow-hidden shadow-sm`,children:[(0,B.jsx)(D,{className:`border-b px-4 py-3`,children:(0,B.jsx)(b,{className:`text-sm`,children:(0,B.jsx)(`h2`,{children:`Install`})})}),(0,B.jsxs)(T,{className:`grid gap-6 p-4 sm:grid-cols-[12rem_minmax(0,1fr)] sm:p-6`,children:[(0,B.jsx)(at,{build:e}),(0,B.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-4`,children:[(0,B.jsx)(ot,{build:e}),(0,B.jsxs)(`a`,{className:n({className:`h-auto min-h-11 w-full min-w-0 py-2 whitespace-normal sm:min-h-8 sm:w-fit`,variant:`outline`}),download:!0,href:d(e.id),children:[(0,B.jsx)(se,{"data-icon":`inline-start`}),(0,B.jsxs)(`span`,{className:`text-left [overflow-wrap:anywhere]`,children:[`Download `,t]})]})]})]})]})}var ct=`https://hot-updater.dev/docs/guides/bundle-diffing#first-ota-update`;function lt({detail:r,page:i,onPage:a}){let o=i.before!==void 0||i.after!==void 0,s=ve(r.build.min_bundle_id,i,o),c=o?s.data:r.patches,{next:d,previous:f}=c??{};return(0,B.jsxs)(w,{className:`overflow-hidden shadow-sm`,id:`patches`,children:[(0,B.jsx)(D,{className:`border-b px-4 py-3`,children:(0,B.jsx)(b,{className:`text-sm`,children:(0,B.jsx)(`h2`,{children:`Patches from this build`})})}),(0,B.jsxs)(T,{className:`p-0`,children:[o&&s.isError?(0,B.jsx)(`div`,{className:`p-4`,children:(0,B.jsxs)(C,{variant:`destructive`,children:[(0,B.jsx)(x,{}),(0,B.jsx)(y,{children:`Patches couldn't be loaded`}),(0,B.jsx)(S,{children:s.error.message}),(0,B.jsx)(he,{children:(0,B.jsxs)(t,{onClick:()=>void s.refetch(),size:`xs`,variant:`outline`,children:[(0,B.jsx)(de,{"data-icon":`inline-start`}),`Retry`]})})]})}):c===void 0?(0,B.jsxs)(`div`,{className:`flex flex-col gap-2 p-4`,children:[(0,B.jsx)(`span`,{className:`sr-only`,children:`Loading patches`}),(0,B.jsx)(e,{className:`h-4 w-full`}),(0,B.jsx)(e,{className:`h-4 w-2/3`})]}):c.data.length===0?o?(0,B.jsxs)(N,{className:`py-10`,children:[(0,B.jsx)(k,{children:(0,B.jsx)(j,{children:`No more patches`})}),(0,B.jsx)(t,{className:`min-h-11 sm:min-h-8`,onClick:()=>a({}),variant:`outline`,children:`Show the newest patches`})]}):(0,B.jsxs)(N,{className:`py-10`,children:[(0,B.jsxs)(k,{children:[(0,B.jsx)(O,{variant:`icon`,children:(0,B.jsx)(ce,{})}),(0,B.jsx)(j,{children:`No patches from this build`}),(0,B.jsxs)(M,{children:[`A deploy adds a patch from this build's bundle while it is its scope's newest build and the deploy config turns patches on, with `,(0,B.jsx)(`code`,{className:`font-mono`,children:`patch`}),` in`,` `,(0,B.jsx)(`code`,{className:`font-mono`,children:`hot-updater.config.ts`}),`.`]})]}),(0,B.jsx)(A,{children:(0,B.jsxs)(`a`,{className:n({className:`min-h-11 sm:min-h-8`,variant:`outline`}),href:ct,rel:`noreferrer`,target:`_blank`,children:[`Bundle diffing guide`,(0,B.jsx)(u,{"data-icon":`inline-end`})]})})]}):(0,B.jsxs)(z,{"aria-busy":o&&s.isPlaceholderData,"aria-label":`Patches from this build`,className:`table-fixed`,children:[(0,B.jsx)(P,{children:(0,B.jsxs)(L,{children:[(0,B.jsx)(F,{children:`Target bundle`}),(0,B.jsx)(F,{className:`w-28`,children:`Patch size`}),(0,B.jsx)(F,{className:`hidden w-32 sm:table-cell`,children:`Created`})]})}),(0,B.jsx)(I,{children:c.data.map(e=>(0,B.jsxs)(L,{children:[(0,B.jsx)(R,{className:`py-3 whitespace-normal`,children:(0,B.jsx)(l,{className:`block font-mono text-xs [overflow-wrap:anywhere] underline-offset-4 hover:underline`,search:{bundleId:e.bundleId},title:e.bundleId,to:`/`,translate:`no`,children:e.bundleId})}),(0,B.jsx)(R,{className:`text-xs tabular-nums`,children:m(e.byteSize)}),(0,B.jsx)(R,{className:`hidden sm:table-cell`,children:(0,B.jsx)(p,{uuid:e.bundleId})})]},e.bundleId))})]}),d!==void 0||f!==void 0?(0,B.jsxs)(`nav`,{"aria-label":`Patch pages`,className:`flex items-center justify-end gap-2 border-t px-4 py-2`,children:[(0,B.jsxs)(t,{className:`min-h-11 sm:min-h-7`,disabled:f===void 0||o&&s.isPlaceholderData,onClick:()=>a({after:f}),size:`sm`,variant:`ghost`,children:[(0,B.jsx)(ee,{"data-icon":`inline-start`}),`Newer`]}),(0,B.jsxs)(t,{className:`min-h-11 sm:min-h-7`,disabled:d===void 0||o&&s.isPlaceholderData,onClick:()=>a({before:d}),size:`sm`,variant:`ghost`,children:[`Older`,(0,B.jsx)(ae,{"data-icon":`inline-end`})]})]}):null]})]})}var ut=(e,t)=>{let n=e.data.find(e=>e.bundleId===t);if(n!==void 0)return{kind:`patch`,byteSize:n.byteSize};let r=e.data.at(-1)?.bundleId;return e.next!==void 0&&r!==void 0&&t<r?{kind:`unknown`}:{kind:`full`}};function dt({download:e}){switch(e.kind){case`patch`:return(0,B.jsxs)(`span`,{className:`text-xs`,children:[`Patch`,` `,(0,B.jsxs)(`span`,{className:`text-muted-foreground tabular-nums`,children:[`(`,m(e.byteSize),`)`]})]});case`full`:return(0,B.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Full bundle`});case`unknown`:return(0,B.jsx)(`a`,{className:`text-xs underline-offset-4 hover:underline`,href:`#patches`,children:`See patches`})}}function ft({detail:e}){let{servedNow:t,patches:r,catalogScopeKey:i}=e,a=(0,B.jsxs)(l,{className:`inline-flex items-center gap-0.5 underline-offset-4 hover:underline`,search:{scopeKey:i},to:`/`,children:[`All releases in this scope`,(0,B.jsx)(u,{"aria-hidden":`true`,className:`size-3`})]});return(0,B.jsxs)(w,{className:`overflow-hidden shadow-sm`,children:[(0,B.jsx)(D,{className:`border-b px-4 py-3`,children:(0,B.jsx)(b,{className:`text-sm`,children:(0,B.jsx)(`h2`,{children:`Served now`})})}),(0,B.jsx)(T,{className:`p-0`,children:t.length===0?(0,B.jsxs)(N,{className:`py-10`,children:[(0,B.jsxs)(k,{children:[(0,B.jsx)(O,{variant:`icon`,children:(0,B.jsx)(Se,{})}),(0,B.jsx)(j,{children:`No OTA for this build yet`}),(0,B.jsxs)(M,{children:[`No release in this build's scope is newer than its built-in bundle. Deploy one with`,` `,(0,B.jsx)(`code`,{className:`font-mono`,children:`hot-updater deploy`}),`, and it shows here.`]})]}),(0,B.jsx)(A,{children:(0,B.jsx)(l,{className:n({className:`min-h-11 sm:min-h-8`,variant:`outline`}),search:{scopeKey:i},to:`/`,children:`All releases in this scope`})})]}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(z,{"aria-label":`Served now`,className:`table-fixed`,children:[(0,B.jsx)(P,{children:(0,B.jsxs)(L,{children:[(0,B.jsx)(F,{children:`Bundle`}),(0,B.jsx)(F,{className:`hidden w-40 md:table-cell`,children:`Rollout`}),(0,B.jsx)(F,{className:`hidden w-32 sm:table-cell`,children:`Created`}),(0,B.jsx)(F,{className:`w-32`,children:`First OTA download`})]})}),(0,B.jsx)(I,{children:t.map(e=>{let t=e.bundleId,n=e.rolloutCohortCount/ge*100;return(0,B.jsxs)(L,{children:[(0,B.jsx)(R,{className:`py-3 whitespace-normal`,children:(0,B.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1`,children:[(0,B.jsx)(l,{className:`font-mono text-xs [overflow-wrap:anywhere] underline-offset-4 hover:underline`,search:{releaseId:e.releaseId},title:t,to:`/`,translate:`no`,children:t}),e.message?(0,B.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:e.message}):null]})}),(0,B.jsx)(R,{className:`hidden md:table-cell`,children:(0,B.jsxs)(`div`,{className:`flex flex-wrap gap-1`,children:[e.targetCohorts.length>0?(0,B.jsx)(E,{variant:`secondary`,children:e.targetCohorts.length===1?`1 cohort`:`${e.targetCohorts.length} cohorts`}):(0,B.jsx)(xe,{percentage:n}),e.shouldForceUpdate?(0,B.jsx)(E,{variant:`outline`,children:`Forced`}):null]})}),(0,B.jsx)(R,{className:`hidden sm:table-cell`,children:(0,B.jsx)(p,{uuid:t})}),(0,B.jsx)(R,{children:(0,B.jsx)(dt,{download:ut(r,t)})})]},e.releaseId)})})]}),(0,B.jsxs)(`p`,{className:`border-t px-4 py-3 text-xs text-muted-foreground`,children:[`What the update check serves an install of this build now, newest first: not the history. `,a]})]})})]})}function pt({buildId:r,search:i,onSearchChange:a}){let o=ye(r),c=o.data,u={...i.patchesBefore===void 0?{}:{before:i.patchesBefore},...i.patchesAfter===void 0?{}:{after:i.patchesAfter}};return(0,B.jsxs)(`div`,{className:`flex h-svh min-h-0 flex-col`,children:[(0,B.jsxs)(`header`,{className:`sticky top-0 z-10 flex shrink-0 items-center gap-x-2 border-b bg-background px-3 py-3 sm:min-h-12 sm:bg-card/70 sm:px-4 sm:backdrop-blur-sm`,children:[(0,B.jsx)(s,{className:`-ml-1 size-11 lg:size-7`}),(0,B.jsxs)(l,{className:n({className:`min-h-11 sm:min-h-7`,size:`sm`,variant:`ghost`}),to:`/native-builds`,children:[(0,B.jsx)(ee,{"data-icon":`inline-start`}),`Native builds`]}),c?(0,B.jsxs)(`h1`,{className:`flex min-w-0 items-center gap-1.5 text-sm font-medium`,children:[(0,B.jsx)(_e,{className:`size-3.5 shrink-0 text-muted-foreground`,platform:c.build.platform}),(0,B.jsxs)(`span`,{className:`min-w-0 [overflow-wrap:anywhere]`,children:[f(c.build.platform),` `,te[c.build.artifact_kind].label,` ·`,` `,(0,B.jsx)(`span`,{translate:`no`,children:c.channel})]}),(0,B.jsx)(`span`,{className:`hidden text-xs font-normal text-muted-foreground tabular-nums sm:inline`,children:m(c.build.byte_size)})]}):(0,B.jsx)(`h1`,{className:`sr-only`,children:`Native build`})]}),(0,B.jsx)(`div`,{className:`min-h-0 min-w-0 flex-1 overflow-y-auto bg-muted/5 p-3 sm:p-6`,children:(0,B.jsx)(`div`,{className:`mx-auto flex w-full max-w-5xl flex-col gap-4 sm:gap-6`,children:o.isError?(0,B.jsxs)(C,{variant:`destructive`,children:[(0,B.jsx)(x,{}),(0,B.jsx)(y,{children:`The native build couldn't be loaded`}),(0,B.jsx)(S,{children:o.error.message}),(0,B.jsx)(he,{children:(0,B.jsxs)(t,{onClick:()=>void o.refetch(),size:`xs`,variant:`outline`,children:[(0,B.jsx)(de,{"data-icon":`inline-start`}),`Retry`]})})]}):c===void 0?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`span`,{className:`sr-only`,children:`Loading the native build`}),(0,B.jsx)(e,{className:`h-56 w-full rounded-xl`}),(0,B.jsx)(e,{className:`h-64 w-full rounded-xl`})]}):c===null?(0,B.jsxs)(N,{className:`border py-16`,children:[(0,B.jsxs)(k,{children:[(0,B.jsx)(O,{variant:`icon`,children:(0,B.jsx)(ue,{})}),(0,B.jsx)(j,{children:`Native build not found`}),(0,B.jsxs)(M,{children:[`No native build has this ID. It may have been deleted with`,` `,(0,B.jsx)(`code`,{className:`font-mono`,children:`native-build delete`}),`, or be from another console.`]})]}),(0,B.jsx)(A,{children:(0,B.jsx)(l,{className:n({className:`min-h-11 sm:min-h-8`,variant:`outline`}),to:`/native-builds`,children:`Show all native builds`})})]}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(st,{build:c.build}),(0,B.jsx)(we,{detail:c}),(0,B.jsx)(ft,{detail:c}),(0,B.jsx)(lt,{detail:c,onPage:e=>a({...e.before===void 0?{}:{patchesBefore:e.before},...e.after===void 0?{}:{patchesAfter:e.after}}),page:u})]})})})]})}function mt(){let{buildId:e}=g.useParams(),t=g.useSearch(),n=g.useNavigate();return(0,B.jsx)(pt,{buildId:e,onSearchChange:e=>void n({search:e,replace:!0}),search:t})}export{mt as component};
|