Merge pull request #5008 from RSSNext/release/mobile/0.5.3

release(mobile): Release v0.5.3
This commit is contained in:
DIYgod 2026-05-13 12:07:09 +08:00 committed by GitHub
commit 77ad41bc1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 139 additions and 7 deletions

View File

@ -0,0 +1,11 @@
# What's New in v0.5.3
## Shiny new things
## Improvements
## No longer broken
## Thanks
Special thanks to volunteer contributors @ for their valuable contributions

View File

@ -33,7 +33,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>0.5.2</string>
<string>0.5.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@ -54,7 +54,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>5</string>
<string>6</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationCategoryType</key>

View File

@ -1,6 +1,6 @@
{
"name": "@follow/mobile",
"version": "0.5.2",
"version": "0.5.3",
"private": true,
"main": "src/main.tsx",
"scripts": {

View File

@ -1,5 +1,5 @@
{
"version": "0.5.2",
"version": "0.5.3",
"mode": "ota",
"runtimeVersion": "0.5.0",
"channel": "production"

View File

@ -85,6 +85,41 @@ describe("buildManifest", () => {
expect(first.id).toBe(second.id)
})
it("includes the embedded Expo config needed by expo-constants after an OTA launch", () => {
const manifest = buildManifest(createRelease(), {
origin: "https://ota.folo.is",
platform: "ios",
})
expect(manifest.extra).toMatchObject({
expoClient: {
name: "Folo",
slug: "follow",
owner: "follow",
scheme: ["follow", "folo"],
version: "0.4.2",
runtimeVersion: "0.4.1",
updates: {
url: "https://ota.folo.is/manifest",
requestHeaders: {
"expo-channel-name": "production",
},
},
ios: {
bundleIdentifier: "is.follow",
},
android: {
package: "is.follow",
},
extra: {
eas: {
projectId: "a6335b14-fb84-45aa-ba80-6f6ab8926920",
},
},
},
})
})
})
describe("/manifest", () => {

View File

@ -5,6 +5,43 @@ import type { OtaPlatform, OtaPlatformPayload, OtaProjectedPlatforms, OtaRelease
type PlatformPayload = OtaPlatformPayload
type PlatformAsset = PlatformPayload["launchAsset"] | PlatformPayload["assets"][number]
type MobileExpoClientConfig = {
name: string
slug: string
owner: string
version: string
runtimeVersion: string
orientation: "portrait"
scheme: string[]
userInterfaceStyle: "automatic"
updates: {
url: string
requestHeaders: {
"expo-channel-name": string
}
codeSigningMetadata: {
keyid: string
alg: string
}
checkAutomatically: "NEVER"
}
ios: {
bundleIdentifier: string
supportsTablet: boolean
usesAppleSignIn: boolean
}
android: {
package: string
}
extra: {
eas: {
projectId: string
}
}
}
const MOBILE_UPDATE_URL = "https://ota.folo.is/manifest"
const MOBILE_EAS_PROJECT_ID = "a6335b14-fb84-45aa-ba80-6f6ab8926920"
export interface ManifestAsset {
key: string
@ -26,6 +63,7 @@ export interface OtaManifest {
}
extra: {
product: OtaRelease["product"]
expoClient?: MobileExpoClientConfig
}
}
@ -62,9 +100,7 @@ export function buildManifest(
channel: release.channel,
releaseVersion: release.releaseVersion,
},
extra: {
product: release.product,
},
extra: buildManifestExtra(release),
}
}
@ -142,6 +178,56 @@ function toExpoAssetIdentity(path: string, contentType: string) {
}
}
function buildManifestExtra(release: OtaRelease): OtaManifest["extra"] {
const extra: OtaManifest["extra"] = {
product: release.product,
}
if (release.product === "mobile") {
// Expo Updates hydrates Constants.expoConfig from extra.expoClient after an OTA launch.
extra.expoClient = buildMobileExpoClientConfig(release)
}
return extra
}
function buildMobileExpoClientConfig(release: Extract<OtaRelease, { product: "mobile" }>) {
return {
name: "Folo",
slug: "follow",
owner: "follow",
version: release.releaseVersion,
runtimeVersion: release.runtimeVersion,
orientation: "portrait",
scheme: ["follow", "folo"],
userInterfaceStyle: "automatic",
updates: {
url: MOBILE_UPDATE_URL,
requestHeaders: {
"expo-channel-name": release.channel,
},
codeSigningMetadata: {
keyid: "main",
alg: "rsa-v1_5-sha256",
},
checkAutomatically: "NEVER",
},
ios: {
bundleIdentifier: "is.follow",
supportsTablet: true,
usesAppleSignIn: true,
},
android: {
package: "is.follow",
},
extra: {
eas: {
projectId: MOBILE_EAS_PROJECT_ID,
},
},
} satisfies MobileExpoClientConfig
}
function inferExtensionFromContentType(contentType: string) {
switch (contentType) {
case "application/javascript": {