From 4d588cb904b941c738f311c61c9c8f2801b157c7 Mon Sep 17 00:00:00 2001 From: Callan Barrett Date: Thu, 22 Oct 2026 15:18:59 +0800 Subject: [PATCH] Prepare v2.0.1 store release with iPad support Build 31 (v2.0.0) targets iPhone only. Add iPad to the iOS device family with all four iPad orientations, and bump package, lockfile, Android and iOS to 2.0.1 build 32 since v2.0.0's release workflow has already run. Map native:2.0.1+32 and live:2.0.1-ota.1 to the existing 2.0.0 announcement, and guard iPad support in the release config tests. Keep the focused ZapScript text field above the toolbar below it so its focus outline is not cut off. --- android/app/build.gradle | 4 +-- docs/deployment.md | 2 +- ios/App/App.xcodeproj/project.pbxproj | 12 ++++---- ios/App/App/Info.plist | 7 +++++ package-lock.json | 4 +-- package.json | 2 +- src/__tests__/unit/lib/whatsNew.test.ts | 9 ++++++ .../validation/release-config.test.ts | 30 ++++++++++++++++++- src/lib/whatsNew.ts | 11 +++++-- src/styles/components.css | 5 ++++ 10 files changed, 71 insertions(+), 15 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index e6e74dd5..8ba8758e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "dev.wizzo.tapto" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 31 - versionName "2.0.0" + versionCode 32 + versionName "2.0.1" resValue "string", "capawesome_live_update_default_channel", "production-" + defaultConfig.versionCode testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { diff --git a/docs/deployment.md b/docs/deployment.md index 65b5c48b..d476a3ec 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -60,7 +60,7 @@ The About screen derives its visible OTA version from the announcement mapped to For later OTAs on the same native build, increment the OTA sequence (`ota.2`, `ota.3`, and so on), add the matching announcement mapping, and update the release validation guard. Do not reuse a release key for different bundle contents. -The displayed version can be any bump, not just a patch. 1.15.0 shipped as a live update on the 1.14.1 build 30 binary: channel `production-30`, release key `live:1.14.1-ota.2`. 2.0.0 ships the same way as the third live update on that binary: channel `production-30`, release key `live:1.14.1-ota.3`. `live:1.14.1-ota.1` stays mapped to the 1.14.1 announcement and `live:1.14.1-ota.2` to 1.15.0. The 2.0.0 store release (native `2.0.0+31`, channel `production-31`, release key `live:2.0.0-ota.1`) reuses the 2.0.0 announcement so people who already received 2.0.0 over the air do not see it again. The next store release must use a version above 2.0.0. +The displayed version can be any bump, not just a patch. 1.15.0 shipped as a live update on the 1.14.1 build 30 binary: channel `production-30`, release key `live:1.14.1-ota.2`. 2.0.0 ships the same way as the third live update on that binary: channel `production-30`, release key `live:1.14.1-ota.3`. `live:1.14.1-ota.1` stays mapped to the 1.14.1 announcement and `live:1.14.1-ota.2` to 1.15.0. The 2.0.0 store release (native `2.0.0+31`, channel `production-31`, release key `live:2.0.0-ota.1`) reuses the 2.0.0 announcement so people who already received 2.0.0 over the air do not see it again. 2.0.1 (native `2.0.1+32`, channel `production-32`, release key `live:2.0.1-ota.1`) adds iPad support to the iOS target and reuses the same announcement. The next store release must use a version above 2.0.1. ### Pushing a Live Update diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 6e078d9a..84079041 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -388,7 +388,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = App/App.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 31; + CURRENT_PROJECT_VERSION = 32; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_USER_SCRIPT_SANDBOXING = NO; INFOPLIST_FILE = App/Info.plist; @@ -399,7 +399,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.0; + MARKETING_VERSION = 2.0.1; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = dev.wizzo.tapto; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -408,7 +408,7 @@ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -419,7 +419,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = App/App.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 31; + CURRENT_PROJECT_VERSION = 32; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_USER_SCRIPT_SANDBOXING = NO; INFOPLIST_FILE = App/Info.plist; @@ -430,7 +430,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.0; + MARKETING_VERSION = 2.0.1; PRODUCT_BUNDLE_IDENTIFIER = dev.wizzo.tapto; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -438,7 +438,7 @@ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist index f17fbdd6..b26cf44b 100644 --- a/ios/App/App/Info.plist +++ b/ios/App/App/Info.plist @@ -78,6 +78,13 @@ UIInterfaceOrientationPortrait + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIViewControllerBasedStatusBarAppearance diff --git a/package-lock.json b/package-lock.json index bd79f869..1ace89a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "zaparoo-app", - "version": "2.0.0", + "version": "2.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "zaparoo-app", - "version": "2.0.0", + "version": "2.0.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 7a82c1c1..8c5d3d67 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "zaparoo-app", "private": true, "license": "Apache-2.0", - "version": "2.0.0", + "version": "2.0.1", "type": "module", "packageManager": "npm@12.0.1", "engines": { diff --git a/src/__tests__/unit/lib/whatsNew.test.ts b/src/__tests__/unit/lib/whatsNew.test.ts index 83ed2af2..e4ef04ec 100644 --- a/src/__tests__/unit/lib/whatsNew.test.ts +++ b/src/__tests__/unit/lib/whatsNew.test.ts @@ -136,6 +136,15 @@ describe("whatsNew", () => { ); }); + it("should map the 2.0.1 store build and its first live update to 2.0.0", () => { + expect(getWhatsNewAnnouncement("native:2.0.1+32")?.id).toBe( + "release-2.0.0", + ); + expect(getWhatsNewAnnouncement("live:2.0.1-ota.1")?.id).toBe( + "release-2.0.0", + ); + }); + it("should show the third 1.14.1 live update as 2.0.0", () => { const announcement = getWhatsNewAnnouncement("live:1.14.1-ota.3"); diff --git a/src/__tests__/validation/release-config.test.ts b/src/__tests__/validation/release-config.test.ts index a7136402..c33f81cb 100644 --- a/src/__tests__/validation/release-config.test.ts +++ b/src/__tests__/validation/release-config.test.ts @@ -54,7 +54,7 @@ describe("release configuration", () => { new Set([packageJson.version]), ); expect(new Set(iosBuildNumbers)).toEqual(new Set([androidVersionCode])); - expect(androidVersionCode).toBe(31); + expect(androidVersionCode).toBe(32); }); it("should use versioned Capawesome live update channels", () => { @@ -89,6 +89,34 @@ describe("release configuration", () => { expect(mainActivity).not.toContain('android:launchMode="singleTask"'); }); + it("should target iPhone and iPad with every iPad orientation", () => { + const xcodeProject = readProjectFile( + "ios/App/App.xcodeproj/project.pbxproj", + ); + const iosInfoPlist = readProjectFile("ios/App/App/Info.plist"); + const deviceFamilies = [ + ...xcodeProject.matchAll(/TARGETED_DEVICE_FAMILY = ([^;]+);/g), + ].map((match) => match[1]); + const ipadOrientations = requireMatch( + iosInfoPlist, + /UISupportedInterfaceOrientations~ipad<\/key>\s*([\s\S]*?)<\/array>/, + "iPad orientations", + ); + + expect(deviceFamilies.length).toBeGreaterThan(0); + expect(new Set(deviceFamilies)).toEqual(new Set(['"1,2"'])); + for (const orientation of [ + "Portrait", + "PortraitUpsideDown", + "LandscapeLeft", + "LandscapeRight", + ]) { + expect(ipadOrientations).toContain( + `UIInterfaceOrientation${orientation}`, + ); + } + }); + it("should enable the iOS In-App Purchase capability", () => { const xcodeProject = readProjectFile( "ios/App/App.xcodeproj/project.pbxproj", diff --git a/src/lib/whatsNew.ts b/src/lib/whatsNew.ts index e1b8eb59..a29f3cec 100644 --- a/src/lib/whatsNew.ts +++ b/src/lib/whatsNew.ts @@ -21,10 +21,17 @@ export type WhatsNewAnnouncement = { export const WHATS_NEW_ANNOUNCEMENTS: WhatsNewAnnouncement[] = [ { - // Live update on the 1.14.1 build 30 binary, then native 2.0.0 build 31. + // Live update on the 1.14.1 build 30 binary, then the 2.0.0 build 31 and + // 2.0.1 build 32 native releases (2.0.1 only adds iPad support). id: "release-2.0.0", version: "2.0.0", - releaseKeys: ["native:2.0.0+31", "live:2.0.0-ota.1", "live:1.14.1-ota.3"], + releaseKeys: [ + "native:2.0.0+31", + "live:2.0.0-ota.1", + "native:2.0.1+32", + "live:2.0.1-ota.1", + "live:1.14.1-ota.3", + ], title: "What's new in v2.0.0", items: [ "The whole App has been redesigned with the Zaparoo Online look, plus a light theme that follows your phone (Settings > Accessibility > Appearance).", diff --git a/src/styles/components.css b/src/styles/components.css index add9ee1d..689fb45a 100644 --- a/src/styles/components.css +++ b/src/styles/components.css @@ -486,6 +486,11 @@ .wui-editor > textarea { border-radius: 4px 4px 0 0; } + /* The toolbar below paints over the offset outline unless the field is lifted. */ + .wui-editor > textarea:focus-visible { + position: relative; + z-index: 1; + } .wui-field-label { margin-bottom: 0.5rem; }