From 23ad7f8a4231a3b78abec32bb67bbd0c415b5011 Mon Sep 17 00:00:00 2001 From: "Github Workflow (on behalf of markemer)" Date: Thu, 7 May 2026 16:55:19 +0000 Subject: [PATCH 01/23] Release 8.3.2 --- CHANGELOG.md | 14 ++++++++++++++ android/CHANGELOG.md | 6 ++++++ android/package.json | 2 +- cli/CHANGELOG.md | 13 +++++++++++++ cli/package.json | 2 +- core/CHANGELOG.md | 4 ++++ core/package.json | 2 +- ios/CHANGELOG.md | 4 ++++ ios/package.json | 2 +- lerna.json | 2 +- 10 files changed, 46 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95ee704f6..3851a6663 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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) ### Bug Fixes diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index 5812a4832..ca3b6f0ef 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.3.2](https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2) (2026-05-07) + +### Bug Fixes + +- **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) ### Bug Fixes diff --git a/android/package.json b/android/package.json index f55229c31..5ecf01e07 100644 --- a/android/package.json +++ b/android/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/android", - "version": "8.3.1", + "version": "8.3.2", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index ac66f222f..1cc5720a1 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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)) + ## [8.3.1](https://github.com/ionic-team/capacitor/compare/8.3.0...8.3.1) (2026-04-16) ### Bug Fixes diff --git a/cli/package.json b/cli/package.json index b9f5d1ccc..abc3774df 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/cli", - "version": "8.3.1", + "version": "8.3.2", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 60a9ca82b..08c8815c3 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.3.2](https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2) (2026-05-07) + +**Note:** Version bump only for package @capacitor/core + ## [8.3.1](https://github.com/ionic-team/capacitor/compare/8.3.0...8.3.1) (2026-04-16) **Note:** Version bump only for package @capacitor/core diff --git a/core/package.json b/core/package.json index 54e8c7110..bc3bebc0f 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/core", - "version": "8.3.1", + "version": "8.3.2", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md index a16975c79..111b642ac 100644 --- a/ios/CHANGELOG.md +++ b/ios/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.3.2](https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2) (2026-05-07) + +**Note:** Version bump only for package @capacitor/ios + ## [8.3.1](https://github.com/ionic-team/capacitor/compare/8.3.0...8.3.1) (2026-04-16) ### Bug Fixes diff --git a/ios/package.json b/ios/package.json index 4f7200cad..0972ed946 100644 --- a/ios/package.json +++ b/ios/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/ios", - "version": "8.3.1", + "version": "8.3.2", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/lerna.json b/lerna.json index 5f513f656..d0a1ebc02 100644 --- a/lerna.json +++ b/lerna.json @@ -11,6 +11,6 @@ "tagVersionPrefix": "" } }, - "version": "8.3.1", + "version": "8.3.2", "$schema": "node_modules/lerna/schemas/lerna-schema.json" } From b2d771926a180e60deea31992d7d4abcd5ca3bc7 Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Fri, 8 May 2026 18:44:22 +0200 Subject: [PATCH 02/23] fix(cli): copy plugin files in CocoaPods projects (#8467) --- cli/src/ios/update.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/ios/update.ts b/cli/src/ios/update.ts index 9fcd1c718..82ca85a88 100644 --- a/cli/src/ios/update.ts +++ b/cli/src/ios/update.ts @@ -564,7 +564,7 @@ async function copyPluginsNativeFiles(config: Config, cordovaPlugins: Plugin[]) const isSPM = (await config.ios.packageManager) === 'SPM'; for (const p of cordovaPlugins) { const platformTag = getPluginPlatform(p, platform); - if (platformTag.$?.package) { + if (isSPM && platformTag.$?.package) { continue; } const sourceFiles = getPlatformElement(p, platform, 'source-file'); From 76ff70e0e40bbbca63c5195c572f166e5ce82089 Mon Sep 17 00:00:00 2001 From: "Github Workflow (on behalf of markemer)" Date: Fri, 8 May 2026 17:08:40 +0000 Subject: [PATCH 03/23] Release 8.3.3 --- CHANGELOG.md | 6 ++++++ android/CHANGELOG.md | 4 ++++ android/package.json | 2 +- cli/CHANGELOG.md | 6 ++++++ cli/package.json | 2 +- core/CHANGELOG.md | 4 ++++ core/package.json | 2 +- ios/CHANGELOG.md | 4 ++++ ios/package.json | 2 +- lerna.json | 2 +- 10 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3851a6663..d4ad41ff2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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 diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index ca3b6f0ef..d4b2fc534 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08) + +**Note:** Version bump only for package @capacitor/android + ## [8.3.2](https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2) (2026-05-07) ### Bug Fixes diff --git a/android/package.json b/android/package.json index 5ecf01e07..07db8a26e 100644 --- a/android/package.json +++ b/android/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/android", - "version": "8.3.2", + "version": "8.3.3", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 1cc5720a1..452ba4cc6 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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 diff --git a/cli/package.json b/cli/package.json index abc3774df..cd17f5d2f 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/cli", - "version": "8.3.2", + "version": "8.3.3", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 08c8815c3..26f5723fe 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08) + +**Note:** Version bump only for package @capacitor/core + ## [8.3.2](https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2) (2026-05-07) **Note:** Version bump only for package @capacitor/core diff --git a/core/package.json b/core/package.json index bc3bebc0f..373249f98 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/core", - "version": "8.3.2", + "version": "8.3.3", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md index 111b642ac..b9b7863b0 100644 --- a/ios/CHANGELOG.md +++ b/ios/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08) + +**Note:** Version bump only for package @capacitor/ios + ## [8.3.2](https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2) (2026-05-07) **Note:** Version bump only for package @capacitor/ios diff --git a/ios/package.json b/ios/package.json index 0972ed946..bd4c0a320 100644 --- a/ios/package.json +++ b/ios/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/ios", - "version": "8.3.2", + "version": "8.3.3", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/lerna.json b/lerna.json index d0a1ebc02..d64bfcd44 100644 --- a/lerna.json +++ b/lerna.json @@ -11,6 +11,6 @@ "tagVersionPrefix": "" } }, - "version": "8.3.2", + "version": "8.3.3", "$schema": "node_modules/lerna/schemas/lerna-schema.json" } From b7e167bbab47c57a5f72ff9e76a726ab7d8a1c1f Mon Sep 17 00:00:00 2001 From: "Alex J." Date: Tue, 12 May 2026 15:19:58 -0400 Subject: [PATCH 04/23] chore(cli): update telemetry endpoint (#8464) --- cli/src/ipc.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/src/ipc.ts b/cli/src/ipc.ts index 41894e53a..37c38110b 100644 --- a/cli/src/ipc.ts +++ b/cli/src/ipc.ts @@ -49,9 +49,9 @@ export async function receive(msg: IPCMessage): Promise { // This request is only made if telemetry is on. const req = request( { - hostname: 'api.ionicjs.com', + hostname: 'metrics-capacitor.outsystems.com', port: 443, - path: '/events/metrics', + path: '/metrics', method: 'POST', headers: { 'Content-Type': 'application/json', @@ -60,7 +60,7 @@ export async function receive(msg: IPCMessage): Promise { (response) => { debug('Sent %O metric to events service (status: %O)', data.name, response.statusCode); - if (response.statusCode !== 204) { + if (response.statusCode !== 202) { response.on('data', (chunk) => { debug('Bad response from events service. Request body: %O', chunk.toString()); }); From de1e506e48204f3d9a51bc911fafc341fd81fc36 Mon Sep 17 00:00:00 2001 From: "Github Workflow (on behalf of alexgerardojacinto)" Date: Tue, 12 May 2026 20:38:58 +0000 Subject: [PATCH 05/23] Release 8.3.4 --- CHANGELOG.md | 4 ++++ android/CHANGELOG.md | 4 ++++ android/package.json | 2 +- cli/CHANGELOG.md | 4 ++++ cli/package.json | 2 +- core/CHANGELOG.md | 4 ++++ core/package.json | 2 +- ios/CHANGELOG.md | 4 ++++ ios/package.json | 2 +- lerna.json | 2 +- 10 files changed, 25 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4ad41ff2..a7f2b7713 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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 diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index d4b2fc534..74d538d9f 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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/android + ## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08) **Note:** Version bump only for package @capacitor/android diff --git a/android/package.json b/android/package.json index 07db8a26e..8ae93f3f2 100644 --- a/android/package.json +++ b/android/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/android", - "version": "8.3.3", + "version": "8.3.4", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 452ba4cc6..bba24688f 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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/cli + ## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08) ### Bug Fixes diff --git a/cli/package.json b/cli/package.json index cd17f5d2f..9df346b14 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/cli", - "version": "8.3.3", + "version": "8.3.4", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 26f5723fe..017293794 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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/core + ## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08) **Note:** Version bump only for package @capacitor/core diff --git a/core/package.json b/core/package.json index 373249f98..eef113a50 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/core", - "version": "8.3.3", + "version": "8.3.4", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md index b9b7863b0..87ee73bb4 100644 --- a/ios/CHANGELOG.md +++ b/ios/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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/ios + ## [8.3.3](https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3) (2026-05-08) **Note:** Version bump only for package @capacitor/ios diff --git a/ios/package.json b/ios/package.json index bd4c0a320..a7b8d3133 100644 --- a/ios/package.json +++ b/ios/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/ios", - "version": "8.3.3", + "version": "8.3.4", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/lerna.json b/lerna.json index d64bfcd44..1e53d6bdc 100644 --- a/lerna.json +++ b/lerna.json @@ -11,6 +11,6 @@ "tagVersionPrefix": "" } }, - "version": "8.3.3", + "version": "8.3.4", "$schema": "node_modules/lerna/schemas/lerna-schema.json" } From 731a82e554d9c1270241897228e934c38759bbbb Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Thu, 21 May 2026 17:39:31 +0200 Subject: [PATCH 06/23] chore: format java code (#8475) --- .../com/getcapacitor/BridgeWebChromeClient.java | 12 ++++++------ .../src/main/java/com/getcapacitor/FileUtils.java | 6 +++--- .../src/main/java/com/getcapacitor/Plugin.java | 4 ++-- .../cordova/MockCordovaWebViewImpl.java | 14 ++++++-------- .../com/getcapacitor/plugin/CapacitorHttp.java | 4 ++-- .../java/com/getcapacitor/ConfigBuildingTest.java | 6 +++--- 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java b/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java index 6ca1c8a83..58371a9ff 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java +++ b/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java @@ -246,14 +246,14 @@ public boolean onJsPrompt(WebView view, String url, String message, String defau public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { super.onGeolocationPermissionsShowPrompt(origin, callback); Logger.debug("onGeolocationPermissionsShowPrompt: DOING IT HERE FOR ORIGIN: " + origin); - final String[] geoPermissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }; + final String[] geoPermissions = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}; if (!PermissionHelper.hasPermissions(bridge.getContext(), geoPermissions)) { permissionListener = (isGranted) -> { if (isGranted) { callback.invoke(origin, true, false); } else { - final String[] coarsePermission = { Manifest.permission.ACCESS_COARSE_LOCATION }; + final String[] coarsePermission = {Manifest.permission.ACCESS_COARSE_LOCATION}; if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && PermissionHelper.hasPermissions(bridge.getContext(), coarsePermission) @@ -294,7 +294,7 @@ public boolean onShowFileChooser( filePathCallback.onReceiveValue(null); } }; - final String[] camPermission = { Manifest.permission.CAMERA }; + final String[] camPermission = {Manifest.permission.CAMERA}; permissionLauncher.launch(camPermission); } } else { @@ -305,7 +305,7 @@ public boolean onShowFileChooser( } private boolean isMediaCaptureSupported() { - String[] permissions = { Manifest.permission.CAMERA }; + String[] permissions = {Manifest.permission.CAMERA}; return ( PermissionHelper.hasPermissions(bridge.getContext(), permissions) || !PermissionHelper.hasDefinedPermission(bridge.getContext(), Manifest.permission.CAMERA) @@ -343,7 +343,7 @@ private boolean showImageCapturePicker(final ValueCallback filePathCallba activityListener = (activityResult) -> { Uri[] result = null; if (activityResult.getResultCode() == Activity.RESULT_OK) { - result = new Uri[] { imageFileUri }; + result = new Uri[] {imageFileUri}; } filePathCallback.onReceiveValue(result); }; @@ -362,7 +362,7 @@ private boolean showVideoCapturePicker(final ValueCallback filePathCallba activityListener = (activityResult) -> { Uri[] result = null; if (activityResult.getResultCode() == Activity.RESULT_OK) { - result = new Uri[] { activityResult.getData().getData() }; + result = new Uri[] {activityResult.getData().getData()}; } filePathCallback.onReceiveValue(result); }; diff --git a/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java b/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java index ce09e7c2f..0fdf64feb 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java +++ b/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java @@ -118,7 +118,7 @@ else if (isMediaDocument(uri)) { } final String selection = "_id=?"; - final String[] selectionArgs = new String[] { split[1] }; + final String[] selectionArgs = new String[] {split[1]}; return getDataColumn(context, contentUri, selection, selectionArgs); } @@ -195,7 +195,7 @@ private static String getDataColumn(Context context, Uri uri, String selection, String path = null; Cursor cursor = null; final String column = "_data"; - final String[] projection = { column }; + final String[] projection = {column}; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); @@ -292,7 +292,7 @@ private static String getPathToNonPrimaryVolume(Context context, String tag) { } private static String sanitizeFilename(String displayName) { - String[] badCharacters = new String[] { "..", "/" }; + String[] badCharacters = new String[] {"..", "/"}; String[] segments = displayName.split("/"); String fileName = segments[segments.length - 1]; for (String suspString : badCharacters) { diff --git a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java index 19c8b8b3a..e55d933cc 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java @@ -465,7 +465,7 @@ protected void requestAllPermissions(@NonNull PluginCall call, @NonNull String c * @param callbackName the name of the callback to run when the permission request is complete */ protected void requestPermissionForAlias(@NonNull String alias, @NonNull PluginCall call, @NonNull String callbackName) { - requestPermissionForAliases(new String[] { alias }, call, callbackName); + requestPermissionForAliases(new String[] {alias}, call, callbackName); } /** @@ -583,7 +583,7 @@ public void pluginRequestAllPermissions() { */ @Deprecated public void pluginRequestPermission(String permission, int requestCode) { - ActivityCompat.requestPermissions(getActivity(), new String[] { permission }, requestCode); + ActivityCompat.requestPermissions(getActivity(), new String[] {permission}, requestCode); } /** diff --git a/android/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java b/android/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java index 1115429d7..020c1457a 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java +++ b/android/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java @@ -70,14 +70,12 @@ public CapacitorEvalBridgeMode(WebView webView, CordovaInterface cordova) { @Override public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) { - cordova - .getActivity() - .runOnUiThread(() -> { - String js = queue.popAndEncodeAsJs(); - if (js != null) { - webView.evaluateJavascript(js, null); - } - }); + cordova.getActivity().runOnUiThread(() -> { + String js = queue.popAndEncodeAsJs(); + if (js != null) { + webView.evaluateJavascript(js, null); + } + }); } } diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java index 46bc17417..7d5ab337e 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java @@ -18,8 +18,8 @@ @CapacitorPlugin( permissions = { - @Permission(strings = { Manifest.permission.WRITE_EXTERNAL_STORAGE }, alias = "HttpWrite"), - @Permission(strings = { Manifest.permission.READ_EXTERNAL_STORAGE }, alias = "HttpRead") + @Permission(strings = {Manifest.permission.WRITE_EXTERNAL_STORAGE}, alias = "HttpWrite"), + @Permission(strings = {Manifest.permission.READ_EXTERNAL_STORAGE}, alias = "HttpRead") } ) public class CapacitorHttp extends Plugin { diff --git a/android/capacitor/src/test/java/com/getcapacitor/ConfigBuildingTest.java b/android/capacitor/src/test/java/com/getcapacitor/ConfigBuildingTest.java index 1af51039d..ae12edb02 100644 --- a/android/capacitor/src/test/java/com/getcapacitor/ConfigBuildingTest.java +++ b/android/capacitor/src/test/java/com/getcapacitor/ConfigBuildingTest.java @@ -42,7 +42,7 @@ public void setup() { config = new CapConfig.Builder(context) .setAllowMixedContent(true) - .setAllowNavigation(new String[] { "http://www.google.com" }) + .setAllowNavigation(new String[] {"http://www.google.com"}) .setAndroidScheme("test") .setCaptureInput(true) .setLoggingEnabled(true) @@ -64,7 +64,7 @@ public void setup() { @Test public void getCoreConfigValues() { assertTrue(config.isMixedContentAllowed()); - assertArrayEquals(new String[] { "http://www.google.com" }, config.getAllowNavigation()); + assertArrayEquals(new String[] {"http://www.google.com"}, config.getAllowNavigation()); assertEquals("test", config.getAndroidScheme()); assertTrue(config.isInputCaptured()); assertTrue(config.isLoggingEnabled()); @@ -97,7 +97,7 @@ public void getPluginInt() { @Test public void getPluginArray() { - String[] comparison = new String[] { "5", "6", "7", "8" }; + String[] comparison = new String[] {"5", "6", "7", "8"}; String[] testArray = config.getPluginConfiguration(TEST_PLUGIN_NAME).getArray("var5"); assertArrayEquals(comparison, testArray); } From bc745364129853769ca2fcfc3cc2a6c7624ee513 Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Thu, 21 May 2026 18:04:37 +0200 Subject: [PATCH 07/23] chore: format java code (#8477) --- .../java/com/getcapacitor/BridgeWebChromeClient.java | 12 ++++++------ .../src/main/java/com/getcapacitor/FileUtils.java | 6 +++--- .../src/main/java/com/getcapacitor/Plugin.java | 4 ++-- .../java/com/getcapacitor/plugin/CapacitorHttp.java | 4 ++-- .../java/com/getcapacitor/ConfigBuildingTest.java | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java b/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java index 58371a9ff..6ca1c8a83 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java +++ b/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java @@ -246,14 +246,14 @@ public boolean onJsPrompt(WebView view, String url, String message, String defau public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { super.onGeolocationPermissionsShowPrompt(origin, callback); Logger.debug("onGeolocationPermissionsShowPrompt: DOING IT HERE FOR ORIGIN: " + origin); - final String[] geoPermissions = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}; + final String[] geoPermissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }; if (!PermissionHelper.hasPermissions(bridge.getContext(), geoPermissions)) { permissionListener = (isGranted) -> { if (isGranted) { callback.invoke(origin, true, false); } else { - final String[] coarsePermission = {Manifest.permission.ACCESS_COARSE_LOCATION}; + final String[] coarsePermission = { Manifest.permission.ACCESS_COARSE_LOCATION }; if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && PermissionHelper.hasPermissions(bridge.getContext(), coarsePermission) @@ -294,7 +294,7 @@ public boolean onShowFileChooser( filePathCallback.onReceiveValue(null); } }; - final String[] camPermission = {Manifest.permission.CAMERA}; + final String[] camPermission = { Manifest.permission.CAMERA }; permissionLauncher.launch(camPermission); } } else { @@ -305,7 +305,7 @@ public boolean onShowFileChooser( } private boolean isMediaCaptureSupported() { - String[] permissions = {Manifest.permission.CAMERA}; + String[] permissions = { Manifest.permission.CAMERA }; return ( PermissionHelper.hasPermissions(bridge.getContext(), permissions) || !PermissionHelper.hasDefinedPermission(bridge.getContext(), Manifest.permission.CAMERA) @@ -343,7 +343,7 @@ private boolean showImageCapturePicker(final ValueCallback filePathCallba activityListener = (activityResult) -> { Uri[] result = null; if (activityResult.getResultCode() == Activity.RESULT_OK) { - result = new Uri[] {imageFileUri}; + result = new Uri[] { imageFileUri }; } filePathCallback.onReceiveValue(result); }; @@ -362,7 +362,7 @@ private boolean showVideoCapturePicker(final ValueCallback filePathCallba activityListener = (activityResult) -> { Uri[] result = null; if (activityResult.getResultCode() == Activity.RESULT_OK) { - result = new Uri[] {activityResult.getData().getData()}; + result = new Uri[] { activityResult.getData().getData() }; } filePathCallback.onReceiveValue(result); }; diff --git a/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java b/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java index 0fdf64feb..ce09e7c2f 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java +++ b/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java @@ -118,7 +118,7 @@ else if (isMediaDocument(uri)) { } final String selection = "_id=?"; - final String[] selectionArgs = new String[] {split[1]}; + final String[] selectionArgs = new String[] { split[1] }; return getDataColumn(context, contentUri, selection, selectionArgs); } @@ -195,7 +195,7 @@ private static String getDataColumn(Context context, Uri uri, String selection, String path = null; Cursor cursor = null; final String column = "_data"; - final String[] projection = {column}; + final String[] projection = { column }; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); @@ -292,7 +292,7 @@ private static String getPathToNonPrimaryVolume(Context context, String tag) { } private static String sanitizeFilename(String displayName) { - String[] badCharacters = new String[] {"..", "/"}; + String[] badCharacters = new String[] { "..", "/" }; String[] segments = displayName.split("/"); String fileName = segments[segments.length - 1]; for (String suspString : badCharacters) { diff --git a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java index e55d933cc..19c8b8b3a 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java @@ -465,7 +465,7 @@ protected void requestAllPermissions(@NonNull PluginCall call, @NonNull String c * @param callbackName the name of the callback to run when the permission request is complete */ protected void requestPermissionForAlias(@NonNull String alias, @NonNull PluginCall call, @NonNull String callbackName) { - requestPermissionForAliases(new String[] {alias}, call, callbackName); + requestPermissionForAliases(new String[] { alias }, call, callbackName); } /** @@ -583,7 +583,7 @@ public void pluginRequestAllPermissions() { */ @Deprecated public void pluginRequestPermission(String permission, int requestCode) { - ActivityCompat.requestPermissions(getActivity(), new String[] {permission}, requestCode); + ActivityCompat.requestPermissions(getActivity(), new String[] { permission }, requestCode); } /** diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java index 7d5ab337e..46bc17417 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java @@ -18,8 +18,8 @@ @CapacitorPlugin( permissions = { - @Permission(strings = {Manifest.permission.WRITE_EXTERNAL_STORAGE}, alias = "HttpWrite"), - @Permission(strings = {Manifest.permission.READ_EXTERNAL_STORAGE}, alias = "HttpRead") + @Permission(strings = { Manifest.permission.WRITE_EXTERNAL_STORAGE }, alias = "HttpWrite"), + @Permission(strings = { Manifest.permission.READ_EXTERNAL_STORAGE }, alias = "HttpRead") } ) public class CapacitorHttp extends Plugin { diff --git a/android/capacitor/src/test/java/com/getcapacitor/ConfigBuildingTest.java b/android/capacitor/src/test/java/com/getcapacitor/ConfigBuildingTest.java index ae12edb02..1af51039d 100644 --- a/android/capacitor/src/test/java/com/getcapacitor/ConfigBuildingTest.java +++ b/android/capacitor/src/test/java/com/getcapacitor/ConfigBuildingTest.java @@ -42,7 +42,7 @@ public void setup() { config = new CapConfig.Builder(context) .setAllowMixedContent(true) - .setAllowNavigation(new String[] {"http://www.google.com"}) + .setAllowNavigation(new String[] { "http://www.google.com" }) .setAndroidScheme("test") .setCaptureInput(true) .setLoggingEnabled(true) @@ -64,7 +64,7 @@ public void setup() { @Test public void getCoreConfigValues() { assertTrue(config.isMixedContentAllowed()); - assertArrayEquals(new String[] {"http://www.google.com"}, config.getAllowNavigation()); + assertArrayEquals(new String[] { "http://www.google.com" }, config.getAllowNavigation()); assertEquals("test", config.getAndroidScheme()); assertTrue(config.isInputCaptured()); assertTrue(config.isLoggingEnabled()); @@ -97,7 +97,7 @@ public void getPluginInt() { @Test public void getPluginArray() { - String[] comparison = new String[] {"5", "6", "7", "8"}; + String[] comparison = new String[] { "5", "6", "7", "8" }; String[] testArray = config.getPluginConfiguration(TEST_PLUGIN_NAME).getArray("var5"); assertArrayEquals(comparison, testArray); } From 93c72de40a2ec4c78b33659250cb08340083088e Mon Sep 17 00:00:00 2001 From: Robin Genz Date: Thu, 21 May 2026 18:54:21 +0200 Subject: [PATCH 08/23] feat: add method getDouble to plugin config (#7638) Co-authored-by: jcesarmobile --- .../java/com/getcapacitor/PluginConfig.java | 11 ++++++++++ .../java/com/getcapacitor/util/JSONUtils.java | 20 +++++++++++++++++++ ios/Capacitor/Capacitor/PluginConfig.swift | 7 +++++++ 3 files changed, 38 insertions(+) diff --git a/android/capacitor/src/main/java/com/getcapacitor/PluginConfig.java b/android/capacitor/src/main/java/com/getcapacitor/PluginConfig.java index 0f00fc530..1d21ae90e 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/PluginConfig.java +++ b/android/capacitor/src/main/java/com/getcapacitor/PluginConfig.java @@ -65,6 +65,17 @@ public int getInt(String configKey, int defaultValue) { return JSONUtils.getInt(config, configKey, defaultValue); } + /** + * Get a double value for a plugin in the Capacitor config. + * + * @param configKey The key of the value to retrieve + * @param defaultValue A default value to return if the key does not exist in the config + * @return The value from the config, if key exists. Default value returned if not + */ + public double getDouble(String configKey, double defaultValue) { + return JSONUtils.getDouble(config, configKey, defaultValue); + } + /** * Get a string array value for a plugin in the Capacitor config. * diff --git a/android/capacitor/src/main/java/com/getcapacitor/util/JSONUtils.java b/android/capacitor/src/main/java/com/getcapacitor/util/JSONUtils.java index 1d2fc2078..f24e5aa0b 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/util/JSONUtils.java +++ b/android/capacitor/src/main/java/com/getcapacitor/util/JSONUtils.java @@ -75,6 +75,26 @@ public static int getInt(JSONObject jsonObject, String key, int defaultValue) { return defaultValue; } + /** + * Get a double value from the given JSON object. + * + * @param jsonObject A JSON object to search + * @param key A key to fetch from the JSON object + * @param defaultValue A default value to return if the key cannot be found + * @return The value at the given key in the JSON object, or the default value + */ + public static double getDouble(JSONObject jsonObject, String key, double defaultValue) { + String k = getDeepestKey(key); + try { + JSONObject o = getDeepestObject(jsonObject, key); + return o.getDouble(k); + } catch (JSONException ignore) { + // value was not found + } + + return defaultValue; + } + /** * Get a JSON object value from the given JSON object. * diff --git a/ios/Capacitor/Capacitor/PluginConfig.swift b/ios/Capacitor/Capacitor/PluginConfig.swift index f2461e102..8d73bc1de 100644 --- a/ios/Capacitor/Capacitor/PluginConfig.swift +++ b/ios/Capacitor/Capacitor/PluginConfig.swift @@ -30,6 +30,13 @@ import Foundation return defaultValue } + @objc public func getDouble(_ configKey: String, _ defaultValue: Double) -> Double { + if let val = (self.config)[keyPath: KeyPath(configKey)] as? Double { + return val + } + return defaultValue + } + public func getArray(_ configKey: String, _ defaultValue: JSArray? = nil) -> JSArray? { if let val = (self.config)[keyPath: KeyPath(configKey)] as? JSArray { return val From e456de083e19644f484bec5a5359cb67960ac8bc Mon Sep 17 00:00:00 2001 From: Joey Pender Date: Fri, 22 May 2026 13:39:38 -0500 Subject: [PATCH 09/23] fix(SystemBars): make `safe-area-inset-x` available on API <= 34 (#8424) --- .../com/getcapacitor/plugin/SystemBars.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java index b335b4b1c..76e74207c 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java @@ -164,13 +164,18 @@ private Insets calcSafeAreaInsets(WindowInsetsCompat insets) { } private void initSafeAreaCSSVariables() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && insetHandlingEnabled) { + WindowInsetsCompat insets; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { View v = (View) this.getBridge().getWebView().getParent(); - WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(v); - if (insets != null) { - Insets safeAreaInsets = calcSafeAreaInsets(insets); - injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); - } + insets = ViewCompat.getRootWindowInsets(v); + } else { + insets = WindowInsetsCompat.CONSUMED; + } + + if (insets != null) { + Insets safeAreaInsets = calcSafeAreaInsets(insets); + injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); } } @@ -186,10 +191,8 @@ private void initWindowInsetsListener() { // We need to correct for a possible shown IME v.setPadding(0, 0, 0, keyboardVisible ? imeInsets.bottom : 0); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && hasViewportCover && insetHandlingEnabled) { - Insets safeAreaInsets = calcSafeAreaInsets(insets); - injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); - } + Insets safeAreaInsets = calcSafeAreaInsets(insets); + injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); return new WindowInsetsCompat.Builder(insets) .setInsets( @@ -221,10 +224,8 @@ private void initWindowInsetsListener() { .setInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout(), Insets.of(0, 0, 0, 0)) .build(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && hasViewportCover && insetHandlingEnabled) { - Insets safeAreaInsets = calcSafeAreaInsets(newInsets); - injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); - } + Insets safeAreaInsets = calcSafeAreaInsets(newInsets); + injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); return newInsets; }); From 258867b7bf37b1837b99b02ec9638e5a6df08d97 Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Tue, 26 May 2026 12:00:02 +0200 Subject: [PATCH 10/23] feat(cli): add experimental packageOptions (#8471) --- cli/src/declarations.ts | 20 ++++++++++++++++++++ cli/src/ios/update.ts | 3 +++ cli/src/util/spm.ts | 21 ++++++++++++++++++--- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/cli/src/declarations.ts b/cli/src/declarations.ts index 6c8645406..bda7ff0c0 100644 --- a/cli/src/declarations.ts +++ b/cli/src/declarations.ts @@ -559,6 +559,13 @@ export interface CapacitorConfig { * @since 8.3.0 */ packageTraits?: { [pluginId: string]: string[] }; + /** + * Define options to apply to the package. + * The key is the plugin ID (e.g. `@capacitor-community/device`) + * + * @since 8.4.0 + */ + packageOptions?: { [pluginId: string]: PackageOptions }; }; }; }; @@ -799,3 +806,16 @@ export interface PluginsConfig { animation?: 'FADE' | 'NONE'; }; } + +export interface PackageOptions { + /** + * Create a symlink to the plugin folder instead of pointing to the plugin path. + * Useful when plugin names conflict. + */ + symlink?: boolean; + /** + * Useful to avoid target name conflicts in dependencies + * [see](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/modulealiasing/) + */ + moduleAliases?: { [target: string]: string }; +} diff --git a/cli/src/ios/update.ts b/cli/src/ios/update.ts index 82ca85a88..b060e59a8 100644 --- a/cli/src/ios/update.ts +++ b/cli/src/ios/update.ts @@ -639,6 +639,9 @@ async function copyPluginsNativeFiles(config: Config, cordovaPlugins: Plugin[]) async function removePluginsNativeFiles(config: Config) { await remove(config.ios.cordovaPluginsDirAbs); + if ((await config.ios.packageManager) === 'SPM') { + await remove(join(config.ios.nativeProjectDirAbs, 'CapApp-SPM', 'symlinks')); + } await extractTemplate(config.cli.assets.ios.cordovaPluginsTemplateArchiveAbs, config.ios.cordovaPluginsDirAbs); } diff --git a/cli/src/util/spm.ts b/cli/src/util/spm.ts index 7d15787ce..2ef26bcda 100644 --- a/cli/src/util/spm.ts +++ b/cli/src/util/spm.ts @@ -1,4 +1,4 @@ -import { pathExists, existsSync, readFileSync, writeFileSync, remove, move, mkdtemp } from 'fs-extra'; +import { ensureSymlink, pathExists, existsSync, readFileSync, writeFileSync, remove, move, mkdtemp } from 'fs-extra'; import { tmpdir } from 'os'; import { join, relative, resolve } from 'path'; import type { PlistObject } from 'plist'; @@ -100,6 +100,7 @@ export async function generatePackageText(config: Config, plugins: Plugin[]): Pr const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name); const iosVersion = getMajoriOSVersion(config); const packageTraits = config.app.extConfig.experimental?.ios?.spm?.packageTraits ?? {}; + const packageOptions = config.app.extConfig.experimental?.ios?.spm?.packageOptions ?? {}; const swiftToolsVersion = config.app.extConfig.experimental?.ios?.spm?.swiftToolsVersion ?? '5.9'; let packageSwiftText = `// swift-tools-version: ${swiftToolsVersion} @@ -132,7 +133,13 @@ let package = Package( packageSwiftText += `,\n .package(name: "${plugin.name}", path: "../../capacitor-cordova-ios-plugins/sources/${plugin.name}")`; } } else { - const relPath = relative(config.ios.nativeXcodeProjDirAbs, plugin.rootPath); + const options = packageOptions[plugin.id]; + const symlink = options?.symlink; + const symlinkFolder = join('symlinks', plugin.name); + const relPath = symlink ? symlinkFolder : relative(config.ios.nativeXcodeProjDirAbs, plugin.rootPath); + if (symlink) { + await ensureSymlink(plugin.rootPath, resolve(config.ios.nativeProjectDirAbs, 'CapApp-SPM', symlinkFolder)); + } const traits = packageTraits[plugin.id]; const traitsSuffix = traits?.length ? `, traits: [${traits @@ -156,7 +163,15 @@ let package = Package( .product(name: "Cordova", package: "capacitor-swift-pm")`; for (const plugin of plugins) { - let pluginText = `,\n .product(name: "${plugin.ios?.name}", package: "${plugin.ios?.name}")`; + const aliases = Object.entries(packageOptions[plugin.id]?.moduleAliases ?? {}); + const aliasText = aliases?.length + ? `, moduleAliases: [${aliases + .map(([target, replacement]) => { + return `"${target}": "${replacement}"`; + }) + .join(', ')}]` + : ''; + let pluginText = `,\n .product(name: "${plugin.ios?.name}", package: "${plugin.ios?.name}"${aliasText})`; if (getPluginType(plugin, config.ios.name) === PluginType.Cordova) { const platformTag = getPluginPlatform(plugin, config.ios.name); if (platformTag.$?.package) { From b4b297a52f8732659662d5e5aaeff81c0f7d9835 Mon Sep 17 00:00:00 2001 From: "Alex J." Date: Wed, 27 May 2026 14:49:32 -0400 Subject: [PATCH 11/23] feat(cli): capture ios_package_manager in telemetry (#8482) --- cli/src/telemetry.ts | 25 +++++++++++++++- cli/test/telemetry.spec.ts | 60 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 cli/test/telemetry.spec.ts diff --git a/cli/src/telemetry.ts b/cli/src/telemetry.ts index 8e0d847ac..593397502 100644 --- a/cli/src/telemetry.ts +++ b/cli/src/telemetry.ts @@ -1,8 +1,9 @@ import { Command } from 'commander'; import Debug from 'debug'; +import { pathExists } from 'fs-extra'; import c from './colors'; -import type { Config } from './definitions'; +import type { Config, PackageManager } from './definitions'; import { send } from './ipc'; import { output } from './log'; import { readConfig, writeConfig } from './sysconfig'; @@ -26,6 +27,7 @@ export interface CommandMetricData { error: string | null; node_version: string; os: string; + ios_package_manager: PackageManager | 'unknown'; } export interface Metric { @@ -80,9 +82,12 @@ export function telemetryAction(config: Config, action: CommanderAction): Comman error: error ? (error.message ? error.message : String(error)) : null, node_version: process.version, os: config.cli.os, + ios_package_manager: await getIOSPackageManager(config), ...Object.fromEntries(versions), }; + debug('metric payload: %O', data); + if (isInteractive()) { let sysconfig = await readConfig(); @@ -126,6 +131,24 @@ export async function sendMetric( } } +/** + * Resolve the iOS dependency manager for telemetry. Returns 'unknown' for + * non-iOS projects or when detection throws, so callers never have to handle + * errors from this signal. + */ +export async function getIOSPackageManager(config: Config): Promise { + try { + if (!(await pathExists(config.ios.platformDirAbs))) { + return 'unknown'; + } + + return await config.ios.packageManager; + } catch (e) { + debug('Could not resolve iOS package manager for telemetry: %O', e); + return 'unknown'; + } +} + /** * Get a unique anonymous identifier for this app. */ diff --git a/cli/test/telemetry.spec.ts b/cli/test/telemetry.spec.ts new file mode 100644 index 000000000..412048527 --- /dev/null +++ b/cli/test/telemetry.spec.ts @@ -0,0 +1,60 @@ +import { pathExists } from 'fs-extra'; + +import type { Config, IOSConfig } from '../src/definitions'; +import { getIOSPackageManager } from '../src/telemetry'; + +jest.mock('fs-extra', () => ({ + pathExists: jest.fn(), +})); + +const mockedPathExists = pathExists as unknown as jest.Mock; + +function makeConfig(ios: Partial): Config { + return { ios } as unknown as Config; +} + +describe('getIOSPackageManager', () => { + beforeEach(() => { + mockedPathExists.mockReset(); + }); + + it('returns "unknown" when the iOS platform directory does not exist', async () => { + mockedPathExists.mockResolvedValueOnce(false); + + const result = await getIOSPackageManager( + makeConfig({ + platformDirAbs: '/tmp/no-such-dir/ios', + packageManager: Promise.resolve('SPM'), + }), + ); + + expect(result).toBe('unknown'); + expect(mockedPathExists).toHaveBeenCalledWith('/tmp/no-such-dir/ios'); + }); + + it('returns the resolved package manager when iOS is present', async () => { + mockedPathExists.mockResolvedValueOnce(true); + + const result = await getIOSPackageManager( + makeConfig({ + platformDirAbs: '/tmp/app/ios', + packageManager: Promise.resolve('SPM'), + }), + ); + + expect(result).toBe('SPM'); + }); + + it('returns "unknown" when packageManager resolution throws', async () => { + mockedPathExists.mockResolvedValueOnce(true); + + const result = await getIOSPackageManager( + makeConfig({ + platformDirAbs: '/tmp/app/ios', + packageManager: Promise.reject(new Error('boom')), + }), + ); + + expect(result).toBe('unknown'); + }); +}); From 1d031a4abec2c793079ba8897ad2e40c4cc6c7f9 Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Thu, 28 May 2026 15:00:43 +0200 Subject: [PATCH 12/23] fix(cli): revert live reload config on failure (#8485) --- cli/src/tasks/run.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/src/tasks/run.ts b/cli/src/tasks/run.ts index 2abdb9cd2..439c29209 100644 --- a/cli/src/tasks/run.ts +++ b/cli/src/tasks/run.ts @@ -116,6 +116,9 @@ export async function runCommand( await sleepForever(); } } catch (e: any) { + if (options.liveReload) { + await CapLiveReloadHelper.revertCapConfigForLiveReload(); + } if (!isFatal(e)) { fatal(e.stack ?? e); } From f1077ef9645b1ada2dd2635e3c3220612bdb4da6 Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Fri, 29 May 2026 11:02:23 +0200 Subject: [PATCH 13/23] chore: fix typo in declarations.ts (#8488) --- cli/src/declarations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/declarations.ts b/cli/src/declarations.ts index bda7ff0c0..1103b6585 100644 --- a/cli/src/declarations.ts +++ b/cli/src/declarations.ts @@ -604,7 +604,7 @@ export interface CapacitorConfig { * Configure the local scheme on Android. * * Custom schemes on Android are unable to change the URL path as of Webview 117. Changing this value from anything other than `http` or `https` can result in your - * application unable to resolve routing. If you must change this for some reason, consider using a hash-based url strategy, but there are no guarentees that this + * application unable to resolve routing. If you must change this for some reason, consider using a hash-based url strategy, but there are no guarantees that this * will continue to work long term as allowing non-standard schemes to modify query parameters and url fragments is only allowed for compatibility reasons. * https://ionic.io/blog/capacitor-android-customscheme-issue-with-chrome-117 * From d4ad7ffe39daf66e0cfc63af9028d5c05543bde7 Mon Sep 17 00:00:00 2001 From: Joey Pender Date: Mon, 1 Jun 2026 10:31:48 -0500 Subject: [PATCH 14/23] fix(SystemBars): respect `insetsHandling` disable (#8481) --- .../com/getcapacitor/plugin/SystemBars.java | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java index 76e74207c..29b76e2f2 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java @@ -16,6 +16,7 @@ import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsControllerCompat; import androidx.webkit.WebViewCompat; +import com.getcapacitor.Logger; import com.getcapacitor.Plugin; import com.getcapacitor.PluginCall; import com.getcapacitor.PluginMethod; @@ -32,6 +33,7 @@ public class SystemBars extends Plugin { static final String BAR_STATUS_BAR = "StatusBar"; static final String BAR_GESTURE_BAR = "NavigationBar"; + // TODO: In Cap 9, add an additional option "full" static final String INSETS_HANDLING_CSS = "css"; static final String INSETS_HANDLING_DISABLE = "disable"; @@ -53,7 +55,7 @@ function capacitorSystemBarsCheckMetaViewport() { capacitorSystemBarsCheckMetaViewport(); """; - private boolean insetHandlingEnabled = true; + private String insetsHandling = INSETS_HANDLING_CSS; private boolean hasViewportCover = false; private String currentStatusBarStyle = STYLE_DEFAULT; @@ -94,9 +96,15 @@ private void initSystemBars() { String style = getConfig().getString("style", STYLE_DEFAULT).toUpperCase(Locale.US); boolean hidden = getConfig().getBoolean("hidden", false); - String insetsHandling = getConfig().getString("insetsHandling", "css"); - if (insetsHandling.equals(INSETS_HANDLING_DISABLE)) { - insetHandlingEnabled = false; + 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; } initWindowInsetsListener(); @@ -146,13 +154,15 @@ public void setAnimation(final PluginCall call) { @JavascriptInterface public void onDOMReady() { - getActivity().runOnUiThread(() -> { - this.bridge.getWebView().evaluateJavascript(viewportMetaJSFunction, (res) -> { - hasViewportCover = res.equals("true"); + if (INSETS_HANDLING_CSS.equals(insetsHandling)) { + getActivity().runOnUiThread(() -> { + this.bridge.getWebView().evaluateJavascript(viewportMetaJSFunction, (res) -> { + hasViewportCover = res.equals("true"); - getBridge().getWebView().requestApplyInsets(); + getBridge().getWebView().requestApplyInsets(); + }); }); - }); + } } private Insets calcSafeAreaInsets(WindowInsetsCompat insets) { @@ -164,22 +174,28 @@ private Insets calcSafeAreaInsets(WindowInsetsCompat insets) { } private void initSafeAreaCSSVariables() { - WindowInsetsCompat insets; + if (INSETS_HANDLING_CSS.equals(insetsHandling)) { + WindowInsetsCompat insets; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { - View v = (View) this.getBridge().getWebView().getParent(); - insets = ViewCompat.getRootWindowInsets(v); - } else { - insets = WindowInsetsCompat.CONSUMED; - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { + View v = (View) this.getBridge().getWebView().getParent(); + insets = ViewCompat.getRootWindowInsets(v); + } else { + insets = WindowInsetsCompat.CONSUMED; + } - if (insets != null) { - Insets safeAreaInsets = calcSafeAreaInsets(insets); - injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); + if (insets != null) { + Insets safeAreaInsets = calcSafeAreaInsets(insets); + injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left); + } } } private void initWindowInsetsListener() { + if (INSETS_HANDLING_DISABLE.equals(insetsHandling)) { + return; + } + ViewCompat.setOnApplyWindowInsetsListener((View) getBridge().getWebView().getParent(), (v, insets) -> { boolean shouldPassthroughInsets = getWebViewMajorVersion() >= WEBVIEW_VERSION_WITH_SAFE_AREA_FIX && hasViewportCover; From 4c6c3219afb5223211e857457e46283c37eb9424 Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Mon, 1 Jun 2026 21:04:08 +0200 Subject: [PATCH 15/23] fix(android): show only the requested system bar (#8480) Co-authored-by: Joey Pender Co-authored-by: Pedro Bilro Co-authored-by: Mark Anderson --- .../com/getcapacitor/plugin/SystemBars.java | 14 ++-- .../getcapacitor/plugin/SystemBarsTest.java | 73 +++++++++++++++++++ 2 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 android/capacitor/src/test/java/com/getcapacitor/plugin/SystemBarsTest.java diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java index 29b76e2f2..fd7137094 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java @@ -304,19 +304,21 @@ private void setHidden(boolean hide, String bar) { WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.getInsetsController(window, window.getDecorView()); if (hide) { - if (bar.isEmpty() || bar.equals(BAR_STATUS_BAR)) { + if (bar.isEmpty()) { + windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.systemBars()); + } else if (bar.equals(BAR_STATUS_BAR)) { windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.statusBars()); - } - if (bar.isEmpty() || bar.equals(BAR_GESTURE_BAR)) { + } else if (bar.equals(BAR_GESTURE_BAR)) { windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.navigationBars()); } return; } - if (bar.isEmpty() || bar.equals(BAR_STATUS_BAR)) { + if (bar.isEmpty()) { windowInsetsControllerCompat.show(WindowInsetsCompat.Type.systemBars()); - } - if (bar.isEmpty() || bar.equals(BAR_GESTURE_BAR)) { + } else if (bar.equals(BAR_STATUS_BAR)) { + windowInsetsControllerCompat.show(WindowInsetsCompat.Type.statusBars()); + } else if (bar.equals(BAR_GESTURE_BAR)) { windowInsetsControllerCompat.show(WindowInsetsCompat.Type.navigationBars()); } } diff --git a/android/capacitor/src/test/java/com/getcapacitor/plugin/SystemBarsTest.java b/android/capacitor/src/test/java/com/getcapacitor/plugin/SystemBarsTest.java new file mode 100644 index 000000000..f72373a88 --- /dev/null +++ b/android/capacitor/src/test/java/com/getcapacitor/plugin/SystemBarsTest.java @@ -0,0 +1,73 @@ +package com.getcapacitor.plugin; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.view.View; +import android.view.Window; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.core.view.WindowInsetsControllerCompat; +import com.getcapacitor.Bridge; +import java.lang.reflect.Method; +import org.junit.Test; +import org.mockito.MockedStatic; + +public class SystemBarsTest { + + @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 = 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; + } +} From 36b729d10380687bf5eab2cfa8affcbd1655541b Mon Sep 17 00:00:00 2001 From: Mark Anderson Date: Mon, 1 Jun 2026 15:11:51 -0400 Subject: [PATCH 16/23] chore: Decrease timeout for CI jobs from 60 to 30 minutes (#8476) Co-authored-by: jcesarmobile --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8664a402d..56fce5389 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ concurrency: jobs: setup: runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 30 steps: - name: Get Latest uses: actions/setup-node@v6 @@ -32,7 +32,7 @@ jobs: key: ${{ runner.OS }}-dependencies-cache-${{ hashFiles('**/package.json') }} lint: runs-on: macos-15 - timeout-minutes: 60 + timeout-minutes: 30 steps: - uses: actions/setup-node@v6 with: @@ -48,7 +48,7 @@ jobs: - run: npm run lint test-cli: runs-on: macos-15 - timeout-minutes: 60 + timeout-minutes: 30 needs: - setup - lint @@ -69,7 +69,7 @@ jobs: working-directory: ./cli test-core: runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 30 needs: - setup - lint @@ -90,7 +90,7 @@ jobs: working-directory: ./core test-ios: runs-on: macos-15 - timeout-minutes: 60 + timeout-minutes: 30 needs: - setup - lint @@ -118,7 +118,7 @@ jobs: run: sh ./scripts/native-podspec.sh lint test-android: runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 30 needs: - setup - lint From 41fd9deb6df07ef83ae390d16824e8bcbefef517 Mon Sep 17 00:00:00 2001 From: "Github Workflow (on behalf of markemer)" Date: Tue, 2 Jun 2026 15:56:03 +0000 Subject: [PATCH 17/23] Release 8.4.0 --- CHANGELOG.md | 15 +++++++++++++++ android/CHANGELOG.md | 12 ++++++++++++ android/package.json | 4 ++-- cli/CHANGELOG.md | 11 +++++++++++ cli/package.json | 2 +- core/CHANGELOG.md | 4 ++++ core/package.json | 2 +- ios/CHANGELOG.md | 6 ++++++ ios/package.json | 4 ++-- lerna.json | 2 +- 10 files changed, 55 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7f2b7713..cd4fe5f5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,21 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [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 diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index 74d538d9f..df7ce545e 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [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)) + ## [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/android diff --git a/android/package.json b/android/package.json index 8ae93f3f2..af3f4f556 100644 --- a/android/package.json +++ b/android/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/android", - "version": "8.3.4", + "version": "8.4.0", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", @@ -23,7 +23,7 @@ "verify": "./gradlew clean lint build test -b capacitor/build.gradle" }, "peerDependencies": { - "@capacitor/core": "^8.3.0" + "@capacitor/core": "^8.4.0" }, "publishConfig": { "access": "public" diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index bba24688f..ee48a8d5f 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [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)) + ## [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/cli diff --git a/cli/package.json b/cli/package.json index 9df346b14..1f987d33a 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/cli", - "version": "8.3.4", + "version": "8.4.0", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 017293794..1de9522ff 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) + +**Note:** Version bump only for package @capacitor/core + ## [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/core diff --git a/core/package.json b/core/package.json index eef113a50..b22aef174 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/core", - "version": "8.3.4", + "version": "8.4.0", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md index 87ee73bb4..eac0a4a1c 100644 --- a/ios/CHANGELOG.md +++ b/ios/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) + +### 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.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/ios diff --git a/ios/package.json b/ios/package.json index a7b8d3133..a58c02090 100644 --- a/ios/package.json +++ b/ios/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/ios", - "version": "8.3.4", + "version": "8.4.0", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", @@ -25,7 +25,7 @@ "xc:build:CapacitorCordova": "cd CapacitorCordova && xcodebuild && cd .." }, "peerDependencies": { - "@capacitor/core": "^8.3.0" + "@capacitor/core": "^8.4.0" }, "publishConfig": { "access": "public" diff --git a/lerna.json b/lerna.json index 1e53d6bdc..b2efb400d 100644 --- a/lerna.json +++ b/lerna.json @@ -11,6 +11,6 @@ "tagVersionPrefix": "" } }, - "version": "8.3.4", + "version": "8.4.0", "$schema": "node_modules/lerna/schemas/lerna-schema.json" } From 28bb2c687069dfdd6aa7abc866004a1c6388d103 Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Tue, 2 Jun 2026 21:31:41 +0200 Subject: [PATCH 18/23] fix(cli): patch Capacitor SPM dependency version in plugins (#8492) Co-authored-by: Mark Anderson --- cli/src/ios/update.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/cli/src/ios/update.ts b/cli/src/ios/update.ts index b060e59a8..1f4bc87d0 100644 --- a/cli/src/ios/update.ts +++ b/cli/src/ios/update.ts @@ -1,5 +1,6 @@ import { copy, remove, pathExists, readFile, realpath, writeFile } from 'fs-extra'; import { basename, dirname, join, relative } from 'path'; +import { major } from 'semver'; import c from '../colors'; import { checkPlatformVersions, getCapacitorPackageVersion, runTask } from '../common'; @@ -58,6 +59,28 @@ async function updatePluginFiles(config: Config, plugins: Plugin[], deployment: await generateCordovaPackageFiles(cordovaPlugins, config); const validSPMPackages = await checkPluginsForPackageSwift(config, plugins); + 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) { + content = setAllStringIn( + content, + `url: "https://github.com/ionic-team/capacitor-swift-pm.git",`, + `)`, + ` from: "${majorCapVersion}.0.0"`, + ); + await writeFile(packageSwiftPath, content); + logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`); + } + }), + ); await generatePackageFile(config, validSPMPackages.concat(cordovaPlugins)); } else { From 6048e90171afa0229a3c25b52a23c377c6bb804c Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Mon, 15 Jun 2026 12:11:19 +0200 Subject: [PATCH 19/23] fix(cli): make SPM dependency patch work on prereleases (#8508) --- cli/src/ios/update.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cli/src/ios/update.ts b/cli/src/ios/update.ts index 1f4bc87d0..3ab793c25 100644 --- a/cli/src/ios/update.ts +++ b/cli/src/ios/update.ts @@ -1,6 +1,6 @@ import { copy, remove, pathExists, readFile, realpath, writeFile } from 'fs-extra'; import { basename, dirname, join, relative } from 'path'; -import { major } from 'semver'; +import { major, prerelease } from 'semver'; import c from '../colors'; import { checkPlatformVersions, getCapacitorPackageVersion, runTask } from '../common'; @@ -70,11 +70,13 @@ async function updatePluginFiles(config: Config, plugins: Plugin[], deployment: 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: "${majorCapVersion}.0.0"`, + ` from: "${forceVersion}"`, ); await writeFile(packageSwiftPath, content); logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`); From 7217b5215a175eededf607a216e0cab2a8450a34 Mon Sep 17 00:00:00 2001 From: "Github Workflow (on behalf of jcesarmobile)" Date: Fri, 19 Jun 2026 09:01:59 +0000 Subject: [PATCH 20/23] Release 8.4.1 --- CHANGELOG.md | 7 +++++++ android/CHANGELOG.md | 4 ++++ android/package.json | 2 +- cli/CHANGELOG.md | 7 +++++++ cli/package.json | 2 +- core/CHANGELOG.md | 4 ++++ core/package.json | 2 +- ios/CHANGELOG.md | 4 ++++ ios/package.json | 2 +- lerna.json | 2 +- 10 files changed, 31 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd4fe5f5a..db3954562 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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 diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index df7ce545e..5bc9de9f6 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.4.1](https://github.com/ionic-team/capacitor/compare/8.4.0...8.4.1) (2026-06-19) + +**Note:** Version bump only for package @capacitor/android + # [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) ### Bug Fixes diff --git a/android/package.json b/android/package.json index af3f4f556..7354f3b2c 100644 --- a/android/package.json +++ b/android/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/android", - "version": "8.4.0", + "version": "8.4.1", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index ee48a8d5f..df61fcbaa 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [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 diff --git a/cli/package.json b/cli/package.json index 1f987d33a..7a77d11e9 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/cli", - "version": "8.4.0", + "version": "8.4.1", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 1de9522ff..1003c8ceb 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.4.1](https://github.com/ionic-team/capacitor/compare/8.4.0...8.4.1) (2026-06-19) + +**Note:** Version bump only for package @capacitor/core + # [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) **Note:** Version bump only for package @capacitor/core diff --git a/core/package.json b/core/package.json index b22aef174..f821cfd9d 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/core", - "version": "8.4.0", + "version": "8.4.1", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md index eac0a4a1c..dfcf383ff 100644 --- a/ios/CHANGELOG.md +++ b/ios/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.4.1](https://github.com/ionic-team/capacitor/compare/8.4.0...8.4.1) (2026-06-19) + +**Note:** Version bump only for package @capacitor/ios + # [8.4.0](https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0) (2026-06-02) ### Features diff --git a/ios/package.json b/ios/package.json index a58c02090..a6a78c23d 100644 --- a/ios/package.json +++ b/ios/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/ios", - "version": "8.4.0", + "version": "8.4.1", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitorjs.com", "author": "Ionic Team (https://ionic.io)", diff --git a/lerna.json b/lerna.json index b2efb400d..be3666942 100644 --- a/lerna.json +++ b/lerna.json @@ -11,6 +11,6 @@ "tagVersionPrefix": "" } }, - "version": "8.4.0", + "version": "8.4.1", "$schema": "node_modules/lerna/schemas/lerna-schema.json" } From b789b683f04863e65c66d630890f00561c0d5b7a Mon Sep 17 00:00:00 2001 From: Mark Anderson Date: Mon, 22 Jun 2026 15:42:23 -0400 Subject: [PATCH 21/23] chore: run `npm run fmt` to fix lint errors (#8516) --- .../java/com/getcapacitor/BridgeWebChromeClient.java | 4 ++-- .../src/main/java/com/getcapacitor/FileUtils.java | 2 +- .../java/com/getcapacitor/WebViewLocalServer.java | 12 ++++++------ .../getcapacitor/plugin/CapacitorCookieManager.java | 6 +++--- .../getcapacitor/plugin/util/HttpRequestHandler.java | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java b/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java index 6ca1c8a83..ec7867369 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java +++ b/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java @@ -282,7 +282,7 @@ public boolean onShowFileChooser( boolean captureEnabled = fileChooserParams.isCaptureEnabled(); boolean capturePhoto = captureEnabled && acceptTypes.contains("image/*"); final boolean captureVideo = captureEnabled && acceptTypes.contains("video/*"); - if ((capturePhoto || captureVideo)) { + if (capturePhoto || captureVideo) { if (isMediaCaptureSupported()) { showMediaCaptureOrFilePicker(filePathCallback, fileChooserParams, captureVideo); } else { @@ -447,7 +447,7 @@ public boolean onConsoleMessage(ConsoleMessage consoleMessage) { } public boolean isValidMsg(String msg) { - return !(msg.contains("%cresult %c") || (msg.contains("%cnative %c")) || msg.equalsIgnoreCase("console.groupEnd")); + return !(msg.contains("%cresult %c") || msg.contains("%cnative %c") || msg.equalsIgnoreCase("console.groupEnd")); } private Uri createImageFileUri() throws IOException { diff --git a/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java b/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java index ce09e7c2f..cec171946 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java +++ b/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java @@ -218,7 +218,7 @@ private static String getCopyFilePath(Uri uri, Context context) { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); cursor.moveToFirst(); - String name = (cursor.getString(nameIndex)); + String name = cursor.getString(nameIndex); String fileName = sanitizeFilename(name); File file = new File(context.getFilesDir(), fileName); try { diff --git a/android/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java b/android/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java index a39483de9..0c5480079 100755 --- a/android/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java +++ b/android/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java @@ -221,7 +221,7 @@ private boolean isErrorUrl(Uri uri) { } private boolean isMainUrl(Uri loadingUrl) { - return (bridge.getServerUrl() == null && loadingUrl.getHost().equalsIgnoreCase(bridge.getHost())); + return bridge.getServerUrl() == null && loadingUrl.getHost().equalsIgnoreCase(bridge.getHost()); } private boolean isAllowedUrl(Uri loadingUrl) { @@ -722,31 +722,31 @@ private InputStream getInputStream() { @Override public int available() throws IOException { InputStream is = getInputStream(); - return (is != null) ? is.available() : -1; + return is != null ? is.available() : -1; } @Override public int read() throws IOException { InputStream is = getInputStream(); - return (is != null) ? is.read() : -1; + return is != null ? is.read() : -1; } @Override public int read(byte[] b) throws IOException { InputStream is = getInputStream(); - return (is != null) ? is.read(b) : -1; + return is != null ? is.read(b) : -1; } @Override public int read(byte[] b, int off, int len) throws IOException { InputStream is = getInputStream(); - return (is != null) ? is.read(b, off, len) : -1; + return is != null ? is.read(b, off, len) : -1; } @Override public long skip(long n) throws IOException { InputStream is = getInputStream(); - return (is != null) ? is.skip(n) : 0; + return is != null ? is.skip(n) : 0; } } diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookieManager.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookieManager.java index cf4ab6326..472323bbc 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookieManager.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookieManager.java @@ -192,12 +192,12 @@ public void flush() { @Override public void put(URI uri, Map> responseHeaders) { // make sure our args are valid - if ((uri == null) || (responseHeaders == null)) return; + if (uri == null || responseHeaders == null) return; // go over the headers for (String headerKey : responseHeaders.keySet()) { // ignore headers which aren't cookie related - if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue; + if (headerKey == null || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue; // process each of the headers for (String headerValue : Objects.requireNonNull(responseHeaders.get(headerKey))) { @@ -215,7 +215,7 @@ public void put(URI uri, Map> responseHeaders) { @Override public Map> get(URI uri, Map> requestHeaders) { // make sure our args are valid - if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null"); + if (uri == null || requestHeaders == null) throw new IllegalArgumentException("Argument is null"); // save our url once String url = uri.toString(); diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java index b47d57cf1..69278bc63 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java @@ -168,8 +168,8 @@ public HttpURLConnectionBuilder setUrlParams(JSObject params, boolean shouldEnco "://" + uri.getAuthority() + uri.getPath() + - ((!urlQuery.equals("")) ? "?" + urlQuery : "") + - ((uri.getFragment() != null) ? uri.getFragment() : ""); + (!urlQuery.equals("") ? "?" + urlQuery : "") + + (uri.getFragment() != null ? uri.getFragment() : ""); this.url = new URL(unEncodedUrlString); return this; From 6f2d3283897a375d09ca9ec8784a9f0d65f0a530 Mon Sep 17 00:00:00 2001 From: "Alex J." Date: Wed, 8 Jul 2026 10:35:37 -0400 Subject: [PATCH 22/23] fix(android): explicitly grant URI permissions for image capture intent (#8526) --- .../src/main/java/com/getcapacitor/BridgeWebChromeClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java b/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java index ec7867369..34fa2d834 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java +++ b/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java @@ -340,6 +340,7 @@ private boolean showImageCapturePicker(final ValueCallback filePathCallba return false; } takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri); + takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); activityListener = (activityResult) -> { Uri[] result = null; if (activityResult.getResultCode() == Activity.RESULT_OK) { From 88eb69f70892e27901e346f768e30fe47223400d Mon Sep 17 00:00:00 2001 From: Nils Peper Date: Fri, 10 Jul 2026 11:32:22 +0200 Subject: [PATCH 23/23] fix(ios): adopt UIScene life cycle in default iOS app templates 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> --- .../App/App.xcodeproj/project.pbxproj | 4 ++ ios-pods-template/App/App/AppDelegate.swift | 16 +++++++ ios-pods-template/App/App/Info.plist | 19 ++++++++ ios-pods-template/App/App/SceneDelegate.swift | 46 +++++++++++++++++++ .../App/App.xcodeproj/project.pbxproj | 4 ++ ios-spm-template/App/App/AppDelegate.swift | 16 +++++++ ios-spm-template/App/App/Info.plist | 19 ++++++++ ios-spm-template/App/App/SceneDelegate.swift | 46 +++++++++++++++++++ 8 files changed, 170 insertions(+) create mode 100644 ios-pods-template/App/App/SceneDelegate.swift create mode 100644 ios-spm-template/App/App/SceneDelegate.swift diff --git a/ios-pods-template/App/App.xcodeproj/project.pbxproj b/ios-pods-template/App/App.xcodeproj/project.pbxproj index 092f57491..c7e83d217 100644 --- a/ios-pods-template/App/App.xcodeproj/project.pbxproj +++ b/ios-pods-template/App/App.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; + 2C6EFDE1674F365EA0601FC0 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6197F4D7F73A0E1131CB2963 /* SceneDelegate.swift */; }; 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; @@ -22,6 +23,7 @@ 50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = ""; }; 504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; 504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 6197F4D7F73A0E1131CB2963 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; @@ -75,6 +77,7 @@ children = ( 50379B222058CBB4000EE86E /* capacitor.config.json */, 504EC3071FED79650016851F /* AppDelegate.swift */, + 6197F4D7F73A0E1131CB2963 /* SceneDelegate.swift */, 504EC30B1FED79650016851F /* Main.storyboard */, 504EC30E1FED79650016851F /* Assets.xcassets */, 504EC3101FED79650016851F /* LaunchScreen.storyboard */, @@ -210,6 +213,7 @@ buildActionMask = 2147483647; files = ( 504EC3081FED79650016851F /* AppDelegate.swift in Sources */, + 2C6EFDE1674F365EA0601FC0 /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios-pods-template/App/App/AppDelegate.swift b/ios-pods-template/App/App/AppDelegate.swift index c3cd83b5c..5315e07ba 100644 --- a/ios-pods-template/App/App/AppDelegate.swift +++ b/ios-pods-template/App/App/AppDelegate.swift @@ -46,4 +46,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) } + // MARK: UIScene life cycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called + // shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they + // will not return. + } + } diff --git a/ios-pods-template/App/App/Info.plist b/ios-pods-template/App/App/Info.plist index ed6ff0bd4..599741e62 100644 --- a/ios-pods-template/App/App/Info.plist +++ b/ios-pods-template/App/App/Info.plist @@ -22,6 +22,25 @@ $(CURRENT_PROJECT_VERSION) LSRequiresIPhoneOS + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/ios-pods-template/App/App/SceneDelegate.swift b/ios-pods-template/App/App/SceneDelegate.swift new file mode 100644 index 000000000..7e0600f50 --- /dev/null +++ b/ios-pods-template/App/App/SceneDelegate.swift @@ -0,0 +1,46 @@ +import UIKit + +/// Adopts the UIWindowScene-based life cycle required by newer iOS SDKs (see the +/// `UIApplicationSceneManifest` entry in Info.plist). Without this class and the +/// corresponding manifest entry, apps built with a scene-lifecycle-requiring SDK +/// fail to launch (UIKit logs "UIScene life cycle is required for apps built with +/// this SDK") even though no crash log is produced. +/// +/// See: https://developer.apple.com/documentation/technotes/tn3187-migrating-to-the-uikit-scene-based-life-cycle +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // The root view controller (CAPBridgeViewController, via Main.storyboard) is configured + // automatically from UISceneStoryboardFile in Info.plist, so no manual window/root view + // controller setup is required here. + guard scene is UIWindowScene else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific + // state information to restore the scene back to its current state. + } +} diff --git a/ios-spm-template/App/App.xcodeproj/project.pbxproj b/ios-spm-template/App/App.xcodeproj/project.pbxproj index 46f934efd..f2d5dc1ed 100644 --- a/ios-spm-template/App/App.xcodeproj/project.pbxproj +++ b/ios-spm-template/App/App.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */ = {isa = PBXBuildFile; productRef = 4D22ABE82AF431CB00220026 /* CapApp-SPM */; }; 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; + 785D74E6F5C248B56B0A9CF9 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A43193715767FB78F37E3E9 /* SceneDelegate.swift */; }; 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; @@ -22,6 +23,7 @@ 50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = ""; }; 504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; 504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 8A43193715767FB78F37E3E9 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; @@ -64,6 +66,7 @@ children = ( 50379B222058CBB4000EE86E /* capacitor.config.json */, 504EC3071FED79650016851F /* AppDelegate.swift */, + 8A43193715767FB78F37E3E9 /* SceneDelegate.swift */, 504EC30B1FED79650016851F /* Main.storyboard */, 504EC30E1FED79650016851F /* Assets.xcassets */, 504EC3101FED79650016851F /* LaunchScreen.storyboard */, @@ -156,6 +159,7 @@ buildActionMask = 2147483647; files = ( 504EC3081FED79650016851F /* AppDelegate.swift in Sources */, + 785D74E6F5C248B56B0A9CF9 /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios-spm-template/App/App/AppDelegate.swift b/ios-spm-template/App/App/AppDelegate.swift index c3cd83b5c..5315e07ba 100644 --- a/ios-spm-template/App/App/AppDelegate.swift +++ b/ios-spm-template/App/App/AppDelegate.swift @@ -46,4 +46,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) } + // MARK: UIScene life cycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called + // shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they + // will not return. + } + } diff --git a/ios-spm-template/App/App/Info.plist b/ios-spm-template/App/App/Info.plist index 42bcf6750..5f1dce67a 100644 --- a/ios-spm-template/App/App/Info.plist +++ b/ios-spm-template/App/App/Info.plist @@ -24,6 +24,25 @@ $(CURRENT_PROJECT_VERSION) LSRequiresIPhoneOS + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/ios-spm-template/App/App/SceneDelegate.swift b/ios-spm-template/App/App/SceneDelegate.swift new file mode 100644 index 000000000..7e0600f50 --- /dev/null +++ b/ios-spm-template/App/App/SceneDelegate.swift @@ -0,0 +1,46 @@ +import UIKit + +/// Adopts the UIWindowScene-based life cycle required by newer iOS SDKs (see the +/// `UIApplicationSceneManifest` entry in Info.plist). Without this class and the +/// corresponding manifest entry, apps built with a scene-lifecycle-requiring SDK +/// fail to launch (UIKit logs "UIScene life cycle is required for apps built with +/// this SDK") even though no crash log is produced. +/// +/// See: https://developer.apple.com/documentation/technotes/tn3187-migrating-to-the-uikit-scene-based-life-cycle +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // The root view controller (CAPBridgeViewController, via Main.storyboard) is configured + // automatically from UISceneStoryboardFile in Info.plist, so no manual window/root view + // controller setup is required here. + guard scene is UIWindowScene else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific + // state information to restore the scene back to its current state. + } +}