diff --git a/packages/pluggableWidgets/gallery-native/CHANGELOG.md b/packages/pluggableWidgets/gallery-native/CHANGELOG.md index 18940f590..1ee503bbf 100644 --- a/packages/pluggableWidgets/gallery-native/CHANGELOG.md +++ b/packages/pluggableWidgets/gallery-native/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +- We've fixed an issue where Gallery widget does not display data. + ## [2.1.0] - 2026-4-10 ### Changed diff --git a/packages/pluggableWidgets/gallery-native/package.json b/packages/pluggableWidgets/gallery-native/package.json index 57b21044d..5360338e4 100644 --- a/packages/pluggableWidgets/gallery-native/package.json +++ b/packages/pluggableWidgets/gallery-native/package.json @@ -1,7 +1,7 @@ { "name": "gallery-native", "widgetName": "Gallery", - "version": "2.1.0", + "version": "2.1.1", "description": "A flexible gallery widget that renders columns, rows and layouts.", "copyright": "© Mendix Technology BV 2022. All rights reserved.", "license": "Apache-2.0", diff --git a/packages/pluggableWidgets/gallery-native/src/components/Gallery.tsx b/packages/pluggableWidgets/gallery-native/src/components/Gallery.tsx index 956a1cfc1..54c2de07c 100644 --- a/packages/pluggableWidgets/gallery-native/src/components/Gallery.tsx +++ b/packages/pluggableWidgets/gallery-native/src/components/Gallery.tsx @@ -1,5 +1,14 @@ -import { ReactElement, ReactNode, useCallback, useMemo } from "react"; -import { Text, Pressable, View, ViewProps, Platform, TouchableOpacity, useWindowDimensions } from "react-native"; +import { ReactElement, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + LayoutChangeEvent, + Text, + Pressable, + View, + ViewProps, + Platform, + TouchableOpacity, + useWindowDimensions +} from "react-native"; import { ObjectItem, DynamicValue } from "mendix"; import DeviceInfo from "react-native-device-info"; import { GalleryStyle } from "../ui/Styles"; @@ -35,6 +44,13 @@ export const Gallery = (props: GalleryProps): ReactElem const lastItemId = props.items?.[props.items.length - 1]?.id; const { name, style, itemRenderer } = props; const { width } = useWindowDimensions(); + // FlashList requires a non-zero height to render items (it's virtualized and needs viewport dimensions). + // When the parent provides height (e.g. via flex), we use flex: 1. When it doesn't (e.g. a Container + // widget with no flex/height), flex: 1 resolves to 0 and nothing renders. In that case, we fall back + // to minHeight based on FlashList's reported content size. We measure the FlashList area specifically so we get the height of the list area, not the entire Gallery (which may include filters and padding). + const listAreaRef = useRef(null); + const [contentHeight, setContentHeight] = useState(0); + const [layoutDecision, setLayoutDecision] = useState<"minHeight" | "flex" | null>(null); const onEndReached = (): void => { if (props.pagination === "virtualScrolling" && props.hasMoreItems) { @@ -137,29 +153,62 @@ export const Gallery = (props: GalleryProps): ReactElem [props.style.emptyPlaceholder, props.emptyPlaceholder] ); + const handleListAreaLayout = useCallback( + (event: LayoutChangeEvent) => { + const { height } = event.nativeEvent.layout; + if (height > 0 && layoutDecision === null) { + setLayoutDecision("flex"); + } + }, + [layoutDecision] + ); + + useEffect(() => { + if (contentHeight > 0 && layoutDecision === null && listAreaRef.current) { + listAreaRef.current.measure((_x, _y, _width, height) => { + setLayoutDecision(height > 0 ? "flex" : "minHeight"); + }); + } + }, [contentHeight, layoutDecision]); + + const containerStyle = isScrollDirectionVertical + ? layoutDecision === "minHeight" + ? [{ minHeight: Math.max(contentHeight, 1) }, props.style.container] + : [{ flex: 1 }, props.style.container] + : props.style.container; + + const listStyle = isScrollDirectionVertical ? [{ flex: 1 }, props.style.list] : props.style.list; + return ( - + {props.filters ? {props.filters} : null} - item.id} - ListEmptyComponent={renderEmptyPlaceholder} - onEndReached={onEndReached} - onEndReachedThreshold={0.6} - scrollEventThrottle={50} - renderItem={renderItem} - style={props.style.list} - testID={`${name}-list`} - /> + + item.id} + ListEmptyComponent={renderEmptyPlaceholder} + onEndReached={onEndReached} + onEndReachedThreshold={0.6} + scrollEventThrottle={50} + renderItem={renderItem} + style={listStyle} + testID={`${name}-list`} + onContentSizeChange={isScrollDirectionVertical ? (_w, h) => setContentHeight(h) : undefined} + /> + ); }; diff --git a/packages/pluggableWidgets/gallery-native/src/components/__tests__/__snapshots__/Gallery.spec.tsx.snap b/packages/pluggableWidgets/gallery-native/src/components/__tests__/__snapshots__/Gallery.spec.tsx.snap index 8665fd92e..aa845444f 100644 --- a/packages/pluggableWidgets/gallery-native/src/components/__tests__/__snapshots__/Gallery.spec.tsx.snap +++ b/packages/pluggableWidgets/gallery-native/src/components/__tests__/__snapshots__/Gallery.spec.tsx.snap @@ -2,173 +2,198 @@ exports[`Gallery rendering rendering with load more button it shouldn't render the paging button if hasn't more item 1`] = ` - - + + - 11 + + 11 + - - - + - 22 + + 22 + - - - + - 33 + + 33 + - - - + - 44 + + 44 + - - - + - 55 + + 55 + - - - + - 66 + + 66 + - - - + - 77 + + 77 + - - - + - 88 + + 88 + - - - + - 99 + + 99 + @@ -178,220 +203,245 @@ exports[`Gallery rendering rendering with load more button it shouldn't render t exports[`Gallery rendering rendering with load more button renders correctly 1`] = ` - - + + - 11 + + 11 + - - - + - 22 + + 22 + - - - + - 33 + + 33 + - - - + - 44 + + 44 + - - - + - 55 + + 55 + - - - + - 66 + + 66 + - - - + - 77 + + 77 + - - - + - 88 + + 88 + - - - + - 99 + + 99 + - - - - Load more - + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={{}} + testID="gallery-test-pagination-button" + > + + Load more + + @@ -399,220 +449,245 @@ exports[`Gallery rendering rendering with load more button renders correctly 1`] exports[`Gallery rendering rendering with load more button renders correctly with custom paging button title 1`] = ` - - + + - 11 + + 11 + - - - + - 22 + + 22 + - - - + - 33 + + 33 + - - - + - 44 + + 44 + - - - + - 55 + + 55 + - - - + - 66 + + 66 + - - - + - 77 + + 77 + - - - + - 88 + + 88 + - - - + - 99 + + 99 + - - - - Show more - + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={{}} + testID="gallery-test-pagination-button" + > + + Show more + + @@ -620,173 +695,198 @@ exports[`Gallery rendering rendering with load more button renders correctly wit exports[`Gallery rendering renders correctly 1`] = ` - - + + - 11 + + 11 + - - - + - 22 + + 22 + - - - + - 33 + + 33 + - - - + - 44 + + 44 + - - - + - 55 + + 55 + - - - + - 66 + + 66 + - - - + - 77 + + 77 + - - - + - 88 + + 88 + - - - + - 99 + + 99 + @@ -799,214 +899,216 @@ exports[`Gallery rendering renders correctly horizontal 1`] = ` style={{}} testID="gallery-test" > - - - + + } + horizontal={true} + keyExtractor={[Function]} + onEndReached={[Function]} + onEndReachedThreshold={0.6} + scrollEventThrottle={50} + testID="gallery-test-list" + > + - 11 + + 11 + - - - + - 22 + + 22 + - - - + - 33 + + 33 + - - - + - 44 + + 44 + - - - + - 55 + + 55 + - - - + - 66 + + 66 + - - - + - 77 + + 77 + - - - + - 88 + + 88 + - - - + - 99 + + 99 + @@ -1016,28 +1118,53 @@ exports[`Gallery rendering renders correctly horizontal 1`] = ` exports[`Gallery rendering renders correctly with empty list and custom placeholder 1`] = ` - - - Empty list... - + + + + Empty list... + + @@ -1045,176 +1172,201 @@ exports[`Gallery rendering renders correctly with empty list and custom placehol exports[`Gallery rendering renders correctly with filter 1`] = ` - - + + - 11 + + 11 + - - - + - 22 + + 22 + - - - + - 33 + + 33 + - - - + - 44 + + 44 + - - - + - 55 + + 55 + - - - + - 66 + + 66 + - - - + - 77 + + 77 + - - - + - 88 + + 88 + - - - + - 99 + + 99 + diff --git a/packages/pluggableWidgets/gallery-native/src/package.xml b/packages/pluggableWidgets/gallery-native/src/package.xml index 131f3fb0a..cc5b9921c 100644 --- a/packages/pluggableWidgets/gallery-native/src/package.xml +++ b/packages/pluggableWidgets/gallery-native/src/package.xml @@ -1,6 +1,6 @@ - +