Skip to content
2 changes: 1 addition & 1 deletion configs/e2e/mendix-versions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"latest": "10.24.4.77222"
"latest": "10.24.14.90436"
}
5 changes: 4 additions & 1 deletion packages/jsActions/nanoflow-actions-native/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Fixed

- We've fixed a synchronization issue with Base64 images generated by the Signature widget.

## [5.2.0] Nanoflow Commons - 2026-1-23

- We've migrated from using @react-native-community/geolocation to react-native-permissions for handling location permissions.
-

## [5.1.6] Nanoflow Commons - 2025-12-05

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,7 +17,7 @@ import { Base64 } from "js-base64";
* @param {MxObject} image
* @returns {Promise.<boolean>}
*/
export function Base64DecodeToImage(base64: string, image: mendix.lib.MxObject): Promise<boolean> {
export async function Base64DecodeToImage(base64: string, image: mendix.lib.MxObject): Promise<boolean> {
// BEGIN USER CODE

if (!base64) {
Expand All @@ -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);
});
Expand Down
Loading