diff --git a/apps/mobile/changelog/0.5.3.md b/apps/mobile/changelog/0.5.3.md new file mode 100644 index 000000000..c8e24f30d --- /dev/null +++ b/apps/mobile/changelog/0.5.3.md @@ -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 diff --git a/apps/mobile/ios/Folo/Info.plist b/apps/mobile/ios/Folo/Info.plist index f2d0c36e9..9c849eaa5 100644 --- a/apps/mobile/ios/Folo/Info.plist +++ b/apps/mobile/ios/Folo/Info.plist @@ -33,7 +33,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 0.5.2 + 0.5.3 CFBundleSignature ???? CFBundleURLTypes @@ -54,7 +54,7 @@ CFBundleVersion - 5 + 6 ITSAppUsesNonExemptEncryption LSApplicationCategoryType diff --git a/apps/mobile/package.json b/apps/mobile/package.json index d3a3aac83..d439ab9e3 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@follow/mobile", - "version": "0.5.2", + "version": "0.5.3", "private": true, "main": "src/main.tsx", "scripts": { diff --git a/apps/mobile/release.json b/apps/mobile/release.json index 2e6f3e8e2..60ae1b255 100644 --- a/apps/mobile/release.json +++ b/apps/mobile/release.json @@ -1,5 +1,5 @@ { - "version": "0.5.2", + "version": "0.5.3", "mode": "ota", "runtimeVersion": "0.5.0", "channel": "production" diff --git a/apps/ota/src/__tests__/manifest.test.ts b/apps/ota/src/__tests__/manifest.test.ts index 2653162f3..e6307c958 100644 --- a/apps/ota/src/__tests__/manifest.test.ts +++ b/apps/ota/src/__tests__/manifest.test.ts @@ -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", () => { diff --git a/apps/ota/src/lib/manifest.ts b/apps/ota/src/lib/manifest.ts index 866201017..1b47972d7 100644 --- a/apps/ota/src/lib/manifest.ts +++ b/apps/ota/src/lib/manifest.ts @@ -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) { + 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": {