From db2eb3a189b78a28af4c4cb035805f4d05642a96 Mon Sep 17 00:00:00 2001 From: vadymv-mendix Date: Thu, 5 Feb 2026 13:57:05 +0100 Subject: [PATCH 1/7] chore: bump pnpm version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6236b9c05..e5461d2d7 100644 --- a/package.json +++ b/package.json @@ -102,5 +102,5 @@ "react-native-snap-carousel@3.9.1": "patches/react-native-snap-carousel+3.9.1.patch" } }, - "packageManager": "pnpm@10.13.1" + "packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264" } From 5750a941dcc751505e367fa4ae537a6d33fd8e72 Mon Sep 17 00:00:00 2001 From: vadymv-mendix Date: Thu, 5 Feb 2026 14:13:34 +0100 Subject: [PATCH 2/7] fix(ci): build all widgets when JS actions change to fix test failures Changes: - Add `widgets_to_test` output separate from `widgets` (build vs test) - Add `js_actions_changed` flag for cleaner conditional logic - When only JS actions change: build all widgets, skip widget tests - Update workflow to use new outputs for test matrix and conditions - Add README.md documenting script behavior and outputs --- .github/scripts/README.md | 43 ++++++++++++++++++++ .github/scripts/determine-widget-scope.sh | 46 ++++++++++++++++----- .github/workflows/NativePipeline.yml | 49 ++++++++++++----------- 3 files changed, 104 insertions(+), 34 deletions(-) create mode 100644 .github/scripts/README.md diff --git a/.github/scripts/README.md b/.github/scripts/README.md new file mode 100644 index 000000000..04ec4206a --- /dev/null +++ b/.github/scripts/README.md @@ -0,0 +1,43 @@ +# GitHub Actions Scripts + +This directory contains helper scripts used by the CI/CD pipeline. + +## determine-widget-scope.sh + +Determines which widgets and JS actions should be built and tested based on changed files or manual input. + +### Usage + +```bash +./determine-widget-scope.sh +``` + +### Outputs + +| Output | Description | +| -------------------- | ---------------------------------------------------- | +| `scope` | pnpm filter scope for building | +| `widgets` | JSON array of widgets to BUILD | +| `widgets_to_test` | JSON array of widgets to TEST (used for test matrix) | +| `js_actions_changed` | Boolean flag indicating if JS actions changed | + +### Pipeline Behavior + +| Scenario | Widgets Built | Widgets Tested | JS Actions Built | JS Actions Tested | +| ---------------------- | --------------- | --------------- | ---------------- | ----------------- | +| Only JS actions change | All | None | Yes | Yes | +| Only widgets change | Changed only | Changed only | No | No | +| Both change | Changed widgets | Changed widgets | Yes | Yes | +| Full run (`*-native`) | All | All | Yes | Yes | +| Manual: `js-actions` | All | None | Yes | Yes | + +### Why build all widgets when only JS actions change? + +The JS action tests run against a full test project that requires all widgets to be present. Without building all widgets, the test project would be incomplete and tests would fail. + +## Other Scripts + +- **determine-nt-version.py** - Determines the Native Template version based on Mendix version +- **mxbuild.Dockerfile** - Docker image for mxbuild +- **setup-runtime.sh** - Sets up the Mendix runtime +- **start-runtime-with-verification.sh** - Starts the runtime with health verification diff --git a/.github/scripts/determine-widget-scope.sh b/.github/scripts/determine-widget-scope.sh index 2070918a2..4983cd507 100644 --- a/.github/scripts/determine-widget-scope.sh +++ b/.github/scripts/determine-widget-scope.sh @@ -44,39 +44,65 @@ if [ "$event_name" == "pull_request" ]; then selected_workspaces=$(echo $selected_workspaces | xargs) # Build the final scope and widgets output + # Note: widgets output is used for both BUILDING and the widget TEST MATRIX + # When only JS actions change, widgets_to_test is empty (no widget tests needed) + # but we still need to build all widgets for the test project if [[ -n "$selected_workspaces" ]] && [[ "$js_actions_changed" == "true" ]]; then # Both widgets and JS actions changed # Convert space-separated widget names to JSON array format widget_array=$(echo "$selected_workspaces" | sed 's/ /","/g') echo "scope=--all --include '$selected_workspaces mobile-resources-native nanoflow-actions-native'" >> $GITHUB_OUTPUT - echo "widgets=[\"$widget_array\",\"mobile-resources-native\",\"nanoflow-actions-native\"]" >> $GITHUB_OUTPUT + echo "widgets=[\"$widget_array\"]" >> $GITHUB_OUTPUT + echo "widgets_to_test=[\"$widget_array\"]" >> $GITHUB_OUTPUT + echo "js_actions_changed=true" >> $GITHUB_OUTPUT elif [[ -n "$selected_workspaces" ]] && [[ "$js_actions_changed" == "false" ]]; then # Only widgets changed widget_array=$(echo "$selected_workspaces" | sed 's/ /","/g') echo "scope=--all --include '$selected_workspaces'" >> $GITHUB_OUTPUT echo "widgets=[\"$widget_array\"]" >> $GITHUB_OUTPUT + echo "widgets_to_test=[\"$widget_array\"]" >> $GITHUB_OUTPUT + echo "js_actions_changed=false" >> $GITHUB_OUTPUT elif [[ -z "$selected_workspaces" ]] && [[ "$js_actions_changed" == "true" ]]; then - # Only JS actions changed - echo "scope=--all --include 'mobile-resources-native nanoflow-actions-native'" >> $GITHUB_OUTPUT - echo "widgets=[\"mobile-resources-native\",\"nanoflow-actions-native\"]" >> $GITHUB_OUTPUT + # Only JS actions changed - need to build ALL widgets because JS action tests + # require the full test project with all widgets to function properly + # But widget tests should NOT run (empty widgets_to_test) + echo "scope=--all --include '*-native mobile-resources-native nanoflow-actions-native'" >> $GITHUB_OUTPUT + echo "widgets=${all_widgets}" >> $GITHUB_OUTPUT + echo "widgets_to_test=[]" >> $GITHUB_OUTPUT + echo "js_actions_changed=true" >> $GITHUB_OUTPUT else # No specific changes detected in widgets or JS actions, run everything echo "scope=--all --include '*-native mobile-resources-native nanoflow-actions-native'" >> $GITHUB_OUTPUT - echo "widgets=${all_widgets_and_js}" >> $GITHUB_OUTPUT + echo "widgets=${all_widgets}" >> $GITHUB_OUTPUT + echo "widgets_to_test=${all_widgets}" >> $GITHUB_OUTPUT + echo "js_actions_changed=true" >> $GITHUB_OUTPUT fi else if [ -n "$input_workspace" ] && [ "$input_workspace" != "*-native" ] && [ "$input_workspace" != "js-actions" ]; then + # Specific widget(s) selected selected_workspaces=$(echo "$input_workspace" | sed 's/,/ /g') echo "scope=--all --include '${selected_workspaces}'" >> $GITHUB_OUTPUT echo "widgets=[\"$input_workspace\"]" >> $GITHUB_OUTPUT + echo "widgets_to_test=[\"$input_workspace\"]" >> $GITHUB_OUTPUT + echo "js_actions_changed=false" >> $GITHUB_OUTPUT elif [ "$input_workspace" == "js-actions" ]; then - echo "scope=--all --include 'mobile-resources-native nanoflow-actions-native'" >> $GITHUB_OUTPUT - echo "widgets=[\"mobile-resources-native\",\"nanoflow-actions-native\"]" >> $GITHUB_OUTPUT + # JS actions selected - need to build ALL widgets because JS action tests + # require the full test project with all widgets to function properly + # But widget tests should NOT run (empty widgets_to_test) + echo "scope=--all --include '*-native mobile-resources-native nanoflow-actions-native'" >> $GITHUB_OUTPUT + echo "widgets=${all_widgets}" >> $GITHUB_OUTPUT + echo "widgets_to_test=[]" >> $GITHUB_OUTPUT + echo "js_actions_changed=true" >> $GITHUB_OUTPUT else + # All widgets (*-native) or default - run everything echo "scope=--all --include '*-native mobile-resources-native nanoflow-actions-native'" >> $GITHUB_OUTPUT - echo "widgets=${all_widgets_and_js}" >> $GITHUB_OUTPUT + echo "widgets=${all_widgets}" >> $GITHUB_OUTPUT + echo "widgets_to_test=${all_widgets}" >> $GITHUB_OUTPUT + echo "js_actions_changed=true" >> $GITHUB_OUTPUT fi fi -echo "Determined scope: $(cat $GITHUB_OUTPUT | grep scope= | cut -d= -f2)" -echo "Widgets: $(cat $GITHUB_OUTPUT | grep widgets= | cut -d= -f2)" \ No newline at end of file +echo "Determined scope: $(cat $GITHUB_OUTPUT | grep 'scope=' | cut -d= -f2)" +echo "Widgets to build: $(cat $GITHUB_OUTPUT | grep '^widgets=' | cut -d= -f2)" +echo "Widgets to test: $(cat $GITHUB_OUTPUT | grep 'widgets_to_test=' | cut -d= -f2)" +echo "JS actions changed: $(cat $GITHUB_OUTPUT | grep 'js_actions_changed=' | cut -d= -f2)" \ No newline at end of file diff --git a/.github/workflows/NativePipeline.yml b/.github/workflows/NativePipeline.yml index 1e1f45e19..bcb3c16be 100644 --- a/.github/workflows/NativePipeline.yml +++ b/.github/workflows/NativePipeline.yml @@ -88,6 +88,8 @@ jobs: outputs: scope: ${{ steps.scope.outputs.scope }} widgets: ${{ steps.scope.outputs.widgets }} + widgets_to_test: ${{ steps.scope.outputs.widgets_to_test }} + js_actions_changed: ${{ steps.scope.outputs.js_actions_changed }} steps: - name: "Check out code" uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -101,7 +103,9 @@ jobs: - name: "Debug Scope Output" run: | echo "Scope is: ${{ steps.scope.outputs.scope }}" - echo "Widgets or js actions are: ${{ steps.scope.outputs.widgets }}" + echo "Widgets to build: ${{ steps.scope.outputs.widgets }}" + echo "Widgets to test: ${{ steps.scope.outputs.widgets_to_test }}" + echo "JS actions changed: ${{ steps.scope.outputs.js_actions_changed }}" mendix-version: runs-on: ubuntu-24.04 outputs: @@ -215,23 +219,20 @@ jobs: run: pnpm install --frozen-lockfile - name: "Force rebuild resources" run: | - # Build JS actions if needed - if [ "${{ github.event.inputs.workspace }}" = "js-actions" ] || \ + # Build JS actions if needed (when js_actions_changed is true OR when workspace explicitly includes them) + if [ "${{ needs.scope.outputs.js_actions_changed }}" = "true" ] || \ + [ "${{ github.event.inputs.workspace }}" = "js-actions" ] || \ [ "${{ github.event.inputs.workspace }}" = "*-native" ] || \ [ "${{ github.event_name }}" = "schedule" ]; then pnpm --filter=mobile-resources-native run build pnpm --filter=nanoflow-actions-native run build fi - # Build widgets if needed (any specific widget, *-native, or nightly) - if [ "${{ github.event.inputs.workspace }}" != "js-actions" ] || \ - [ "${{ github.event.inputs.workspace }}" = "*-native" ] || \ - [ "${{ github.event_name }}" = "schedule" ]; then - widgets=$(echo '${{ needs.scope.outputs.widgets }}' | jq -r '.[]') - for w in $widgets; do - pnpm --filter=$w run build - done - fi + # Build widgets from scope + widgets=$(echo '${{ needs.scope.outputs.widgets }}' | jq -r '.[]') + for w in $widgets; do + pnpm --filter=$w run build + done - name: "Unit test" run: pnpm -r --filter="${{ needs.scope.outputs.scope }}" run test - name: "Upload JS actions resources artifact" @@ -487,14 +488,14 @@ jobs: android-widget-tests: needs: [scope, mendix-version, project, android-app] - # Run if project succeeds and either android-app succeeds OR we're using custom artifacts (android-app was skipped) - if: ${{ (github.event.inputs.workspace != 'js-actions' || github.event_name == 'schedule') && always() && needs.project.result == 'success' && (needs.android-app.result == 'success' || needs.android-app.result == 'skipped') }} + # Run if widgets need testing (widgets_to_test is not empty) and project succeeds + if: ${{ needs.scope.outputs.widgets_to_test != '[]' && always() && needs.project.result == 'success' && (needs.android-app.result == 'success' || needs.android-app.result == 'skipped') }} runs-on: ubuntu-24.04 timeout-minutes: 60 strategy: max-parallel: 5 matrix: - widget: ${{ fromJson(needs.scope.outputs.widgets) }} + widget: ${{ fromJson(needs.scope.outputs.widgets_to_test) }} fail-fast: false steps: - name: "Check out code" @@ -563,14 +564,14 @@ jobs: ios-widget-tests: needs: [scope, mendix-version, project, ios-app] - # Run if project succeeds and either ios-app succeeds OR we're using custom artifacts (ios-app was skipped) - if: ${{ (github.event.inputs.workspace != 'js-actions' || github.event_name == 'schedule') && always() && needs.project.result == 'success' && (needs.ios-app.result == 'success' || needs.ios-app.result == 'skipped') }} + # Run if widgets need testing (widgets_to_test is not empty) and project succeeds + if: ${{ needs.scope.outputs.widgets_to_test != '[]' && always() && needs.project.result == 'success' && (needs.ios-app.result == 'success' || needs.ios-app.result == 'skipped') }} runs-on: macos-15 timeout-minutes: 60 strategy: max-parallel: 5 matrix: - widget: ${{ fromJson(needs.scope.outputs.widgets) }} + widget: ${{ fromJson(needs.scope.outputs.widgets_to_test) }} fail-fast: false steps: - name: "Force cleanup workspace" @@ -659,8 +660,8 @@ jobs: android-js-tests: needs: [scope, mendix-version, project, android-app] - # Run if project succeeds and either android-app succeeds OR we're using custom artifacts (android-app was skipped) - if: ${{ (github.event.inputs.workspace == '*-native' || github.event_name == 'schedule' || github.event.inputs.workspace == 'js-actions' || contains(needs.scope.outputs.widgets, 'mobile-resources-native') || contains(needs.scope.outputs.widgets, 'nanoflow-actions-native')) && always() && needs.project.result == 'success' && (needs.android-app.result == 'success' || needs.android-app.result == 'skipped') }} + # Run if JS actions changed and project succeeds and either android-app succeeds OR we're using custom artifacts (android-app was skipped) + if: ${{ needs.scope.outputs.js_actions_changed == 'true' && always() && needs.project.result == 'success' && (needs.android-app.result == 'success' || needs.android-app.result == 'skipped') }} runs-on: ubuntu-24.04 timeout-minutes: 90 steps: @@ -729,8 +730,8 @@ jobs: ios-js-tests: needs: [scope, mendix-version, project, ios-app] - # Run if project succeeds and either ios-app succeeds OR we're using custom artifacts (ios-app was skipped) - if: ${{ (github.event.inputs.workspace == '*-native' || github.event_name == 'schedule' || github.event.inputs.workspace == 'js-actions' || contains(needs.scope.outputs.widgets, 'mobile-resources-native') || contains(needs.scope.outputs.widgets, 'nanoflow-actions-native')) && always() && needs.project.result == 'success' && (needs.ios-app.result == 'success' || needs.ios-app.result == 'skipped') }} + # Run if JS actions changed and project succeeds and either ios-app succeeds OR we're using custom artifacts (ios-app was skipped) + if: ${{ needs.scope.outputs.js_actions_changed == 'true' && always() && needs.project.result == 'success' && (needs.ios-app.result == 'success' || needs.ios-app.result == 'skipped') }} runs-on: macos-15 timeout-minutes: 90 steps: @@ -827,7 +828,7 @@ jobs: - name: "Download Android screenshots" run: | - widgets=$(echo '${{ needs.scope.outputs.widgets }}' | jq -r '.[]') + widgets=$(echo '${{ needs.scope.outputs.widgets_to_test }}' | jq -r '.[]') mkdir -p images/actual/android/ for widget in $widgets; do echo "Downloading android-screenshots-${widget}" @@ -841,7 +842,7 @@ jobs: - name: "Download iOS screenshots" run: | - widgets=$(echo '${{ needs.scope.outputs.widgets }}' | jq -r '.[]') + widgets=$(echo '${{ needs.scope.outputs.widgets_to_test }}' | jq -r '.[]') mkdir -p images/actual/ios/ for widget in $widgets; do echo "Downloading ios-screenshots-${widget}" From 5a7c7d365b3ef06cc30e4f3cdc1961f62f0a317c Mon Sep 17 00:00:00 2001 From: vadymv-mendix Date: Thu, 5 Feb 2026 14:16:10 +0100 Subject: [PATCH 3/7] chore: change to trigger the pipeline testing JS action trigger --- .../src/other/Base64DecodeToImage.ts | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts b/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts index f7243f73d..280defed3 100644 --- a/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts +++ b/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts @@ -6,6 +6,7 @@ // - the code between BEGIN EXTRA CODE and END EXTRA CODE // Other code you write will be lost the next time you deploy the project. import { Base64 } from "js-base64"; +import RNBlobUtil from "react-native-blob-util"; // BEGIN EXTRA CODE // END EXTRA CODE @@ -16,7 +17,7 @@ import { Base64 } from "js-base64"; * @param {MxObject} image * @returns {Promise.} */ -export function Base64DecodeToImage(base64: string, image: mendix.lib.MxObject): Promise { +export async function Base64DecodeToImage(base64: string, image: mendix.lib.MxObject): Promise { // BEGIN USER CODE if (!base64) { @@ -26,8 +27,57 @@ export function Base64DecodeToImage(base64: string, image: mendix.lib.MxObject): throw new Error("image should not be null"); } - const blob = new Blob([Base64.toUint8Array(base64)], { type: "image/png" }); + // Native platform + if (navigator && navigator.product === "ReactNative") { + try { + // Remove data URI prefix if present (e.g., "data:image/png;base64,") + let cleanBase64 = base64; + if (base64.includes(",")) { + cleanBase64 = base64.split(",")[1]; + } + + // Remove any whitespace/newlines + cleanBase64 = cleanBase64.replace(/\s/g, ""); + + // Validate base64 format + if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleanBase64)) { + throw new Error("Invalid base64 format"); + } + + // Create a temporary file path + const tempPath = `${RNBlobUtil.fs.dirs.CacheDir}/temp_image_${Date.now()}.png`; + + // Write Base64 data to a temporary file + await RNBlobUtil.fs.writeFile(tempPath, cleanBase64, "base64"); + // Fetch the file as a blob + const res = await fetch(`file://${tempPath}`); + const blob = await res.blob(); + + return new Promise((resolve, reject) => { + mx.data.saveDocument( + image.getGuid(), + "camera image", + {}, + blob, + () => { + RNBlobUtil.fs.unlink(tempPath).catch(() => {}); + resolve(true); + }, + error => { + RNBlobUtil.fs.unlink(tempPath).catch(() => {}); + reject(error); + } + ); + }); + } catch (error) { + console.error("Failed to decode base64 to image:", error); + return false; + } + } + + // Other platforms + const blob = new Blob([Base64.toUint8Array(base64)], { type: "image/png" }); return new Promise((resolve, reject) => { mx.data.saveDocument(image.getGuid(), "camera image", {}, blob, () => resolve(true), reject); }); From 09e83fdc4554d0265d4b404f0c6787894ea9d718 Mon Sep 17 00:00:00 2001 From: vadymv-mendix Date: Thu, 5 Feb 2026 15:02:02 +0100 Subject: [PATCH 4/7] fix: linter run --- .../src/other/Base64DecodeToImage.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts b/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts index 280defed3..1b8544eb4 100644 --- a/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts +++ b/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts @@ -61,11 +61,15 @@ export async function Base64DecodeToImage(base64: string, image: mendix.lib.MxOb {}, blob, () => { - RNBlobUtil.fs.unlink(tempPath).catch(() => {}); + RNBlobUtil.fs.unlink(tempPath).catch(() => { + // ignore errors during cleanup + }); resolve(true); }, error => { - RNBlobUtil.fs.unlink(tempPath).catch(() => {}); + RNBlobUtil.fs.unlink(tempPath).catch(() => { + // ignore errors during cleanup + }); reject(error); } ); From f7f75a794ce2d4cf7a9654a3a3fdf20db616c77b Mon Sep 17 00:00:00 2001 From: vadymv-mendix Date: Thu, 5 Feb 2026 15:04:12 +0100 Subject: [PATCH 5/7] Revert "chore: change to trigger the pipeline testing JS action trigger" This reverts commit 5a7c7d365b3ef06cc30e4f3cdc1961f62f0a317c. --- .../src/other/Base64DecodeToImage.ts | 58 +------------------ 1 file changed, 2 insertions(+), 56 deletions(-) diff --git a/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts b/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts index 1b8544eb4..f7243f73d 100644 --- a/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts +++ b/packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts @@ -6,7 +6,6 @@ // - the code between BEGIN EXTRA CODE and END EXTRA CODE // Other code you write will be lost the next time you deploy the project. import { Base64 } from "js-base64"; -import RNBlobUtil from "react-native-blob-util"; // BEGIN EXTRA CODE // END EXTRA CODE @@ -17,7 +16,7 @@ import RNBlobUtil from "react-native-blob-util"; * @param {MxObject} image * @returns {Promise.} */ -export async function Base64DecodeToImage(base64: string, image: mendix.lib.MxObject): Promise { +export function Base64DecodeToImage(base64: string, image: mendix.lib.MxObject): Promise { // BEGIN USER CODE if (!base64) { @@ -27,61 +26,8 @@ export async function Base64DecodeToImage(base64: string, image: mendix.lib.MxOb throw new Error("image should not be null"); } - // Native platform - if (navigator && navigator.product === "ReactNative") { - try { - // Remove data URI prefix if present (e.g., "data:image/png;base64,") - let cleanBase64 = base64; - if (base64.includes(",")) { - cleanBase64 = base64.split(",")[1]; - } - - // Remove any whitespace/newlines - cleanBase64 = cleanBase64.replace(/\s/g, ""); - - // Validate base64 format - if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleanBase64)) { - throw new Error("Invalid base64 format"); - } - - // Create a temporary file path - const tempPath = `${RNBlobUtil.fs.dirs.CacheDir}/temp_image_${Date.now()}.png`; - - // Write Base64 data to a temporary file - await RNBlobUtil.fs.writeFile(tempPath, cleanBase64, "base64"); - - // Fetch the file as a blob - const res = await fetch(`file://${tempPath}`); - const blob = await res.blob(); - - return new Promise((resolve, reject) => { - mx.data.saveDocument( - image.getGuid(), - "camera image", - {}, - blob, - () => { - RNBlobUtil.fs.unlink(tempPath).catch(() => { - // ignore errors during cleanup - }); - resolve(true); - }, - error => { - RNBlobUtil.fs.unlink(tempPath).catch(() => { - // ignore errors during cleanup - }); - reject(error); - } - ); - }); - } catch (error) { - console.error("Failed to decode base64 to image:", error); - return false; - } - } - - // Other platforms const blob = new Blob([Base64.toUint8Array(base64)], { type: "image/png" }); + return new Promise((resolve, reject) => { mx.data.saveDocument(image.getGuid(), "camera image", {}, blob, () => resolve(true), reject); }); From 2cbfdfea72fd1ca1db584e261d93d9cafaa0c102 Mon Sep 17 00:00:00 2001 From: vadymv-mendix Date: Thu, 5 Feb 2026 15:06:26 +0100 Subject: [PATCH 6/7] chore: update version to 5.0.1 and add NOOP comments to trigger CI change detection --- packages/pluggableWidgets/app-events-native/CHANGELOG.md | 2 ++ packages/pluggableWidgets/app-events-native/src/AppEvents.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/pluggableWidgets/app-events-native/CHANGELOG.md b/packages/pluggableWidgets/app-events-native/CHANGELOG.md index 73785cecb..089d73051 100644 --- a/packages/pluggableWidgets/app-events-native/CHANGELOG.md +++ b/packages/pluggableWidgets/app-events-native/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +- NOOP to trigger the test + ## [5.0.0] - 2025-3-31 ### Changed diff --git a/packages/pluggableWidgets/app-events-native/src/AppEvents.tsx b/packages/pluggableWidgets/app-events-native/src/AppEvents.tsx index a32cce748..4a0cc8b26 100644 --- a/packages/pluggableWidgets/app-events-native/src/AppEvents.tsx +++ b/packages/pluggableWidgets/app-events-native/src/AppEvents.tsx @@ -5,7 +5,7 @@ import { AppState, AppStateStatus, NativeEventSubscription } from "react-native" import { AppEventsProps } from "../typings/AppEventsProps"; import { executeAction } from "@mendix/piw-utils-internal"; -export type Props = AppEventsProps; +export type Props = AppEventsProps; // NOOP COMMENT TO TRIGGER CI CHANGE DETECTION export class AppEvents extends Component { private readonly onAppStateChangeHandler = this.onAppStateChange.bind(this); From 808a49d269ed287dd9d660b034b896d86467f961 Mon Sep 17 00:00:00 2001 From: vadymv-mendix Date: Thu, 5 Feb 2026 16:16:48 +0100 Subject: [PATCH 7/7] Revert "chore: update version to 5.0.1 and add NOOP comments to trigger CI change detection" This reverts commit 2cbfdfea72fd1ca1db584e261d93d9cafaa0c102. --- packages/pluggableWidgets/app-events-native/CHANGELOG.md | 2 -- packages/pluggableWidgets/app-events-native/src/AppEvents.tsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/pluggableWidgets/app-events-native/CHANGELOG.md b/packages/pluggableWidgets/app-events-native/CHANGELOG.md index 089d73051..73785cecb 100644 --- a/packages/pluggableWidgets/app-events-native/CHANGELOG.md +++ b/packages/pluggableWidgets/app-events-native/CHANGELOG.md @@ -6,8 +6,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] -- NOOP to trigger the test - ## [5.0.0] - 2025-3-31 ### Changed diff --git a/packages/pluggableWidgets/app-events-native/src/AppEvents.tsx b/packages/pluggableWidgets/app-events-native/src/AppEvents.tsx index 4a0cc8b26..a32cce748 100644 --- a/packages/pluggableWidgets/app-events-native/src/AppEvents.tsx +++ b/packages/pluggableWidgets/app-events-native/src/AppEvents.tsx @@ -5,7 +5,7 @@ import { AppState, AppStateStatus, NativeEventSubscription } from "react-native" import { AppEventsProps } from "../typings/AppEventsProps"; import { executeAction } from "@mendix/piw-utils-internal"; -export type Props = AppEventsProps; // NOOP COMMENT TO TRIGGER CI CHANGE DETECTION +export type Props = AppEventsProps; export class AppEvents extends Component { private readonly onAppStateChangeHandler = this.onAppStateChange.bind(this);