From 15635531c66d88752d4d48b179580e206ccfe08c Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Fri, 30 Oct 2026 03:50:14 +0100 Subject: [PATCH] fix(app): keep tablet orientation policy in activity Android resolves manifest resources without screen size qualifiers, so preserve the portrait declaration and unlock tablets when the activity starts. --- packages/app/app.config.test.ts | 25 ++------------ .../app/plugins/with-android-orientation.js | 33 ++----------------- 2 files changed, 4 insertions(+), 54 deletions(-) diff --git a/packages/app/app.config.test.ts b/packages/app/app.config.test.ts index 43e0fa2dcb..f828393631 100644 --- a/packages/app/app.config.test.ts +++ b/packages/app/app.config.test.ts @@ -60,35 +60,14 @@ describe("Android app config", () => { ); }); -it("allows Android tablets to rotate without a portrait manifest lock", async () => { +it("keeps the Android manifest portrait for phone startup", async () => { const manifest = await resolveAndroidManifest(); const activity = manifest.application[0].activity.find( (entry: ManifestEntry) => entry.$["android:name"] === ".MainActivity", ); - expect(activity.$["android:screenOrientation"]).toBe("@integer/paseo_orientation"); + expect(activity.$["android:screenOrientation"]).toBe("portrait"); }, 30_000); -it("generates portrait phone and unrestricted tablet orientation resources", async () => { - const { mkdtemp, readFile, rm } = await import("node:fs/promises"); - const { tmpdir } = await import("node:os"); - const { join } = await import("node:path"); - const root = await mkdtemp(join(tmpdir(), "paseo-orientation-")); - try { - const plugin = createRequire(import.meta.url)("./plugins/with-android-orientation.js"); - const config = plugin({ name: "test", slug: "test" }); - await config.mods.android.dangerous({ - modRequest: { platformProjectRoot: root }, - modResults: {}, - }); - const resource = (directory: string) => - readFile(join(root, "app/src/main/res", directory, "paseo_orientation.xml"), "utf8"); - expect(await resource("values")).toContain('name="paseo_orientation">1'); - expect(await resource("values-sw600dp")).toContain('name="paseo_orientation">-1'); - } finally { - await rm(root, { recursive: true, force: true }); - } -}); - it("updates the native orientation before launch and when screen size changes", async () => { const plugin = createRequire(import.meta.url)("./plugins/with-android-orientation.js"); const config = plugin({ name: "test", slug: "test" }); diff --git a/packages/app/plugins/with-android-orientation.js b/packages/app/plugins/with-android-orientation.js index 44aa0bf29e..223257d38f 100644 --- a/packages/app/plugins/with-android-orientation.js +++ b/packages/app/plugins/with-android-orientation.js @@ -1,17 +1,7 @@ -const { withAndroidManifest, withMainActivity, withDangerousMod } = require("expo/config-plugins"); -const fs = require("node:fs"); -const path = require("node:path"); +const { withMainActivity } = require("expo/config-plugins"); module.exports = function withAndroidOrientation(config) { - // The manifest locks phones before the first activity frame. Tablets start unlocked. - config = withAndroidManifest(config, (mod) => { - const activity = mod.modResults.manifest.application[0].activity.find( - (item) => item.$["android:name"] === ".MainActivity", - ); - activity.$["android:screenOrientation"] = "@integer/paseo_orientation"; - return mod; - }); - config = withMainActivity(config, (mod) => { + return withMainActivity(config, (mod) => { const activity = mod.modResults; if (activity.language !== "kt") throw new Error("Expected Kotlin MainActivity"); const marker = " // Paseo orientation policy"; @@ -45,23 +35,4 @@ ${anchor}`, } return mod; }); - return withDangerousMod(config, [ - "android", - async (mod) => { - const res = path.join(mod.modRequest.platformProjectRoot, "app/src/main/res"); - // ActivityInfo uses 1 for portrait and -1 for unspecified. - for (const [dir, value] of [ - ["values", "1"], - ["values-sw600dp", "-1"], - ]) { - const target = path.join(res, dir); - fs.mkdirSync(target, { recursive: true }); - fs.writeFileSync( - path.join(target, "paseo_orientation.xml"), - `${value}\n`, - ); - } - return mod; - }, - ]); };