chore: sync upstream PR #8527 - fix(ios): adopt UIScene life cycle in default iOS app templates#84
chore: sync upstream PR #8527 - fix(ios): adopt UIScene life cycle in default iOS app templates#84riderx wants to merge 24 commits into
Conversation
Co-authored-by: jcesarmobile <jcesarmobile@gmail.com>
Co-authored-by: Joey Pender <joey.pender@outsystems.com> Co-authored-by: Pedro Bilro <pedro.gustavo.bilro@outsystems.com> Co-authored-by: Mark Anderson <mark.anderson@outsystems.com>
…#8476) Co-authored-by: jcesarmobile <jcesarmobile@gmail.com>
…am#8492) Co-authored-by: Mark Anderson <mark.anderson@outsystems.com>
Apple's TN3187 states that starting with the next major iOS release following iOS 26, apps built with the latest SDK will fail to launch if they don't adopt the UIScene-based life cycle. Both default iOS templates (ios-spm-template and ios-pods-template) still use the pre-scene AppDelegate-only life cycle, so any app scaffolded today via `npx cap add ios` will fail to launch on that SDK with no crash log (UIKit logs: "UIScene life cycle is required for apps built with this SDK") -- the app process starts, immediately shows a black screen, and returns to the Home Screen. This adds the minimal, Apple-documented fix to both templates: - SceneDelegate.swift implementing UIWindowSceneDelegate - AppDelegate: configurationForConnecting / didDiscardSceneSessions - Info.plist: UIApplicationSceneManifest, matching Apple's current official example verbatim (same keys/config name/delegate class) - project.pbxproj: register SceneDelegate.swift in the App target Since the app's root view controller (CAPBridgeViewController) loads from Main.storyboard, the system auto-configures the scene window from UISceneStoryboardFile, so no manual window setup is needed in SceneDelegate. Verified end-to-end on a real device (rebuilt, installed, and launched an app using this exact template layout) -- confirmed this resolves a silent launch failure with zero crash log. Ref: https://developer.apple.com/documentation/technotes/tn3187-migrating-to-the-uikit-scene-based-life-cycle Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…rred fallback)
|
Claude Code could not resolve this upstream sync completely. Please review the branch carefully before merging. |
Beta npm buildMaintainers can publish one Capacitor Plus workspace package from this PR to npm for fast testing. Comment Examples: /publish-beta core
/publish-beta cli
/publish-beta @capacitor-plus/coreIf exactly one workspace package changed, Packages:
The workflow will:
Security note: beta publish is only enabled for branches inside this repository. |
📝 WalkthroughWalkthroughThe release updates package metadata and changelogs for version 8.4.1, extends CLI Swift Package Manager and telemetry handling, changes Android SystemBars configuration and plugin APIs, adds iOS scene lifecycle templates, and increases several CI job timeouts. ChangesCapacitor 8.4.1 platform and tooling updates
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant CapacitorConfig
participant generatePackageText
participant PackageSwift
participant updateIOS
CapacitorConfig->>generatePackageText: packageOptions
generatePackageText->>PackageSwift: generate symlink and moduleAliases entries
updateIOS->>PackageSwift: rewrite incompatible version constraint
sequenceDiagram
participant InfoPlist
participant AppDelegate
participant SceneDelegate
participant MainStoryboard
InfoPlist->>AppDelegate: provide Default Configuration
AppDelegate->>SceneDelegate: connect UIWindowScene
SceneDelegate->>MainStoryboard: use Main storyboard
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cli/src/tasks/run.ts (1)
96-101: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRollback the Android manifest in the error path. The
catchonly reverts the live-reload Cap config; it leaves the Android manifest edited bywriteCordovaAndroidManifest(..., true)ifrun()fails after that point. HoistcordovaPluginsso thecatchcan call the matchingfalsewrite too.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cli/src/tasks/run.ts` around lines 96 - 101, Hoist the cordovaPlugins variable outside the try block so it is available to error handling. In run(), update the catch path to call writeCordovaAndroidManifest(cordovaPlugins, config, platformName, false) for Android after live-reload setup, alongside reverting the Cap config, ensuring both edits are rolled back when execution fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java`:
- Around line 210-211: Extract the duplicated safe-area calculation and
injection sequence into a helper such as
injectSafeAreaCSSFromInsets(WindowInsetsCompat insets) in SystemBars, then
replace both repeated branches with calls to that helper while preserving the
existing inset values and behavior.
- Around line 99-108: Normalize the value read in the SystemBars configuration
logic before comparison, using the same Locale.US-based case normalization
applied to style. Update the configuredInsetsHandling handling so case variants
such as “Disable” and “DISABLE” match INSETS_HANDLING_DISABLE, while preserving
the existing fallback warning and CSS default for unsupported values.
In `@android/capacitor/src/test/java/com/getcapacitor/plugin/SystemBarsTest.java`:
- Around line 22-72: Extend SystemBarsTest coverage to exercise the hide=true
branch in setHidden. Update invokeSetHidden to accept a boolean hide argument,
adjust existing show tests to pass false, and add corresponding tests for empty,
status, and navigation bar values that verify the appropriate controller.hide
call and ensure other bar types are not invoked.
In `@android/CHANGELOG.md`:
- Around line 10-20: Change the 8.4.0 release heading in the changelog from an
h1 to an h2 by using two leading hash characters, keeping the Bug Fixes and
Features subsections unchanged.
In `@CHANGELOG.md`:
- Around line 6-52: Regenerate CHANGELOG.md through the release tooling so the
8.4.1 through 8.3.2 release headers and associated links consistently reference
the Cap-go/capacitor-plus repository instead of mixing in ionic-team/capacitor
URLs.
In `@cli/CHANGELOG.md`:
- Around line 13-22: Change the 8.4.0 release heading in the changelog from an
h1 to an h2 so its “Bug Fixes” and “Features” h3 subsections follow the same
heading hierarchy as other release sections.
In `@cli/src/ios/update.ts`:
- Around line 62-85: Move the single await getCapacitorPackageVersion(config,
config.ios.name) call outside the validSPMPackages.map callback, storing its
result before Promise.all; reuse that iosPlatformVersion for every plugin while
preserving the existing version comparison and update logic.
In `@ios-spm-template/App/App/Info.plist`:
- Around line 27-45: Add an explicit UISceneClassName entry with UIWindowScene
to the application scene configuration alongside UISceneDelegateClassName in
UIApplicationSceneManifest, preserving the existing single-window configuration.
---
Outside diff comments:
In `@cli/src/tasks/run.ts`:
- Around line 96-101: Hoist the cordovaPlugins variable outside the try block so
it is available to error handling. In run(), update the catch path to call
writeCordovaAndroidManifest(cordovaPlugins, config, platformName, false) for
Android after live-reload setup, alongside reverting the Cap config, ensuring
both edits are rolled back when execution fails.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e683360b-e22c-45ad-9fe8-385dc66013db
📒 Files selected for processing (37)
.github/workflows/test.ymlCHANGELOG.mdandroid/CHANGELOG.mdandroid/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.javaandroid/capacitor/src/main/java/com/getcapacitor/FileUtils.javaandroid/capacitor/src/main/java/com/getcapacitor/PluginConfig.javaandroid/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.javaandroid/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.javaandroid/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookieManager.javaandroid/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.javaandroid/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.javaandroid/capacitor/src/main/java/com/getcapacitor/util/JSONUtils.javaandroid/capacitor/src/test/java/com/getcapacitor/plugin/SystemBarsTest.javaandroid/package.jsoncli/CHANGELOG.mdcli/package.jsoncli/src/declarations.tscli/src/ios/update.tscli/src/ipc.tscli/src/tasks/run.tscli/src/telemetry.tscli/src/util/spm.tscli/test/telemetry.spec.tscore/CHANGELOG.mdcore/package.jsonios-pods-template/App/App.xcodeproj/project.pbxprojios-pods-template/App/App/AppDelegate.swiftios-pods-template/App/App/Info.plistios-pods-template/App/App/SceneDelegate.swiftios-spm-template/App/App.xcodeproj/project.pbxprojios-spm-template/App/App/AppDelegate.swiftios-spm-template/App/App/Info.plistios-spm-template/App/App/SceneDelegate.swiftios/CHANGELOG.mdios/Capacitor/Capacitor/PluginConfig.swiftios/package.jsonlerna.json
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
| String configuredInsetsHandling = getConfig().getString("insetsHandling", INSETS_HANDLING_CSS); | ||
| if (INSETS_HANDLING_CSS.equals(configuredInsetsHandling) || INSETS_HANDLING_DISABLE.equals(configuredInsetsHandling)) { | ||
| insetsHandling = configuredInsetsHandling; | ||
| } else { | ||
| Logger.warn( | ||
| "SystemBars", | ||
| "Unknown insetsHandling value '" + configuredInsetsHandling + "'. Falling back to '" + INSETS_HANDLING_CSS + "'." | ||
| ); | ||
| insetsHandling = INSETS_HANDLING_CSS; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Normalize case before comparing insetsHandling.
Unlike style (normalized via .toUpperCase(Locale.US) at line 96), configuredInsetsHandling is compared case-sensitively. A user who configures "Disable"/"DISABLE" silently gets "css" behavior instead of the intended "disable", with only a log warning as feedback.
🔧 Proposed fix
- String configuredInsetsHandling = getConfig().getString("insetsHandling", INSETS_HANDLING_CSS);
+ String configuredInsetsHandling = getConfig().getString("insetsHandling", INSETS_HANDLING_CSS).toLowerCase(Locale.US);
if (INSETS_HANDLING_CSS.equals(configuredInsetsHandling) || INSETS_HANDLING_DISABLE.equals(configuredInsetsHandling)) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| String configuredInsetsHandling = getConfig().getString("insetsHandling", INSETS_HANDLING_CSS); | |
| if (INSETS_HANDLING_CSS.equals(configuredInsetsHandling) || INSETS_HANDLING_DISABLE.equals(configuredInsetsHandling)) { | |
| insetsHandling = configuredInsetsHandling; | |
| } else { | |
| Logger.warn( | |
| "SystemBars", | |
| "Unknown insetsHandling value '" + configuredInsetsHandling + "'. Falling back to '" + INSETS_HANDLING_CSS + "'." | |
| ); | |
| insetsHandling = INSETS_HANDLING_CSS; | |
| } | |
| String configuredInsetsHandling = getConfig().getString("insetsHandling", INSETS_HANDLING_CSS).toLowerCase(Locale.US); | |
| if (INSETS_HANDLING_CSS.equals(configuredInsetsHandling) || INSETS_HANDLING_DISABLE.equals(configuredInsetsHandling)) { | |
| insetsHandling = configuredInsetsHandling; | |
| } else { | |
| Logger.warn( | |
| "SystemBars", | |
| "Unknown insetsHandling value '" + configuredInsetsHandling + "'. Falling back to '" + INSETS_HANDLING_CSS + "'." | |
| ); | |
| insetsHandling = INSETS_HANDLING_CSS; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java`
around lines 99 - 108, Normalize the value read in the SystemBars configuration
logic before comparison, using the same Locale.US-based case normalization
applied to style. Update the configuredInsetsHandling handling so case variants
such as “Disable” and “DISABLE” match INSETS_HANDLING_DISABLE, while preserving
the existing fallback warning and CSS default for unsupported values.
| Insets safeAreaInsets = calcSafeAreaInsets(insets); | ||
| injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Optional: extract duplicated safe-area injection into a helper.
Both branches repeat calcSafeAreaInsets(...) followed by injectSafeAreaCSS(...). Consider a small helper (e.g., injectSafeAreaCSSFromInsets(WindowInsetsCompat insets)) to avoid the duplication.
Also applies to: 243-244
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java`
around lines 210 - 211, Extract the duplicated safe-area calculation and
injection sequence into a helper such as
injectSafeAreaCSSFromInsets(WindowInsetsCompat insets) in SystemBars, then
replace both repeated branches with calls to that helper while preserving the
existing inset values and behavior.
| @Test | ||
| public void showWithEmptyBarShowsSystemBars() throws Exception { | ||
| WindowInsetsControllerCompat controller = invokeSetHidden(""); | ||
|
|
||
| verify(controller).show(WindowInsetsCompat.Type.systemBars()); | ||
| verify(controller, never()).show(WindowInsetsCompat.Type.statusBars()); | ||
| verify(controller, never()).show(WindowInsetsCompat.Type.navigationBars()); | ||
| } | ||
|
|
||
| @Test | ||
| public void showWithStatusBarShowsOnlyStatusBars() throws Exception { | ||
| WindowInsetsControllerCompat controller = invokeSetHidden("StatusBar"); | ||
|
|
||
| verify(controller).show(WindowInsetsCompat.Type.statusBars()); | ||
| verify(controller, never()).show(WindowInsetsCompat.Type.systemBars()); | ||
| verify(controller, never()).show(WindowInsetsCompat.Type.navigationBars()); | ||
| } | ||
|
|
||
| @Test | ||
| public void showWithNavigationBarShowsOnlyNavigationBars() throws Exception { | ||
| WindowInsetsControllerCompat controller = invokeSetHidden("NavigationBar"); | ||
|
|
||
| verify(controller).show(WindowInsetsCompat.Type.navigationBars()); | ||
| verify(controller, never()).show(WindowInsetsCompat.Type.systemBars()); | ||
| verify(controller, never()).show(WindowInsetsCompat.Type.statusBars()); | ||
| } | ||
|
|
||
| private WindowInsetsControllerCompat invokeSetHidden(String bar) throws Exception { | ||
| SystemBars plugin = new SystemBars(); | ||
| Bridge bridge = mock(Bridge.class); | ||
| AppCompatActivity activity = mock(AppCompatActivity.class); | ||
| Window window = mock(Window.class); | ||
| View decorView = mock(View.class); | ||
| WindowInsetsControllerCompat controller = mock(WindowInsetsControllerCompat.class); | ||
|
|
||
| when(bridge.getActivity()).thenReturn(activity); | ||
| when(activity.getWindow()).thenReturn(window); | ||
| when(window.getDecorView()).thenReturn(decorView); | ||
|
|
||
| plugin.setBridge(bridge); | ||
|
|
||
| try (MockedStatic<WindowCompat> windowCompat = mockStatic(WindowCompat.class)) { | ||
| windowCompat.when(() -> WindowCompat.getInsetsController(window, decorView)).thenReturn(controller); | ||
|
|
||
| Method setHidden = SystemBars.class.getDeclaredMethod("setHidden", boolean.class, String.class); | ||
| setHidden.setAccessible(true); | ||
| setHidden.invoke(plugin, false, bar); | ||
| } | ||
|
|
||
| return controller; | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Missing test coverage for the hide=true branch.
All three tests call setHidden(false, bar), only exercising the "show" side of the refactored branching. The hide=true path (Lines 307-315 in SystemBars.java) added/refactored in this same PR has no corresponding test.
✅ Suggested additional tests
`@Test`
public void hideWithEmptyBarHidesSystemBars() throws Exception {
WindowInsetsControllerCompat controller = invokeSetHidden(true, "");
verify(controller).hide(WindowInsetsCompat.Type.systemBars());
}Consider parameterizing invokeSetHidden with a hide boolean to cover both directions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@android/capacitor/src/test/java/com/getcapacitor/plugin/SystemBarsTest.java`
around lines 22 - 72, Extend SystemBarsTest coverage to exercise the hide=true
branch in setHidden. Update invokeSetHidden to accept a boolean hide argument,
adjust existing show tests to pass false, and add corresponding tests for empty,
status, and navigation bar values that verify the appropriate controller.hide
call and ensure other bar types are not invoked.
| # [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) | ||
|
|
||
| ### Bug Fixes | ||
|
|
||
| * **android:** use proguard-android-optimize for AGP 9 compatibility ([52ceef3](https://github.com/Cap-go/capacitor-plus/commit/52ceef3769544c6cb0cbc83963dcc4552983578b)) | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| ## [8.0.7](https://github.com/Cap-go/capacitor-plus/compare/8.0.6...8.0.7) (2026-01-12) | ||
|
|
||
| **Note:** Version bump only for package @capacitor-plus/android | ||
|
|
||
| - **android:** show only the requested system bar ([#8480](https://github.com/ionic-team/capacitor/issues/8480)) ([4c6c321](https://github.com/ionic-team/capacitor/commit/4c6c3219afb5223211e857457e46283c37eb9424)) | ||
| - **SystemBars:** make `safe-area-inset-x` available on API <= 34 ([#8424](https://github.com/ionic-team/capacitor/issues/8424)) ([e456de0](https://github.com/ionic-team/capacitor/commit/e456de083e19644f484bec5a5359cb67960ac8bc)) | ||
| - **SystemBars:** respect `insetsHandling` disable ([#8481](https://github.com/ionic-team/capacitor/issues/8481)) ([d4ad7ff](https://github.com/ionic-team/capacitor/commit/d4ad7ffe39daf66e0cfc63af9028d5c05543bde7)) | ||
|
|
||
| ### Features | ||
|
|
||
| - add method getDouble to plugin config ([#7638](https://github.com/ionic-team/capacitor/issues/7638)) ([93c72de](https://github.com/ionic-team/capacitor/commit/93c72de40a2ec4c78b33659250cb08340083088e)) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the 8.4.0 heading level.
Line [10] is an h1, so the h3 subsections at Lines [12] and [18] skip a heading level. Make the release heading an h2, consistent with the other release sections.
Proposed fix
-# [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02)
+## [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) | |
| ### Bug Fixes | |
| * **android:** use proguard-android-optimize for AGP 9 compatibility ([52ceef3](https://github.com/Cap-go/capacitor-plus/commit/52ceef3769544c6cb0cbc83963dcc4552983578b)) | |
| ## [8.0.7](https://github.com/Cap-go/capacitor-plus/compare/8.0.6...8.0.7) (2026-01-12) | |
| **Note:** Version bump only for package @capacitor-plus/android | |
| - **android:** show only the requested system bar ([#8480](https://github.com/ionic-team/capacitor/issues/8480)) ([4c6c321](https://github.com/ionic-team/capacitor/commit/4c6c3219afb5223211e857457e46283c37eb9424)) | |
| - **SystemBars:** make `safe-area-inset-x` available on API <= 34 ([#8424](https://github.com/ionic-team/capacitor/issues/8424)) ([e456de0](https://github.com/ionic-team/capacitor/commit/e456de083e19644f484bec5a5359cb67960ac8bc)) | |
| - **SystemBars:** respect `insetsHandling` disable ([#8481](https://github.com/ionic-team/capacitor/issues/8481)) ([d4ad7ff](https://github.com/ionic-team/capacitor/commit/d4ad7ffe39daf66e0cfc63af9028d5c05543bde7)) | |
| ### Features | |
| - add method getDouble to plugin config ([#7638](https://github.com/ionic-team/capacitor/issues/7638)) ([93c72de](https://github.com/ionic-team/capacitor/commit/93c72de40a2ec4c78b33659250cb08340083088e)) | |
| ## [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) | |
| ### Bug Fixes | |
| - **android:** show only the requested system bar ([`#8480`](https://github.com/ionic-team/capacitor/issues/8480)) ([4c6c321](https://github.com/ionic-team/capacitor/commit/4c6c3219afb5223211e857457e46283c37eb9424)) | |
| - **SystemBars:** make `safe-area-inset-x` available on API <= 34 ([`#8424`](https://github.com/ionic-team/capacitor/issues/8424)) ([e456de0](https://github.com/ionic-team/capacitor/commit/e456de083e19644f484bec5a5359cb67960ac8bc)) | |
| - **SystemBars:** respect `insetsHandling` disable ([`#8481`](https://github.com/ionic-team/capacitor/issues/8481)) ([d4ad7ff](https://github.com/ionic-team/capacitor/commit/d4ad7ffe39daf66e0cfc63af9028d5c05543bde7)) | |
| ### Features | |
| - add method getDouble to plugin config ([`#7638`](https://github.com/ionic-team/capacitor/issues/7638)) ([93c72de](https://github.com/ionic-team/capacitor/commit/93c72de40a2ec4c78b33659250cb08340083088e)) |
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 12-12: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3
(MD001, heading-increment)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@android/CHANGELOG.md` around lines 10 - 20, Change the 8.4.0 release heading
in the changelog from an h1 to an h2 by using two leading hash characters,
keeping the Bug Fixes and Features subsections unchanged.
Source: Linters/SAST tools
| ## [8.4.1](https://github.com/ionic-team/capacitor/compare/8.4.0...8.4.1) (2026-06-19) | ||
|
|
||
| ### Bug Fixes | ||
|
|
||
| - **cli:** make SPM dependency patch work on prereleases ([#8508](https://github.com/ionic-team/capacitor/issues/8508)) ([6048e90](https://github.com/ionic-team/capacitor/commit/6048e90171afa0229a3c25b52a23c377c6bb804c)) | ||
| - **cli:** patch Capacitor SPM dependency version in plugins ([#8492](https://github.com/ionic-team/capacitor/issues/8492)) ([28bb2c6](https://github.com/ionic-team/capacitor/commit/28bb2c687069dfdd6aa7abc866004a1c6388d103)) | ||
|
|
||
| # [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) | ||
|
|
||
| ### Bug Fixes | ||
|
|
||
| - **android:** show only the requested system bar ([#8480](https://github.com/ionic-team/capacitor/issues/8480)) ([4c6c321](https://github.com/ionic-team/capacitor/commit/4c6c3219afb5223211e857457e46283c37eb9424)) | ||
| - **cli:** revert live reload config on failure ([#8485](https://github.com/ionic-team/capacitor/issues/8485)) ([1d031a4](https://github.com/ionic-team/capacitor/commit/1d031a4abec2c793079ba8897ad2e40c4cc6c7f9)) | ||
| - **SystemBars:** make `safe-area-inset-x` available on API <= 34 ([#8424](https://github.com/ionic-team/capacitor/issues/8424)) ([e456de0](https://github.com/ionic-team/capacitor/commit/e456de083e19644f484bec5a5359cb67960ac8bc)) | ||
| - **SystemBars:** respect `insetsHandling` disable ([#8481](https://github.com/ionic-team/capacitor/issues/8481)) ([d4ad7ff](https://github.com/ionic-team/capacitor/commit/d4ad7ffe39daf66e0cfc63af9028d5c05543bde7)) | ||
|
|
||
| ### Features | ||
|
|
||
| - add method getDouble to plugin config ([#7638](https://github.com/ionic-team/capacitor/issues/7638)) ([93c72de](https://github.com/ionic-team/capacitor/commit/93c72de40a2ec4c78b33659250cb08340083088e)) | ||
| - **cli:** add experimental packageOptions ([#8471](https://github.com/ionic-team/capacitor/issues/8471)) ([258867b](https://github.com/ionic-team/capacitor/commit/258867b7bf37b1837b99b02ec9638e5a6df08d97)) | ||
| - **cli:** capture ios_package_manager in telemetry ([#8482](https://github.com/ionic-team/capacitor/issues/8482)) ([b4b297a](https://github.com/ionic-team/capacitor/commit/b4b297a52f8732659662d5e5aaeff81c0f7d9835)) | ||
|
|
||
| ## [8.3.4](https://github.com/ionic-team/capacitor/compare/8.3.3...8.3.4) (2026-05-12) | ||
|
|
||
| **Note:** Version bump only for package capacitor | ||
|
|
||
| ## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08) | ||
|
|
||
| ### Bug Fixes | ||
|
|
||
| - **cli:** copy plugin files in CocoaPods projects ([#8467](https://github.com/ionic-team/capacitor/issues/8467)) ([b2d7719](https://github.com/ionic-team/capacitor/commit/b2d771926a180e60deea31992d7d4abcd5ca3bc7)) | ||
|
|
||
| ## [8.3.2](https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2) (2026-05-07) | ||
|
|
||
| ### Bug Fixes | ||
|
|
||
| - **cli:** add cSettings support for compiler flags in generated Package.swift ([#8448](https://github.com/ionic-team/capacitor/issues/8448)) ([0bd0676](https://github.com/ionic-team/capacitor/commit/0bd0676315c5fd77e50312dd7b5bf4990dcbd7d0)) | ||
| - **cli:** add system framework and weak framework support in SPM Package.swift ([#8447](https://github.com/ionic-team/capacitor/issues/8447)) ([3232f0f](https://github.com/ionic-team/capacitor/commit/3232f0fe1d9811b0b5c500e3dc05cb8a250177f8)) | ||
| - **cli:** correct Capacitor plugin SPM compat check ([#8440](https://github.com/ionic-team/capacitor/issues/8440)) ([e5ccc45](https://github.com/ionic-team/capacitor/commit/e5ccc451dda27d56bca824ed644bd20fe4d988cb)) | ||
| - **cli:** generate binaryTarget entries for custom xcframeworks in Package.swift ([#8445](https://github.com/ionic-team/capacitor/issues/8445)) ([1f7e33f](https://github.com/ionic-team/capacitor/commit/1f7e33fca43d183332ec19d22b0d75ef81d8cc6d)) | ||
| - **cli:** generate resource entries in Package.swift ([#8455](https://github.com/ionic-team/capacitor/issues/8455)) ([790bd27](https://github.com/ionic-team/capacitor/commit/790bd27123497111984227010c3162cec94a108e)) | ||
| - **cli:** handle Cordova plugins without iOS source files ([#8443](https://github.com/ionic-team/capacitor/issues/8443)) ([0da130e](https://github.com/ionic-team/capacitor/commit/0da130eb7a861bee4e2c35bc0aac53ba9c983fc3)) | ||
| - **cli:** link plugin dependencies in Package.swift ([#8457](https://github.com/ionic-team/capacitor/issues/8457)) ([b3c769e](https://github.com/ionic-team/capacitor/commit/b3c769e856c826b1174518877cf86ac7ce73bf09)) | ||
| - **ios:** support Cordova plugins with Package.swift ([#8438](https://github.com/ionic-team/capacitor/issues/8438)) ([139943b](https://github.com/ionic-team/capacitor/commit/139943b0c05fddb2d1ce2d6f468800fddf17b4cf)) | ||
| - **SystemBars:** avoid extra view padding on API <= 34 ([#8439](https://github.com/ionic-team/capacitor/issues/8439)) ([5b135a7](https://github.com/ionic-team/capacitor/commit/5b135a70217be560e7176c8d5b514cc92ed3e4e4)) | ||
|
|
||
| ## [8.3.1](https://github.com/ionic-team/capacitor/compare/8.3.0...8.3.1) (2026-04-16) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)(CHANGELOG\.md|package\.json|release|changelog|changeset|version|ci|github/workflows|\.github/workflows)($|/)'
echo "== changelog link patterns =="
rg -n "ionic-team/capacitor|Cap-go/capacitor-plus" CHANGELOG.md .github package.json . 2>/dev/null | sed -n '1,220p'
echo "== changelog-related files outline =="
for f in CHANGELOG.md package.json; do
if [ -f "$f" ]; then
echo "--- $f ---"
wc -l "$f"
fi
done
echo "== package scripts if present =="
python3 - <<'PY'
import json, os
p='package.json'
if os.path.exists(p):
data=json.load(open(p))
print(json.dumps(data.get('scripts', {}), indent=2, sort_keys=True))
PYRepository: Cap-go/capacitor-plus
Length of output: 43463
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== root CHANGELOG top =="
sed -n '1,90p' CHANGELOG.md | cat -n
echo "== ios CHANGELOG top =="
sed -n '1,90p' ios/CHANGELOG.md | cat -n
echo "== release/changelog tooling refs =="
rg -n "conventional|changelog|release|version|compare/" .github package.json lerna.json .releaserc* . 2>/dev/null | sed -n '1,260p'
echo "== repo identity refs =="
rg -n "Cap-go/capacitor-plus|ionic-team/capacitor" README.md ios/README.md package.json ios/package.json .github/workflows/*.yml 2>/dev/null | sed -n '1,220p'Repository: Cap-go/capacitor-plus
Length of output: 50377
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== root CHANGELOG 50-120 =="
sed -n '50,120p' CHANGELOG.md | cat -n
echo "== build workflow changelog generation =="
sed -n '45,120p' .github/workflows/build.yml | cat -n
echo "== bump_version workflow relevant bits =="
sed -n '45,95p' .github/workflows/bump_version.yml | cat -nRepository: Cap-go/capacitor-plus
Length of output: 14372
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '45,120p' .github/workflows/build.yml | cat -nRepository: Cap-go/capacitor-plus
Length of output: 2935
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== git remote =="
git remote -v
echo "== lerna.json =="
cat lerna.json
echo "== package.json repository fields =="
python3 - <<'PY'
import json
data=json.load(open('package.json'))
for k in ['repository','homepage','bugs','name','version']:
print(f'{k}: {data.get(k)}')
PY
echo "== root changelog 8.3.1..8.4.1 links only =="
rg -n "## \\[8\\.(3\\.1|3\\.2|3\\.3|3\\.4|4\\.0|4\\.1)\\]|github.com/.*/compare|github.com/.*/issues|github.com/.*/commit" CHANGELOG.md | sed -n '1,120p'Repository: Cap-go/capacitor-plus
Length of output: 25059
Regenerate CHANGELOG.md through the release tooling (CHANGELOG.md:6-52)
This section mixes ionic-team/capacitor links in the 8.4.1–8.3.2 headers with Cap-go/capacitor-plus links below. Keep the changelog fork-scoped end to end so the release notes point at the same repo throughout.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 15-15: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3
(MD001, heading-increment)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CHANGELOG.md` around lines 6 - 52, Regenerate CHANGELOG.md through the
release tooling so the 8.4.1 through 8.3.2 release headers and associated links
consistently reference the Cap-go/capacitor-plus repository instead of mixing in
ionic-team/capacitor URLs.
Source: Coding guidelines
| # [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) | ||
|
|
||
| ### Bug Fixes | ||
|
|
||
| * address follow-up review comments ([8bee786](https://github.com/Cap-go/capacitor-plus/commit/8bee786e2c68ca6c351e88f104b518291c1f81e3)) | ||
| * **cli:** add cSettings support for compiler flags in generated Package.swift ([#8448](https://github.com/Cap-go/capacitor-plus/issues/8448)) ([0bd0676](https://github.com/Cap-go/capacitor-plus/commit/0bd0676315c5fd77e50312dd7b5bf4990dcbd7d0)) | ||
| * **cli:** add system framework and weak framework support in SPM Package.swift ([#8447](https://github.com/Cap-go/capacitor-plus/issues/8447)) ([3232f0f](https://github.com/Cap-go/capacitor-plus/commit/3232f0fe1d9811b0b5c500e3dc05cb8a250177f8)) | ||
| * **cli:** Allow to run update on non macOS ([#8344](https://github.com/Cap-go/capacitor-plus/issues/8344)) ([a441280](https://github.com/Cap-go/capacitor-plus/commit/a441280d7c6b310ca516d6fb2736c09525987774)) | ||
| * **cli:** check CAPACITOR_COCOAPODS_PATH in determinePackageManager ([#8407](https://github.com/Cap-go/capacitor-plus/issues/8407)) ([acb64ab](https://github.com/Cap-go/capacitor-plus/commit/acb64ab92a37ff53701cde453558e272e2e11eb6)) | ||
| * **cli:** correct Capacitor plugin SPM compat check ([#8440](https://github.com/Cap-go/capacitor-plus/issues/8440)) ([e5ccc45](https://github.com/Cap-go/capacitor-plus/commit/e5ccc451dda27d56bca824ed644bd20fe4d988cb)) | ||
| * **cli:** Don't overwrite config.server section with `--live-reload` ([#7528](https://github.com/Cap-go/capacitor-plus/issues/7528)) ([782b9d9](https://github.com/Cap-go/capacitor-plus/commit/782b9d9c26dcf1282b918996becb0224c0baca1d)) | ||
| * **cli:** generate binaryTarget entries for custom xcframeworks in Package.swift ([#8445](https://github.com/Cap-go/capacitor-plus/issues/8445)) ([1f7e33f](https://github.com/Cap-go/capacitor-plus/commit/1f7e33fca43d183332ec19d22b0d75ef81d8cc6d)) | ||
| * **cli:** handle Cordova plugins without iOS source files ([#8443](https://github.com/Cap-go/capacitor-plus/issues/8443)) ([0da130e](https://github.com/Cap-go/capacitor-plus/commit/0da130eb7a861bee4e2c35bc0aac53ba9c983fc3)) | ||
| * **cli:** inline CSS sourcemaps in addition to JS sourcemaps ([#8377](https://github.com/Cap-go/capacitor-plus/issues/8377)) ([69476ab](https://github.com/Cap-go/capacitor-plus/commit/69476ab9c0b47911a14d2482cab53a877a5ae784)) | ||
| * **cli:** Update tar package ([#8311](https://github.com/Cap-go/capacitor-plus/issues/8311)) ([0969c5c](https://github.com/Cap-go/capacitor-plus/commit/0969c5cd0b16cf23d2489a85a3b8fa1bee2ebf3b)) | ||
| * **ios:** support Cordova plugins with Package.swift ([#8438](https://github.com/Cap-go/capacitor-plus/issues/8438)) ([139943b](https://github.com/Cap-go/capacitor-plus/commit/139943b0c05fddb2d1ce2d6f468800fddf17b4cf)) | ||
| * resolve upstream sync conflicts ([75cbb30](https://github.com/Cap-go/capacitor-plus/commit/75cbb3097a7068bcb37313cbe6301628079101ca)) | ||
| * **SystemBars:** use native safe area insets on Android ([#8384](https://github.com/Cap-go/capacitor-plus/issues/8384)) ([4e99598](https://github.com/Cap-go/capacitor-plus/commit/4e99598a2a57ee97e82be1aaa09492744622fa60)) | ||
|
|
||
| - **cli:** revert live reload config on failure ([#8485](https://github.com/ionic-team/capacitor/issues/8485)) ([1d031a4](https://github.com/ionic-team/capacitor/commit/1d031a4abec2c793079ba8897ad2e40c4cc6c7f9)) | ||
|
|
||
| ### Features | ||
|
|
||
| * **cli:** Add --https option for --live-reload ([#8194](https://github.com/Cap-go/capacitor-plus/issues/8194)) ([5db81e6](https://github.com/Cap-go/capacitor-plus/commit/5db81e68c67652e9d2b29d7ad30629b423d2ad30)) | ||
| * **cli:** Add packageManager to iOS config ([#8321](https://github.com/Cap-go/capacitor-plus/issues/8321)) ([a125498](https://github.com/Cap-go/capacitor-plus/commit/a1254983bbb9dcb273d93f3c5f639b792e516406)) | ||
| * **cli:** Experimental config for swift-tools-version in SPM apps ([#8372](https://github.com/Cap-go/capacitor-plus/issues/8372)) ([d2ee84f](https://github.com/Cap-go/capacitor-plus/commit/d2ee84f8186909b142b418c02fc19f79d3c6a6ed)) | ||
| * **cli:** support SPM package traits in generated Package.swift ([#8351](https://github.com/Cap-go/capacitor-plus/issues/8351)) ([27e6aa8](https://github.com/Cap-go/capacitor-plus/commit/27e6aa89cf22e0b1a6d46710faed9aa8899600b0)) | ||
|
|
||
|
|
||
| ### Reverts | ||
|
|
||
| * revert version bump from [#8319](https://github.com/Cap-go/capacitor-plus/issues/8319) and [#8320](https://github.com/Cap-go/capacitor-plus/issues/8320) ([a48ebb6](https://github.com/Cap-go/capacitor-plus/commit/a48ebb622ea4ebe92927bf1756a4d8ac6012884b)) | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| ## [8.0.8](https://github.com/Cap-go/capacitor-plus/compare/8.0.7...8.0.8) (2026-04-08) | ||
|
|
||
| **Note:** Version bump only for package @capacitor-plus/cli | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| ## [8.0.7](https://github.com/Cap-go/capacitor-plus/compare/8.0.6...8.0.7) (2026-01-12) | ||
|
|
||
| **Note:** Version bump only for package @capacitor-plus/cli | ||
|
|
||
|
|
||
|
|
||
|
|
||
| - **cli:** add experimental packageOptions ([#8471](https://github.com/ionic-team/capacitor/issues/8471)) ([258867b](https://github.com/ionic-team/capacitor/commit/258867b7bf37b1837b99b02ec9638e5a6df08d97)) | ||
| - **cli:** capture ios_package_manager in telemetry ([#8482](https://github.com/ionic-team/capacitor/issues/8482)) ([b4b297a](https://github.com/ionic-team/capacitor/commit/b4b297a52f8732659662d5e5aaeff81c0f7d9835)) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the 8.4.0 heading level.
Line [13] is an h1, so the h3 subsections at Lines [15] and [19] skip a heading level. Make the release heading an h2, consistent with the other release sections.
Proposed fix
-# [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02)
+## [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) | |
| ### Bug Fixes | |
| * address follow-up review comments ([8bee786](https://github.com/Cap-go/capacitor-plus/commit/8bee786e2c68ca6c351e88f104b518291c1f81e3)) | |
| * **cli:** add cSettings support for compiler flags in generated Package.swift ([#8448](https://github.com/Cap-go/capacitor-plus/issues/8448)) ([0bd0676](https://github.com/Cap-go/capacitor-plus/commit/0bd0676315c5fd77e50312dd7b5bf4990dcbd7d0)) | |
| * **cli:** add system framework and weak framework support in SPM Package.swift ([#8447](https://github.com/Cap-go/capacitor-plus/issues/8447)) ([3232f0f](https://github.com/Cap-go/capacitor-plus/commit/3232f0fe1d9811b0b5c500e3dc05cb8a250177f8)) | |
| * **cli:** Allow to run update on non macOS ([#8344](https://github.com/Cap-go/capacitor-plus/issues/8344)) ([a441280](https://github.com/Cap-go/capacitor-plus/commit/a441280d7c6b310ca516d6fb2736c09525987774)) | |
| * **cli:** check CAPACITOR_COCOAPODS_PATH in determinePackageManager ([#8407](https://github.com/Cap-go/capacitor-plus/issues/8407)) ([acb64ab](https://github.com/Cap-go/capacitor-plus/commit/acb64ab92a37ff53701cde453558e272e2e11eb6)) | |
| * **cli:** correct Capacitor plugin SPM compat check ([#8440](https://github.com/Cap-go/capacitor-plus/issues/8440)) ([e5ccc45](https://github.com/Cap-go/capacitor-plus/commit/e5ccc451dda27d56bca824ed644bd20fe4d988cb)) | |
| * **cli:** Don't overwrite config.server section with `--live-reload` ([#7528](https://github.com/Cap-go/capacitor-plus/issues/7528)) ([782b9d9](https://github.com/Cap-go/capacitor-plus/commit/782b9d9c26dcf1282b918996becb0224c0baca1d)) | |
| * **cli:** generate binaryTarget entries for custom xcframeworks in Package.swift ([#8445](https://github.com/Cap-go/capacitor-plus/issues/8445)) ([1f7e33f](https://github.com/Cap-go/capacitor-plus/commit/1f7e33fca43d183332ec19d22b0d75ef81d8cc6d)) | |
| * **cli:** handle Cordova plugins without iOS source files ([#8443](https://github.com/Cap-go/capacitor-plus/issues/8443)) ([0da130e](https://github.com/Cap-go/capacitor-plus/commit/0da130eb7a861bee4e2c35bc0aac53ba9c983fc3)) | |
| * **cli:** inline CSS sourcemaps in addition to JS sourcemaps ([#8377](https://github.com/Cap-go/capacitor-plus/issues/8377)) ([69476ab](https://github.com/Cap-go/capacitor-plus/commit/69476ab9c0b47911a14d2482cab53a877a5ae784)) | |
| * **cli:** Update tar package ([#8311](https://github.com/Cap-go/capacitor-plus/issues/8311)) ([0969c5c](https://github.com/Cap-go/capacitor-plus/commit/0969c5cd0b16cf23d2489a85a3b8fa1bee2ebf3b)) | |
| * **ios:** support Cordova plugins with Package.swift ([#8438](https://github.com/Cap-go/capacitor-plus/issues/8438)) ([139943b](https://github.com/Cap-go/capacitor-plus/commit/139943b0c05fddb2d1ce2d6f468800fddf17b4cf)) | |
| * resolve upstream sync conflicts ([75cbb30](https://github.com/Cap-go/capacitor-plus/commit/75cbb3097a7068bcb37313cbe6301628079101ca)) | |
| * **SystemBars:** use native safe area insets on Android ([#8384](https://github.com/Cap-go/capacitor-plus/issues/8384)) ([4e99598](https://github.com/Cap-go/capacitor-plus/commit/4e99598a2a57ee97e82be1aaa09492744622fa60)) | |
| - **cli:** revert live reload config on failure ([#8485](https://github.com/ionic-team/capacitor/issues/8485)) ([1d031a4](https://github.com/ionic-team/capacitor/commit/1d031a4abec2c793079ba8897ad2e40c4cc6c7f9)) | |
| ### Features | |
| * **cli:** Add --https option for --live-reload ([#8194](https://github.com/Cap-go/capacitor-plus/issues/8194)) ([5db81e6](https://github.com/Cap-go/capacitor-plus/commit/5db81e68c67652e9d2b29d7ad30629b423d2ad30)) | |
| * **cli:** Add packageManager to iOS config ([#8321](https://github.com/Cap-go/capacitor-plus/issues/8321)) ([a125498](https://github.com/Cap-go/capacitor-plus/commit/a1254983bbb9dcb273d93f3c5f639b792e516406)) | |
| * **cli:** Experimental config for swift-tools-version in SPM apps ([#8372](https://github.com/Cap-go/capacitor-plus/issues/8372)) ([d2ee84f](https://github.com/Cap-go/capacitor-plus/commit/d2ee84f8186909b142b418c02fc19f79d3c6a6ed)) | |
| * **cli:** support SPM package traits in generated Package.swift ([#8351](https://github.com/Cap-go/capacitor-plus/issues/8351)) ([27e6aa8](https://github.com/Cap-go/capacitor-plus/commit/27e6aa89cf22e0b1a6d46710faed9aa8899600b0)) | |
| ### Reverts | |
| * revert version bump from [#8319](https://github.com/Cap-go/capacitor-plus/issues/8319) and [#8320](https://github.com/Cap-go/capacitor-plus/issues/8320) ([a48ebb6](https://github.com/Cap-go/capacitor-plus/commit/a48ebb622ea4ebe92927bf1756a4d8ac6012884b)) | |
| ## [8.0.8](https://github.com/Cap-go/capacitor-plus/compare/8.0.7...8.0.8) (2026-04-08) | |
| **Note:** Version bump only for package @capacitor-plus/cli | |
| ## [8.0.7](https://github.com/Cap-go/capacitor-plus/compare/8.0.6...8.0.7) (2026-01-12) | |
| **Note:** Version bump only for package @capacitor-plus/cli | |
| - **cli:** add experimental packageOptions ([#8471](https://github.com/ionic-team/capacitor/issues/8471)) ([258867b](https://github.com/ionic-team/capacitor/commit/258867b7bf37b1837b99b02ec9638e5a6df08d97)) | |
| - **cli:** capture ios_package_manager in telemetry ([#8482](https://github.com/ionic-team/capacitor/issues/8482)) ([b4b297a](https://github.com/ionic-team/capacitor/commit/b4b297a52f8732659662d5e5aaeff81c0f7d9835)) | |
| ## [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) | |
| ### Bug Fixes | |
| - **cli:** revert live reload config on failure ([`#8485`](https://github.com/ionic-team/capacitor/issues/8485)) ([1d031a4](https://github.com/ionic-team/capacitor/commit/1d031a4abec2c793079ba8897ad2e40c4cc6c7f9)) | |
| ### Features | |
| - **cli:** add experimental packageOptions ([`#8471`](https://github.com/ionic-team/capacitor/issues/8471)) ([258867b](https://github.com/ionic-team/capacitor/commit/258867b7bf37b1837b99b02ec9638e5a6df08d97)) | |
| - **cli:** capture ios_package_manager in telemetry ([`#8482`](https://github.com/ionic-team/capacitor/issues/8482)) ([b4b297a](https://github.com/ionic-team/capacitor/commit/b4b297a52f8732659662d5e5aaeff81c0f7d9835)) |
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 15-15: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3
(MD001, heading-increment)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@cli/CHANGELOG.md` around lines 13 - 22, Change the 8.4.0 release heading in
the changelog from an h1 to an h2 so its “Bug Fixes” and “Features” h3
subsections follow the same heading hierarchy as other release sections.
Source: Linters/SAST tools
| await Promise.all( | ||
| validSPMPackages.map(async (plugin) => { | ||
| const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name); | ||
| const packageSwiftPath = join(plugin.rootPath, 'Package.swift'); | ||
| let content = await readFile(packageSwiftPath, { encoding: 'utf-8' }); | ||
| const regex = new RegExp( | ||
| 'url:\\s*"https://github.com/ionic-team/capacitor-swift-pm\\.git",\\s*from:\\s*"([^"]+)"', | ||
| ); | ||
| const version = content.match(regex)?.[1]; | ||
| const majorCapVersion = major(iosPlatformVersion); | ||
| if (version && major(version) != majorCapVersion) { | ||
| const preCapVersion = prerelease(iosPlatformVersion); | ||
| const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`; | ||
| content = setAllStringIn( | ||
| content, | ||
| `url: "https://github.com/ionic-team/capacitor-swift-pm.git",`, | ||
| `)`, | ||
| ` from: "${forceVersion}"`, | ||
| ); | ||
| await writeFile(packageSwiftPath, content); | ||
| logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`); | ||
| } | ||
| }), | ||
| ); |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
Hoist getCapacitorPackageVersion outside the per-plugin loop.
iosPlatformVersion doesn't depend on plugin, yet it's re-fetched (an async file/package lookup) for every SPM plugin inside validSPMPackages.map(...). With many plugins this is redundant I/O for an identical result.
♻️ Proposed fix
const validSPMPackages = await checkPluginsForPackageSwift(config, plugins);
+ const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name);
await Promise.all(
validSPMPackages.map(async (plugin) => {
- const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name);
const packageSwiftPath = join(plugin.rootPath, 'Package.swift');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| await Promise.all( | |
| validSPMPackages.map(async (plugin) => { | |
| const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name); | |
| const packageSwiftPath = join(plugin.rootPath, 'Package.swift'); | |
| let content = await readFile(packageSwiftPath, { encoding: 'utf-8' }); | |
| const regex = new RegExp( | |
| 'url:\\s*"https://github.com/ionic-team/capacitor-swift-pm\\.git",\\s*from:\\s*"([^"]+)"', | |
| ); | |
| const version = content.match(regex)?.[1]; | |
| const majorCapVersion = major(iosPlatformVersion); | |
| if (version && major(version) != majorCapVersion) { | |
| const preCapVersion = prerelease(iosPlatformVersion); | |
| const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`; | |
| content = setAllStringIn( | |
| content, | |
| `url: "https://github.com/ionic-team/capacitor-swift-pm.git",`, | |
| `)`, | |
| ` from: "${forceVersion}"`, | |
| ); | |
| await writeFile(packageSwiftPath, content); | |
| logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`); | |
| } | |
| }), | |
| ); | |
| const validSPMPackages = await checkPluginsForPackageSwift(config, plugins); | |
| const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name); | |
| await Promise.all( | |
| validSPMPackages.map(async (plugin) => { | |
| const packageSwiftPath = join(plugin.rootPath, 'Package.swift'); | |
| let content = await readFile(packageSwiftPath, { encoding: 'utf-8' }); | |
| const regex = new RegExp( | |
| 'url:\\s*"https://github.com/ionic-team/capacitor-swift-pm\\.git",\\s*from:\\s*"([^"]+)"', | |
| ); | |
| const version = content.match(regex)?.[1]; | |
| const majorCapVersion = major(iosPlatformVersion); | |
| if (version && major(version) != majorCapVersion) { | |
| const preCapVersion = prerelease(iosPlatformVersion); | |
| const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`; | |
| content = setAllStringIn( | |
| content, | |
| `url: "https://github.com/ionic-team/capacitor-swift-pm.git",`, | |
| `)`, | |
| ` from: "${forceVersion}"`, | |
| ); | |
| await writeFile(packageSwiftPath, content); | |
| logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`); | |
| } | |
| }), | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@cli/src/ios/update.ts` around lines 62 - 85, Move the single await
getCapacitorPackageVersion(config, config.ios.name) call outside the
validSPMPackages.map callback, storing its result before Promise.all; reuse that
iosPlatformVersion for every plugin while preserving the existing version
comparison and update logic.
| <key>UIApplicationSceneManifest</key> | ||
| <dict> | ||
| <key>UIApplicationSupportsMultipleScenes</key> | ||
| <false/> | ||
| <key>UISceneConfigurations</key> | ||
| <dict> | ||
| <key>UIWindowSceneSessionRoleApplication</key> | ||
| <array> | ||
| <dict> | ||
| <key>UISceneConfigurationName</key> | ||
| <string>Default Configuration</string> | ||
| <key>UISceneDelegateClassName</key> | ||
| <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> | ||
| <key>UISceneStoryboardFile</key> | ||
| <string>Main</string> | ||
| </dict> | ||
| </array> | ||
| </dict> | ||
| </dict> |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Consider adding UISceneClassName explicitly.
Apple's default templates and reference implementations for UIApplicationSceneManifest typically include an explicit UISceneClassName (UIWindowScene) entry alongside UISceneDelegateClassName. It defaults to UIWindowScene when omitted, so this shouldn't break anything for a single-window app, but adding it explicitly matches the documented/idiomatic pattern and avoids ambiguity.
📝 Suggested addition
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
+ <key>UISceneClassName</key>
+ <string>UIWindowScene</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <key>UIApplicationSceneManifest</key> | |
| <dict> | |
| <key>UIApplicationSupportsMultipleScenes</key> | |
| <false/> | |
| <key>UISceneConfigurations</key> | |
| <dict> | |
| <key>UIWindowSceneSessionRoleApplication</key> | |
| <array> | |
| <dict> | |
| <key>UISceneConfigurationName</key> | |
| <string>Default Configuration</string> | |
| <key>UISceneDelegateClassName</key> | |
| <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> | |
| <key>UISceneStoryboardFile</key> | |
| <string>Main</string> | |
| </dict> | |
| </array> | |
| </dict> | |
| </dict> | |
| <key>UIApplicationSceneManifest</key> | |
| <dict> | |
| <key>UIApplicationSupportsMultipleScenes</key> | |
| <false/> | |
| <key>UISceneConfigurations</key> | |
| <dict> | |
| <key>UIWindowSceneSessionRoleApplication</key> | |
| <array> | |
| <dict> | |
| <key>UISceneConfigurationName</key> | |
| <string>Default Configuration</string> | |
| <key>UISceneClassName</key> | |
| <string>UIWindowScene</string> | |
| <key>UISceneDelegateClassName</key> | |
| <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> | |
| <key>UISceneStoryboardFile</key> | |
| <string>Main</string> | |
| </dict> | |
| </array> | |
| </dict> | |
| </dict> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@ios-spm-template/App/App/Info.plist` around lines 27 - 45, Add an explicit
UISceneClassName entry with UIWindowScene to the application scene configuration
alongside UISceneDelegateClassName in UIApplicationSceneManifest, preserving the
existing single-window configuration.


Merge Conflict Resolution Required
The sync of upstream PR ionic-team#8527 from @nilspep encountered merge conflicts.
Original PR: ionic-team#8527
What happened
Synced from upstream by Capacitor+ Bot
Summary by CodeRabbit
New Features
Bug Fixes
Release