diff --git a/packages/pluggableWidgets/signature-native/CHANGELOG.md b/packages/pluggableWidgets/signature-native/CHANGELOG.md index a30ff810e..1cbdd7b37 100644 --- a/packages/pluggableWidgets/signature-native/CHANGELOG.md +++ b/packages/pluggableWidgets/signature-native/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +## [2.4.0] - 2026-4-10 + +### Added + +- Added directImage save mode that uploads the signature directly to a System.Image object + ## [2.3.0] - 2025-7-7 - Updated react-native-webview from version v13.12.5 to latest diff --git a/packages/pluggableWidgets/signature-native/package.json b/packages/pluggableWidgets/signature-native/package.json index 8a1de5e7e..57a82a2dc 100644 --- a/packages/pluggableWidgets/signature-native/package.json +++ b/packages/pluggableWidgets/signature-native/package.json @@ -1,7 +1,7 @@ { "name": "signature-native", "widgetName": "Signature", - "version": "2.3.0", + "version": "2.4.0", "license": "Apache-2.0", "repository": { "type": "git", diff --git a/packages/pluggableWidgets/signature-native/src/Signature.editorConfig.ts b/packages/pluggableWidgets/signature-native/src/Signature.editorConfig.ts index aa4f68ac0..2fda000e1 100644 --- a/packages/pluggableWidgets/signature-native/src/Signature.editorConfig.ts +++ b/packages/pluggableWidgets/signature-native/src/Signature.editorConfig.ts @@ -1,6 +1,19 @@ import { StructurePreviewProps, topBar } from "@mendix/piw-utils-internal"; +import { hidePropertiesIn, Properties } from "@mendix/pluggable-widgets-tools"; import { SignaturePreviewProps } from "../typings/SignatureProps"; export const getPreview = (_: SignaturePreviewProps, isDarkMode: boolean): StructurePreviewProps => topBar("Signature", [], isDarkMode); + +export function getProperties(values: SignaturePreviewProps, defaultProperties: Properties): Properties { + if (values.saveMode === "attribute") { + hidePropertiesIn(defaultProperties, values, ["imageObject"]); + } + + if (values.saveMode === "directImage") { + hidePropertiesIn(defaultProperties, values, ["imageAttribute"]); + } + + return defaultProperties; +} diff --git a/packages/pluggableWidgets/signature-native/src/Signature.tsx b/packages/pluggableWidgets/signature-native/src/Signature.tsx index 02b99ceb1..0da242454 100644 --- a/packages/pluggableWidgets/signature-native/src/Signature.tsx +++ b/packages/pluggableWidgets/signature-native/src/Signature.tsx @@ -1,6 +1,7 @@ import { mergeNativeStyles, extractStyles } from "@mendix/pluggable-widgets-tools"; import { executeAction } from "@mendix/piw-utils-internal"; import { ReactElement, useCallback, useRef } from "react"; +import RNBlobUtil from "react-native-blob-util"; import { View, Text } from "react-native"; import SignatureScreen, { SignatureViewRef } from "react-native-signature-canvas"; import { Touchable } from "./components/Touchable"; @@ -10,6 +11,47 @@ import { SignatureStyle, defaultSignatureStyle, webStyles } from "./ui/Styles"; export type Props = SignatureProps; +declare const mx: { + data: { + saveDocument( + guid: string, + fileName: string, + params: object, + blob: Blob, + callback: () => void, + error: (error: Error) => void + ): void; + }; +}; + +function getCleanBase64(signature: string): string { + return signature.includes(",") ? signature.split(",")[1].replace(/\s/g, "") : signature.replace(/\s/g, ""); +} + +async function uploadSignature(signature: string, guid: string): Promise { + const tempPath = `${RNBlobUtil.fs.dirs.CacheDir}/temp_signature_${Date.now()}.png`; + + try { + await RNBlobUtil.fs.writeFile(tempPath, getCleanBase64(signature), "base64"); + + const response = await fetch(`file://${tempPath}`); + const blob = await response.blob(); + + return await new Promise((resolve, reject) => { + mx.data.saveDocument( + guid, + "camera image", + {}, + blob, + () => resolve(), + (error: Error) => reject(error) + ); + }); + } finally { + RNBlobUtil.fs.unlink(tempPath).catch(() => undefined); + } +} + export function Signature(props: Props): ReactElement { const ref = useRef(null); const styles = mergeNativeStyles(defaultSignatureStyle, props.style); @@ -28,11 +70,30 @@ export function Signature(props: Props): ReactElement { const buttonCaptionSave = props.buttonCaptionSave?.value ?? "Save"; const handleSignature = useCallback( - (base64signature: string): void => { - props.imageAttribute.setValue(base64signature); + async (base64signature: string): Promise => { + if (props.saveMode === "directImage") { + const targetGuid = props.imageObject?.value?.id; + + if (!targetGuid) { + console.error( + "Signature direct image mode requires the widget to be placed inside a System.Image data container." + ); + return; + } + + try { + await uploadSignature(base64signature, targetGuid); + executeAction(props.onSave); + } catch (error) { + console.error("Failed to upload signature image:", error); + } + return; + } + + props.imageAttribute?.setValue(base64signature); executeAction(props.onSave); }, - [props.imageAttribute, props.onSave] + [props.imageAttribute, props.imageObject, props.onSave, props.saveMode] ); return ( diff --git a/packages/pluggableWidgets/signature-native/src/Signature.xml b/packages/pluggableWidgets/signature-native/src/Signature.xml index aef8609f4..df52092cb 100644 --- a/packages/pluggableWidgets/signature-native/src/Signature.xml +++ b/packages/pluggableWidgets/signature-native/src/Signature.xml @@ -1,23 +1,32 @@ - - + + Signature Display signature. - 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 - + + Save mode + Choose how the signature is saved. "Store as Base64 string" saves the signature as a base64 value to a String attribute — use the Base64DecodeToImage nanoflow action to convert and commit it to an image object. "Direct image upload" skips the base64 step entirely: the signature is uploaded directly to the linked System.Image object, so you only need to commit the object in your nanoflow. + + Store as Base64 string + Direct image + + + Attribute - + The String attribute that receives the signature as a base64 value when save mode is Store as Base64 string. - + + + Target image + The context System.Image object to which the signature will be uploaded when save mode is Direct image. + @@ -49,7 +58,7 @@ - + diff --git a/packages/pluggableWidgets/signature-native/src/__tests__/Signature.android.spec.tsx b/packages/pluggableWidgets/signature-native/src/__tests__/Signature.android.spec.tsx index 0e8960057..ff445eb25 100644 --- a/packages/pluggableWidgets/signature-native/src/__tests__/Signature.android.spec.tsx +++ b/packages/pluggableWidgets/signature-native/src/__tests__/Signature.android.spec.tsx @@ -6,6 +6,18 @@ import { fireEvent, render } from "@testing-library/react-native"; import { Signature, Props } from "../Signature"; import { actionValue, dynamicValue, EditableValueBuilder } from "@mendix/piw-utils-internal"; +jest.mock("react-native-blob-util", () => ({ + __esModule: true, + default: { + fs: { + dirs: { CacheDir: "/tmp" }, + writeFile: jest.fn().mockResolvedValue(undefined), + unlink: jest.fn().mockResolvedValue(undefined) + }, + fetch: jest.fn() + } +})); + jest.mock("react-native", () => { const RN = jest.requireActual("react-native"); RN.NativeModules.RNCWebView = { isFileUploadSupported: jest.fn(() => true) }; @@ -45,7 +57,8 @@ const defaultProps: Props = { style: [], imageAttribute: new EditableValueBuilder().withValue("").build(), buttonCaptionClear: dynamicValue("Clear"), - buttonCaptionSave: dynamicValue("Save") + buttonCaptionSave: dynamicValue("Save"), + saveMode: "attribute" }; describe("Signature Android", () => { diff --git a/packages/pluggableWidgets/signature-native/src/__tests__/Signature.ios.spec.tsx b/packages/pluggableWidgets/signature-native/src/__tests__/Signature.ios.spec.tsx index 13ffc39b9..0449a0a0a 100644 --- a/packages/pluggableWidgets/signature-native/src/__tests__/Signature.ios.spec.tsx +++ b/packages/pluggableWidgets/signature-native/src/__tests__/Signature.ios.spec.tsx @@ -4,6 +4,18 @@ import { fireEvent, render } from "@testing-library/react-native"; import { Signature, Props } from "../Signature"; import { actionValue, dynamicValue, EditableValueBuilder } from "@mendix/piw-utils-internal"; +jest.mock("react-native-blob-util", () => ({ + __esModule: true, + default: { + fs: { + dirs: { CacheDir: "/tmp" }, + writeFile: jest.fn().mockResolvedValue(undefined), + unlink: jest.fn().mockResolvedValue(undefined) + }, + fetch: jest.fn() + } +})); + jest.mock("react-native", () => { const RN = jest.requireActual("react-native"); RN.NativeModules.RNCWebView = { isFileUploadSupported: jest.fn(() => true) }; @@ -21,7 +33,8 @@ const defaultProps: Props = { style: [], imageAttribute: new EditableValueBuilder().withValue("").build(), buttonCaptionClear: dynamicValue("Clear"), - buttonCaptionSave: dynamicValue("Save") + buttonCaptionSave: dynamicValue("Save"), + saveMode: "attribute" }; jest.mock("react-native-webview", () => { diff --git a/packages/pluggableWidgets/signature-native/src/package.xml b/packages/pluggableWidgets/signature-native/src/package.xml index 5ad56899c..457e35131 100644 --- a/packages/pluggableWidgets/signature-native/src/package.xml +++ b/packages/pluggableWidgets/signature-native/src/package.xml @@ -1,6 +1,6 @@ - + diff --git a/packages/pluggableWidgets/signature-native/typings/SignatureProps.d.ts b/packages/pluggableWidgets/signature-native/typings/SignatureProps.d.ts index ebc9afc79..078627650 100644 --- a/packages/pluggableWidgets/signature-native/typings/SignatureProps.d.ts +++ b/packages/pluggableWidgets/signature-native/typings/SignatureProps.d.ts @@ -4,12 +4,16 @@ * @author Mendix Widgets Framework Team */ import { CSSProperties } from "react"; -import { ActionValue, DynamicValue, EditableValue } from "mendix"; +import { ActionValue, DynamicValue, EditableValue, ObjectItem } from "mendix"; + +export type SaveModeEnum = "attribute" | "directImage"; export interface SignatureProps