Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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": "11.12.3"
"latest": "11.12.5"
}
1 change: 1 addition & 0 deletions configs/jsactions/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export default async args => {

const nativeExternal = [
/^mendix\//,
/^mendix-native(\/|$)/,
/^react-native(\/|$)/,
/^react-native-windows(\/|$)/,
/^react-native-web(\/|$)/,
Expand Down
29 changes: 28 additions & 1 deletion packages/jsActions/mobile-resources-native/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Added

- We added mendix-native as a dependency to provide native file system.

## [12.5.1] Native Mobile Resources - 2026-10-8


Expand All @@ -21,16 +25,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [12.5.0] Native Mobile Resources - 2026-9-24


## [2.3.1] BackgroundGradient

### Changed

- We removed the library of `react-native-linear-gradient` in favor of a react-native View with linear-gradient type background.

## [2.3.1] BackgroundImage

- Fixed background image widget not visible when there is no content inside it.

## [5.3.3] BottomSheet

### Added

- Added an `On change` event that triggers when the `Trigger attribute` value changes, allowing detection of bottom sheet dismissal (e.g. by outside click).
Expand All @@ -41,36 +47,43 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Replaced a deprecated prop 'containerHeight' with the respective 'containerLayoutState' option.

## [3.0.0] Signature

### Added

- Added direct image upload to System.Image object using the type `image` with `allowUpload` set to true.
- Renamed `onSave` action to `onSignEnd` to match web signature widget naming convention

## [12.4.0] Native Mobile Resources - 2026-9-2

### Fixed

- Removed the visible changes in NC and NMR modules during the first build of the app.

## [3.4.0] Animation

### Changed

- We updated react-native-animatable to 1.4.0.

## [3.3.0] BarChart

### Changed

- We updated victory-native to 36.9.2.

## [4.5.0] BarcodeScanner

- We fixed the barcode mask not visible issue and selection logic of QR code.

## [3.3.0] Carousel

### Changed

- We updated deprecated-react-native-prop-types to 4.2.3.
- We pinned react-native-snap-carousel to 3.9.1.

## [2.3.0] ColorPicker

### Changed

- We updated deprecated-react-native-prop-types to 4.2.3.
Expand All @@ -79,73 +92,87 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- We updated tinycolor2 to 1.6.0.

## [2.3.0] ColumnChart

### Changed

- We updated victory-native to 36.9.2.

## [3.6.2] Feedback

### Changed

- We pinned querystringify to 2.2.0.

## [4.3.0] FloatingActionButton

- We have removed the 'react-native-reanimated' library and used Animated API of react native for animation purpose.
- We fixed an issue of secondary button's caption not displayed if its horizontal position is center.
- We refactored code and migrated to functional component.

## [4.5.0] IntroScreen

### Fixed

- We fixed an issue where the IntroScreen did not show the slide set by the active slide attribute, and where swiping between slides did not work reliably on slower Android devices.

## [3.3.0] LineChart

### Changed

- We updated victory-native to 36.9.2.

## [5.2.1] Maps

### Changed

- We pinned prop-types to 15.8.1.

## [2.3.0] PieDoughnutChart

### Changed

- We updated victory-native to 36.9.2.

## [4.1.1] PopupMenu

### Changed

- We pinned react-native-material-menu to 1.2.0.

## [4.4.1] ProgressBar

### Changed

- We pinned react-native-progress to 5.0.1.

## [3.3.1] ProgressCircle

### Changed

- We pinned react-native-progress to 5.0.1.

## [3.0.1] RangeSlider

### Changed

- We pinned @miblanchard/react-native-slider to 2.6.0.

## [5.3.0] Rating

### Changed

- We removed @react-native-vector-icons/common dependency.
- We removed @react-native-vector-icons/get-image depedency.
- We added react-native-svg dependency and fixed the issue of rating icons not visible if user sets empty star and selected star as none in studio pro.

## [4.0.1] Slider

### Changed

- We pinned @miblanchard/react-native-slider to 2.6.0.

## [2.5.0] ToggleButtons

### Changed

- We updated react-native-segmented-control-tab to 3.4.1.
Expand Down
5 changes: 3 additions & 2 deletions packages/jsActions/mobile-resources-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"marketplace": {
"name": "Native Mobile Resources",
"description": "Download this module to access a rich set of widgets and nanoflow actions created for native mobile, including authentication, network, platform, and more. A must-have for native mobile development!",
"minimumMXVersion": "11.12.3",
"minimumMXVersion": "11.12.5",
"marketplaceId": 109513
},
"testProject": {
Expand All @@ -34,6 +34,7 @@
"@sbaiahmed1/react-native-biometrics": "0.15.0",
"@swan-io/react-native-browser": "1.0.1",
"fbjs": "3.0.4",
"mendix-native": "https://github.com/mendix/mendix-native/releases/download/v0.5.2/mendix-native-v0.5.2.tgz",
"mime": "3.0.0",
"react-native-blob-util": "0.24.7",
"react-native-device-info": "15.0.2",
Expand All @@ -51,4 +52,4 @@
"mendix": "11.8.0",
"rimraf": "^6.1.2"
}
}
}
105 changes: 11 additions & 94 deletions packages/jsActions/mobile-resources-native/src/camera/TakePicture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
// - 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 { Big } from "big.js";
import { Alert, Linking, NativeModules, Platform } from "react-native";
import { NativeFileSystem } from "mendix-native";
import { Alert, Linking, Platform } from "react-native";
import {
CameraOptions,
ErrorCode,
Expand All @@ -16,7 +17,8 @@ import {
launchImageLibrary
} from "react-native-image-picker";
import { getLocales } from "react-native-localize";
import { ImagePickerV2Options, ImagePickerV2Response, PictureQuality, PictureSource } from "../../typings/Camera";
import RNPermissions from "react-native-permissions";
import { PictureQuality, PictureSource } from "../../typings/Camera";

Comment thread
YogendraShelke marked this conversation as resolved.
// BEGIN EXTRA CODE
// END EXTRA CODE
Expand Down Expand Up @@ -56,8 +58,7 @@ export async function TakePicture(
}

// V3 dropped the feature of providing an action sheet so users can decide on which action to take, camera or library.
const nativeVersionMajor = NativeModules?.ImagePickerManager?.showImagePicker ? 2 : 4;
const RNPermissions = nativeVersionMajor === 4 ? (await import("react-native-permissions")).default : null;
// react-native-image-picker v7.2.3 is always v4+ (no legacy action sheet API)

try {
const uri = await takePicture();
Expand All @@ -77,32 +78,14 @@ export async function TakePicture(

function takePicture(): Promise<string | undefined> {
return new Promise((resolve, reject) => {
const options = nativeVersionMajor === 2 ? getOptionsV2() : getOptions();
const options = getOptions();
getPictureMethod()
.then(method =>
method(options, (response: ImagePickerV2Response | ImagePickerResponse) => {
method(options, (response: ImagePickerResponse) => {
if (response.didCancel) {
return resolve(undefined);
}

if (nativeVersionMajor === 2) {
const responseV2 = response as ImagePickerV2Response;

if (responseV2.error) {
const unhandledError = handleImagePickerV2Error(responseV2.error);

if (!unhandledError) {
return resolve(undefined);
}

return reject(new Error(responseV2.error));
}

return resolve(responseV2.uri);
}

response = response as ImagePickerResponse;

if (response.errorCode) {
handleImagePickerV4Error(response.errorCode, response.errorMessage);

Expand All @@ -118,7 +101,7 @@ export async function TakePicture(

async function safeRemove(filePath: string): Promise<void> {
try {
await NativeModules.MxFileSystem.remove(filePath);
await NativeFileSystem.remove(filePath);
} catch (error) {
console.warn(`Failed to remove file at ${filePath}. Error: ${error}`);
// ignore error
Expand All @@ -127,7 +110,7 @@ export async function TakePicture(

function storeFile(imageObject: mendix.lib.MxObject, uri: string): Promise<boolean> {
return new Promise((resolve, reject) => {
NativeModules.MxFileSystem.read(uri.replace("file://", ""))
NativeFileSystem.read(uri.replace("file://", ""))
.then((nativeBlob: unknown) => {
const blob = new Blob();
Object.assign(blob, { data: nativeBlob });
Expand Down Expand Up @@ -169,13 +152,10 @@ export async function TakePicture(
}

async function getPictureMethod(): Promise<
(
options: ImagePickerV2Options | CameraOptions | ImageLibraryOptions,
callback: (response: ImagePickerV2Response | ImagePickerResponse) => void
) => void
(options: CameraOptions | ImageLibraryOptions, callback: (response: ImagePickerResponse) => void) => void
> {
async function handleCameraRequest(): Promise<typeof launchCamera> {
if (Platform.OS === "android" && nativeVersionMajor === 4) {
if (Platform.OS === "android") {
await checkAndMaybeRequestAndroidPermission();
}

Expand Down Expand Up @@ -225,38 +205,6 @@ export async function TakePicture(
}
}

function getOptionsV2(): ImagePickerV2Options {
const { maxWidth, maxHeight } = getPictureQuality();
const [language] = getLocales().map(local => local.languageCode);
const isDutch = language === "nl";

return {
mediaType: "photo" as const,
maxWidth,
maxHeight,
noData: true,
title: isDutch ? "Foto toevoegen" : "Select a photo",
cancelButtonTitle: isDutch ? "Annuleren" : "Cancel",
takePhotoButtonTitle: isDutch ? "Foto maken" : "Take photo",
chooseFromLibraryButtonTitle: isDutch ? "Kies uit bibliotheek" : "Choose from library",
permissionDenied: {
title: isDutch
? "Deze app heeft geen toegang tot uw camera of foto bibliotheek"
: "This app does not have access to your camera or photo library",
text: isDutch
? "Ga naar Instellingen > Privacy om toegang tot uw camera en bestanden te verlenen."
: "To enable access, tap Settings > Privacy and turn on Camera and Photos/Storage.",
reTryTitle: isDutch ? "Instellingen" : "Settings",
okTitle: isDutch ? "Annuleren" : "Cancel"
},
storageOptions: {
skipBackup: true,
cameraRoll: false,
privateDirectory: true
}
};
}

function getOptions(): CameraOptions | ImageLibraryOptions {
const { maxWidth, maxHeight } = getPictureQuality();
return {
Expand Down Expand Up @@ -293,37 +241,6 @@ export async function TakePicture(
}
}

function handleImagePickerV2Error(error: string): string | undefined {
const ERRORS = {
AndroidPermissionDenied: "Permissions weren't granted",
iOSPhotoLibraryPermissionDenied: "Photo library permissions not granted",
iOSCameraPermissionDenied: "Camera permissions not granted"
};

switch (error) {
case ERRORS.iOSPhotoLibraryPermissionDenied:
showAlert(
"This app does not have access to your photo library",
"To enable access, tap Settings and turn on Photos."
);
return;

case ERRORS.iOSCameraPermissionDenied:
showAlert(
"This app does not have access to your camera",
"To enable access, tap Settings and turn on Camera."
);
return;

case ERRORS.AndroidPermissionDenied:
// Ignore this error because the image picker plugin already shows an alert in this case.
return;

default:
return error;
}
}

function showAlert(title: string, message: string): void {
Alert.alert(
title,
Expand Down
Loading
Loading