expo-simple-gallery 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/ExpoSimpleGalleryModal.d.ts.map +1 -1
- package/build/ExpoSimpleGalleryModal.js +3 -3
- package/build/ExpoSimpleGalleryModal.js.map +1 -1
- package/build/ExpoSimpleGalleryView.d.ts.map +1 -1
- package/build/ExpoSimpleGalleryView.js +11 -7
- package/build/ExpoSimpleGalleryView.js.map +1 -1
- package/ios/ExpoSimpleGalleryModule.swift +0 -1
- package/ios/ExpoSimpleGalleryView.swift +62 -35
- package/ios/Gallery/GalleryGridView+Configuration.swift +29 -21
- package/ios/Gallery/GalleryGridView.swift +2 -2
- package/package.json +6 -11
- package/src/ExpoSimpleGalleryModal.tsx +6 -22
- package/src/ExpoSimpleGalleryView.tsx +24 -42
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSimpleGalleryModal.d.ts","sourceRoot":"","sources":["../src/ExpoSimpleGalleryModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpoSimpleGalleryModal.d.ts","sourceRoot":"","sources":["../src/ExpoSimpleGalleryModal.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,gCAAgC,CAAC;AAK5F,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,IAAI,EACJ,YAAgB,EAChB,OAAO,EACP,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EACZ,KAAK,EACL,eAAe,GAChB,EAAE,iBAAiB,+BAmDnB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireNativeViewManager } from 'expo-modules-core';
|
|
2
2
|
import { useCallback, useMemo, useState } from 'react';
|
|
3
|
-
import { Modal, StyleSheet, View
|
|
4
|
-
const GalleryViewer =
|
|
3
|
+
import { Modal, StyleSheet, View } from 'react-native';
|
|
4
|
+
const GalleryViewer = requireNativeViewManager('GalleryImageViewer');
|
|
5
5
|
export function GalleryModal({ visible, uris, initialIndex = 0, onClose, overlayComponent: OverlayComponent, selectedUris, style, toggleSelection, }) {
|
|
6
6
|
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
7
7
|
const [currentUri, setCurrentUri] = useState(uris[initialIndex] || '');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSimpleGalleryModal.js","sourceRoot":"","sources":["../src/ExpoSimpleGalleryModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ExpoSimpleGalleryModal.js","sourceRoot":"","sources":["../src/ExpoSimpleGalleryModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { requireNativeViewManager } from 'expo-modules-core';\nimport { type ComponentType, useCallback, useMemo, useState } from 'react';\nimport { Modal, type NativeSyntheticEvent, StyleSheet, View } from 'react-native';\nimport type { GalleryItem } from './ExpoSimpleGallery.types';\nimport type { GalleryModalProps, GalleryViewerProps } from './ExpoSimpleGalleryModal.types';\n\nconst GalleryViewer: ComponentType<GalleryViewerProps> =\n requireNativeViewManager('GalleryImageViewer');\n\nexport function GalleryModal({\n visible,\n uris,\n initialIndex = 0,\n onClose,\n overlayComponent: OverlayComponent,\n selectedUris,\n style,\n toggleSelection,\n}: GalleryModalProps) {\n const [currentIndex, setCurrentIndex] = useState(initialIndex);\n const [currentUri, setCurrentUri] = useState(uris[initialIndex] || '');\n const selected = useMemo(() => selectedUris.has(currentUri), [selectedUris, currentUri]);\n\n const handlePageChange = useCallback(\n (event: NativeSyntheticEvent<{ index: number; uri: string }>) => {\n const { index, uri } = event.nativeEvent;\n setCurrentIndex(index);\n setCurrentUri(uri);\n },\n []\n );\n\n const handleDismissAttempt = useCallback(\n (event: NativeSyntheticEvent<GalleryItem>) => {\n onClose(event);\n },\n [onClose]\n );\n\n const handleSelectionToggle = useCallback(\n (selected?: boolean) => {\n toggleSelection(currentUri, selected);\n },\n [currentUri, toggleSelection]\n );\n\n return (\n <Modal visible={visible} transparent={true} animationType=\"fade\" onRequestClose={onClose}>\n <View style={[styles.container, style]}>\n <GalleryViewer\n style={styles.viewer}\n imageData={{ uris, startIndex: initialIndex }}\n onPageChange={handlePageChange}\n onDismissAttempt={handleDismissAttempt}\n />\n\n {OverlayComponent && (\n <View style={styles.overlayContainer} pointerEvents=\"box-none\">\n <OverlayComponent\n index={currentIndex}\n uri={currentUri}\n selected={selected}\n toggleSelection={handleSelectionToggle}\n />\n </View>\n )}\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n backgroundColor: 'black',\n },\n viewer: {\n flex: 1,\n },\n overlayContainer: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSimpleGalleryView.d.ts","sourceRoot":"","sources":["../src/ExpoSimpleGalleryView.tsx"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,aAAa,EAOnB,MAAM,OAAO,CAAC;AAOf,OAAO,EACL,KAAK,wBAAwB,EAM7B,KAAK,QAAQ,EACd,MAAM,2BAA2B,CAAC;;;;;;;;;;;;;;;;;;;;AAanC,
|
|
1
|
+
{"version":3,"file":"ExpoSimpleGalleryView.d.ts","sourceRoot":"","sources":["../src/ExpoSimpleGalleryView.tsx"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,aAAa,EAOnB,MAAM,OAAO,CAAC;AAOf,OAAO,EACL,KAAK,wBAAwB,EAM7B,KAAK,QAAQ,EACd,MAAM,2BAA2B,CAAC;;;;;;;;;;;;;;;;;;;;AAanC,wBA+PE"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireNativeViewManager } from 'expo-modules-core';
|
|
2
2
|
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
3
3
|
import { processColor, useWindowDimensions, } from 'react-native';
|
|
4
4
|
import { isNestedArray, isNotNullOrUndefined, } from './ExpoSimpleGallery.types';
|
|
5
5
|
import { GalleryModal } from './ExpoSimpleGalleryModal';
|
|
6
6
|
import { MemoizedSectionHeader } from './components/MemoizedSectionHeader';
|
|
7
7
|
import { MemoizedThumbnailOverlayComponent } from './components/MemoizedThumbnailOverlayComponent';
|
|
8
|
-
const NativeView =
|
|
8
|
+
const NativeView = requireNativeViewManager('ExpoSimpleGallery');
|
|
9
9
|
const NativeViewMemoized = memo(NativeView);
|
|
10
10
|
const OVERLAYS_BUFFER = 10;
|
|
11
11
|
export default forwardRef(function ExpoSimpleGalleryView({ thumbnailOverlayComponent: ThumbnailOverlayComponent, fullscreenViewOverlayComponent: FullscreenOverlayComponent = () => null, sectionHeaderComponent: SectionHeaderComponent, sectionHeaderStyle, assets, thumbnailStyle, onSelectionChange, onOverlayPreloadRequested, onSectionHeadersVisible, debugLabels = false, onThumbnailPress, fullscreenViewOverlayStyle, onPreviewMenuOptionSelected, contextMenuOptions, initiallySelected, ...props }, forwardedRef) {
|
|
@@ -78,10 +78,13 @@ export default forwardRef(function ExpoSimpleGalleryView({ thumbnailOverlayCompo
|
|
|
78
78
|
onThumbnailPress?.(event);
|
|
79
79
|
}, [onThumbnailPress, openImageViewer]);
|
|
80
80
|
const handleModalClose = useCallback((event) => {
|
|
81
|
-
|
|
81
|
+
const index = event.nativeEvent.index;
|
|
82
82
|
setModalVisible(false);
|
|
83
|
+
internalRef.current?.centerOnIndex(index);
|
|
83
84
|
}, []);
|
|
84
|
-
const thumbnailOverlays = useMemo(() => assets.flat().map((uri, index) => ThumbnailOverlayComponent ? (<MemoizedThumbnailOverlayComponent
|
|
85
|
+
const thumbnailOverlays = useMemo(() => assets.flat().map((uri, index) => ThumbnailOverlayComponent ? (<MemoizedThumbnailOverlayComponent
|
|
86
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: we need to force re-render on order change
|
|
87
|
+
key={`${uri}-${index}`} OverlayComponent={ThumbnailOverlayComponent} uri={uri} index={index} width={thumbnailWidth} height={thumbnailHeight} selected={selectedUris.has(uri)} debugLabels={debugLabels} isNull={!(index >= visibleRangeMin - OVERLAYS_BUFFER &&
|
|
85
88
|
index <= visibleRangeMax + OVERLAYS_BUFFER)}/>) : null), [
|
|
86
89
|
assets,
|
|
87
90
|
ThumbnailOverlayComponent,
|
|
@@ -126,7 +129,9 @@ export default forwardRef(function ExpoSimpleGalleryView({ thumbnailOverlayCompo
|
|
|
126
129
|
internalRef.current?.setSelected([...newSet]);
|
|
127
130
|
}, [selectedUris]);
|
|
128
131
|
return (<>
|
|
129
|
-
<NativeViewMemoized
|
|
132
|
+
<NativeViewMemoized
|
|
133
|
+
// key={assets.length}
|
|
134
|
+
{...props} thumbnailStyle={thumbnailStyleProcessed} sectionHeaderStyle={sectionHeaderStyle} assets={assets} onSelectionChange={handleSelectionChange} onOverlayPreloadRequested={handleOverlayPreloadRequest} onSectionHeadersVisible={handleSectionHeadersVisible} onThumbnailPress={handleThumbnailPress} onPreviewMenuOptionSelected={handlePreviewMenuOptionSelected} contextMenuOptions={contextMenuOptions} onLayout={() => {
|
|
130
135
|
if (initiallySelected) {
|
|
131
136
|
internalRef.current?.setSelected(initiallySelected?.filter(isNotNullOrUndefined));
|
|
132
137
|
}
|
|
@@ -161,8 +166,7 @@ function useThumbnailDimensions({ thumbnailStyle, contentContainerStyle, columns
|
|
|
161
166
|
contentContainerStyle?.paddingHorizontal ??
|
|
162
167
|
contentContainerStyle?.padding ??
|
|
163
168
|
0;
|
|
164
|
-
const padding = Number.parseFloat(paddingLeft) +
|
|
165
|
-
Number.parseFloat(paddingRight);
|
|
169
|
+
const padding = Number.parseFloat(paddingLeft) + Number.parseFloat(paddingRight);
|
|
166
170
|
const thumbnailWidth = (width - padding - (columnsCount - 1) * thumbnailsSpacing) / columnsCount;
|
|
167
171
|
const thumbnailHeight = thumbnailWidth / thumbnailAspectRatio;
|
|
168
172
|
return { thumbnailWidth, thumbnailHeight };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSimpleGalleryView.js","sourceRoot":"","sources":["../src/ExpoSimpleGalleryView.tsx"],"names":[],"mappings":"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","sourcesContent":["import { requireNativeView } from 'expo';\nimport {\n type ComponentType,\n forwardRef,\n memo,\n type RefAttributes,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n type ColorValue,\n type NativeSyntheticEvent,\n processColor,\n useWindowDimensions,\n} from 'react-native';\nimport {\n type ExpoSimpleGalleryMethods,\n type ExpoSimpleGalleryViewProps,\n type GalleryItem,\n isNestedArray,\n isNotNullOrUndefined,\n type OnPreviewMenuOptionSelectedPayload,\n type UIAction,\n} from './ExpoSimpleGallery.types';\nimport { GalleryModal } from './ExpoSimpleGalleryModal';\nimport { MemoizedSectionHeader } from './components/MemoizedSectionHeader';\nimport { MemoizedThumbnailOverlayComponent } from './components/MemoizedThumbnailOverlayComponent';\n\nconst NativeView: ComponentType<\n ExpoSimpleGalleryViewProps & RefAttributes<ExpoSimpleGalleryMethods>\n> = requireNativeView('ExpoSimpleGallery');\n\nconst NativeViewMemoized = memo(NativeView);\n\nconst OVERLAYS_BUFFER = 10;\n\nexport default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(\n function ExpoSimpleGalleryView(\n {\n thumbnailOverlayComponent: ThumbnailOverlayComponent,\n fullscreenViewOverlayComponent: FullscreenOverlayComponent = () => null,\n sectionHeaderComponent: SectionHeaderComponent,\n sectionHeaderStyle,\n assets,\n thumbnailStyle,\n onSelectionChange,\n onOverlayPreloadRequested,\n onSectionHeadersVisible,\n debugLabels = false,\n onThumbnailPress,\n fullscreenViewOverlayStyle,\n onPreviewMenuOptionSelected,\n contextMenuOptions,\n initiallySelected,\n ...props\n }: ExpoSimpleGalleryViewProps,\n forwardedRef\n ) {\n const { width } = useWindowDimensions();\n const { thumbnailWidth, thumbnailHeight, thumbnailStyleProcessed } =\n useThumbnailDimensions({\n thumbnailStyle,\n contentContainerStyle: props.contentContainerStyle,\n columnsCount: props.columnsCount,\n });\n\n const openImageViewer = useCallback((index: number) => {\n setInitialIndex(index);\n setModalVisible(true);\n }, []);\n\n const thumbnailPressActionRef = useRef(props.thumbnailPressAction);\n useEffect(() => {\n thumbnailPressActionRef.current = props.thumbnailPressAction;\n }, [props.thumbnailPressAction]);\n\n const internalRef = useRef<ExpoSimpleGalleryMethods>(null);\n useImperativeHandle(forwardedRef, () => ({\n centerOnIndex: async (index: number) => {\n internalRef.current?.centerOnIndex(index);\n },\n setSelected: async (uris: string[]) => {\n internalRef.current?.setSelected(uris);\n },\n setThumbnailPressAction: async (\n action: ExpoSimpleGalleryViewProps['thumbnailPressAction']\n ) => {\n thumbnailPressActionRef.current = action;\n internalRef.current?.setThumbnailPressAction(action);\n },\n setThumbnailLongPressAction: async (\n action: ExpoSimpleGalleryViewProps['thumbnailLongPressAction']\n ) => {\n internalRef.current?.setThumbnailLongPressAction(action);\n },\n setThumbnailPanAction: async (\n action: ExpoSimpleGalleryViewProps['thumbnailPanAction']\n ) => {\n internalRef.current?.setThumbnailPanAction(action);\n },\n setContextMenuOptions: async (options: UIAction[]) => {\n internalRef.current?.setContextMenuOptions(options);\n },\n openImageViewer,\n closeImageViewer: () => {\n setModalVisible(false);\n },\n }));\n\n const [modalVisible, setModalVisible] = useState(false);\n const [initialIndex, setInitialIndex] = useState(0);\n\n const [selectedUris, setSelectedUris] = useState<Set<string>>(new Set());\n\n const [visibleRange, setVisibleRange] = useState<[number, number]>([0, 0]);\n const visibleRangeMin = useMemo(() => visibleRange[0], [visibleRange]);\n const visibleRangeMax = useMemo(() => visibleRange[1], [visibleRange]);\n\n const [visibleHeaders, setVisibleHeaders] = useState<number[]>([0]);\n const visibleHeadersRangeMin = useMemo(\n () => Math.min(...visibleHeaders),\n [visibleHeaders]\n );\n const visibleHeadersRangeMax = useMemo(\n () => Math.max(...visibleHeaders),\n [visibleHeaders]\n );\n\n const handleSelectionChange = useCallback(\n (event: NativeSyntheticEvent<{ selected: string[] }>) => {\n setSelectedUris(new Set(event.nativeEvent.selected));\n onSelectionChange?.(event);\n },\n [onSelectionChange]\n );\n\n const handleOverlayPreloadRequest = useCallback(\n (event: NativeSyntheticEvent<{ range: [number, number] }>) => {\n const [start, end] = event.nativeEvent.range;\n setVisibleRange([start, end]);\n onOverlayPreloadRequested?.(event);\n },\n [onOverlayPreloadRequested]\n );\n\n const handleSectionHeadersVisible = useCallback(\n (event: NativeSyntheticEvent<{ sections: number[] }>) => {\n setVisibleHeaders(event.nativeEvent.sections);\n onSectionHeadersVisible?.(event);\n },\n [onSectionHeadersVisible]\n );\n\n const handleThumbnailPress = useCallback(\n (event: NativeSyntheticEvent<GalleryItem>) => {\n if (thumbnailPressActionRef.current === 'open') {\n openImageViewer(event.nativeEvent.index);\n }\n onThumbnailPress?.(event);\n },\n [onThumbnailPress, openImageViewer]\n );\n\n const handleModalClose = useCallback(\n (event: NativeSyntheticEvent<GalleryItem>) => {\n internalRef.current?.centerOnIndex(event.nativeEvent.index);\n setModalVisible(false);\n },\n []\n );\n\n const thumbnailOverlays = useMemo(\n () =>\n assets.flat().map((uri, index) =>\n ThumbnailOverlayComponent ? (\n <MemoizedThumbnailOverlayComponent\n key={uri}\n OverlayComponent={ThumbnailOverlayComponent}\n uri={uri}\n index={index}\n width={thumbnailWidth}\n height={thumbnailHeight}\n selected={selectedUris.has(uri)}\n debugLabels={debugLabels}\n isNull={\n !(\n index >= visibleRangeMin - OVERLAYS_BUFFER &&\n index <= visibleRangeMax + OVERLAYS_BUFFER\n )\n }\n // isNull={false}\n />\n ) : null\n ),\n [\n assets,\n ThumbnailOverlayComponent,\n thumbnailWidth,\n thumbnailHeight,\n selectedUris,\n visibleRangeMin,\n visibleRangeMax,\n debugLabels,\n ]\n );\n\n const sectionHeaders = useMemo(() => {\n if (!SectionHeaderComponent || !isNestedArray(assets)) return null;\n return assets.map((group, index) => (\n <MemoizedSectionHeader\n key={JSON.stringify(group)}\n SectionHeader={SectionHeaderComponent}\n index={index}\n width={width}\n height={Number.parseFloat(\n (sectionHeaderStyle?.height ?? 0).toString()\n )}\n debugLabels={debugLabels}\n isNull={\n !(\n index >= visibleHeadersRangeMin - OVERLAYS_BUFFER &&\n index <= visibleHeadersRangeMax + OVERLAYS_BUFFER\n )\n }\n />\n ));\n }, [\n SectionHeaderComponent,\n assets,\n sectionHeaderStyle?.height,\n debugLabels,\n width,\n visibleHeadersRangeMin,\n visibleHeadersRangeMax,\n ]);\n\n const children = useMemo(\n () => [sectionHeaders, thumbnailOverlays],\n [sectionHeaders, thumbnailOverlays]\n );\n\n const handlePreviewMenuOptionSelected = useCallback(\n (event: NativeSyntheticEvent<OnPreviewMenuOptionSelectedPayload>) => {\n const action =\n contextMenuOptions?.[event.nativeEvent.optionIndex]?.action;\n action?.({\n uri: event.nativeEvent.uri,\n index: event.nativeEvent.index,\n });\n },\n [contextMenuOptions]\n );\n\n const handleToggleSelection = useCallback(\n (uri: string, selected?: boolean) => {\n const shouldSetSelected =\n selected === undefined ? !selectedUris.has(uri) : selected;\n const newSet = new Set(selectedUris);\n if (shouldSetSelected) {\n newSet.add(uri);\n } else {\n newSet.delete(uri);\n }\n internalRef.current?.setSelected([...newSet]);\n },\n [selectedUris]\n );\n\n return (\n <>\n <NativeViewMemoized\n {...props}\n thumbnailStyle={thumbnailStyleProcessed}\n sectionHeaderStyle={sectionHeaderStyle}\n assets={assets}\n onSelectionChange={handleSelectionChange}\n onOverlayPreloadRequested={handleOverlayPreloadRequest}\n onSectionHeadersVisible={handleSectionHeadersVisible}\n onThumbnailPress={handleThumbnailPress}\n onPreviewMenuOptionSelected={handlePreviewMenuOptionSelected}\n contextMenuOptions={contextMenuOptions}\n onLayout={() => {\n if (initiallySelected) {\n internalRef.current?.setSelected(\n initiallySelected?.filter(isNotNullOrUndefined)\n );\n }\n }}\n ref={internalRef}\n >\n {/* @ts-expect-error type of children is intentionally set to never | undefined */}\n {children}\n </NativeViewMemoized>\n <GalleryModal\n visible={modalVisible}\n uris={assets.flat()}\n initialIndex={initialIndex}\n onClose={handleModalClose}\n selectedUris={selectedUris}\n overlayComponent={FullscreenOverlayComponent}\n style={fullscreenViewOverlayStyle}\n toggleSelection={handleToggleSelection}\n />\n </>\n );\n }\n);\n\nfunction useThumbnailDimensions({\n thumbnailStyle,\n contentContainerStyle,\n columnsCount = 2,\n}: {\n thumbnailStyle: ExpoSimpleGalleryViewProps['thumbnailStyle'];\n contentContainerStyle: ExpoSimpleGalleryViewProps['contentContainerStyle'];\n columnsCount?: number;\n}) {\n const { width } = useWindowDimensions();\n const thumbnailStyleProcessed = useMemo(() => {\n if (!thumbnailStyle?.borderColor) return thumbnailStyle;\n const { borderColor } = thumbnailStyle;\n return {\n ...thumbnailStyle,\n borderColor: (processColor(borderColor) as ColorValue) ?? undefined,\n };\n }, [thumbnailStyle]);\n const { thumbnailWidth, thumbnailHeight } = useMemo(() => {\n const thumbnailAspectRatio =\n Number.parseFloat(\n (thumbnailStyleProcessed?.aspectRatio as string) ?? ''\n ) || 1;\n\n const thumbnailsSpacing = contentContainerStyle?.gap\n ? Number.parseInt(contentContainerStyle?.gap.toString())\n : 0;\n const paddingLeft =\n contentContainerStyle?.paddingLeft ??\n contentContainerStyle?.paddingHorizontal ??\n contentContainerStyle?.padding ??\n 0;\n const paddingRight =\n contentContainerStyle?.paddingRight ??\n contentContainerStyle?.paddingHorizontal ??\n contentContainerStyle?.padding ??\n 0;\n const padding =\n Number.parseFloat(paddingLeft as string) +\n Number.parseFloat(paddingRight as string);\n const thumbnailWidth =\n (width - padding - (columnsCount - 1) * thumbnailsSpacing) / columnsCount;\n const thumbnailHeight = thumbnailWidth / thumbnailAspectRatio;\n return { thumbnailWidth, thumbnailHeight };\n }, [width, thumbnailStyleProcessed, columnsCount, contentContainerStyle]);\n return { thumbnailWidth, thumbnailHeight, thumbnailStyleProcessed };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ExpoSimpleGalleryView.js","sourceRoot":"","sources":["../src/ExpoSimpleGalleryView.tsx"],"names":[],"mappings":"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","sourcesContent":["import { requireNativeViewManager } from 'expo-modules-core';\nimport {\n type ComponentType,\n forwardRef,\n memo,\n type RefAttributes,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n type ColorValue,\n type NativeSyntheticEvent,\n processColor,\n useWindowDimensions,\n} from 'react-native';\nimport {\n type ExpoSimpleGalleryMethods,\n type ExpoSimpleGalleryViewProps,\n type GalleryItem,\n isNestedArray,\n isNotNullOrUndefined,\n type OnPreviewMenuOptionSelectedPayload,\n type UIAction,\n} from './ExpoSimpleGallery.types';\nimport { GalleryModal } from './ExpoSimpleGalleryModal';\nimport { MemoizedSectionHeader } from './components/MemoizedSectionHeader';\nimport { MemoizedThumbnailOverlayComponent } from './components/MemoizedThumbnailOverlayComponent';\n\nconst NativeView: ComponentType<\n ExpoSimpleGalleryViewProps & RefAttributes<ExpoSimpleGalleryMethods>\n> = requireNativeViewManager('ExpoSimpleGallery');\n\nconst NativeViewMemoized = memo(NativeView);\n\nconst OVERLAYS_BUFFER = 10;\n\nexport default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(\n function ExpoSimpleGalleryView(\n {\n thumbnailOverlayComponent: ThumbnailOverlayComponent,\n fullscreenViewOverlayComponent: FullscreenOverlayComponent = () => null,\n sectionHeaderComponent: SectionHeaderComponent,\n sectionHeaderStyle,\n assets,\n thumbnailStyle,\n onSelectionChange,\n onOverlayPreloadRequested,\n onSectionHeadersVisible,\n debugLabels = false,\n onThumbnailPress,\n fullscreenViewOverlayStyle,\n onPreviewMenuOptionSelected,\n contextMenuOptions,\n initiallySelected,\n ...props\n }: ExpoSimpleGalleryViewProps,\n forwardedRef\n ) {\n const { width } = useWindowDimensions();\n const { thumbnailWidth, thumbnailHeight, thumbnailStyleProcessed } = useThumbnailDimensions({\n thumbnailStyle,\n contentContainerStyle: props.contentContainerStyle,\n columnsCount: props.columnsCount,\n });\n\n const openImageViewer = useCallback((index: number) => {\n setInitialIndex(index);\n setModalVisible(true);\n }, []);\n\n const thumbnailPressActionRef = useRef(props.thumbnailPressAction);\n useEffect(() => {\n thumbnailPressActionRef.current = props.thumbnailPressAction;\n }, [props.thumbnailPressAction]);\n\n const internalRef = useRef<ExpoSimpleGalleryMethods>(null);\n useImperativeHandle(forwardedRef, () => ({\n centerOnIndex: async (index: number) => {\n internalRef.current?.centerOnIndex(index);\n },\n setSelected: async (uris: string[]) => {\n internalRef.current?.setSelected(uris);\n },\n setThumbnailPressAction: async (\n action: ExpoSimpleGalleryViewProps['thumbnailPressAction']\n ) => {\n thumbnailPressActionRef.current = action;\n internalRef.current?.setThumbnailPressAction(action);\n },\n setThumbnailLongPressAction: async (\n action: ExpoSimpleGalleryViewProps['thumbnailLongPressAction']\n ) => {\n internalRef.current?.setThumbnailLongPressAction(action);\n },\n setThumbnailPanAction: async (action: ExpoSimpleGalleryViewProps['thumbnailPanAction']) => {\n internalRef.current?.setThumbnailPanAction(action);\n },\n setContextMenuOptions: async (options: UIAction[]) => {\n internalRef.current?.setContextMenuOptions(options);\n },\n openImageViewer,\n closeImageViewer: () => {\n setModalVisible(false);\n },\n }));\n\n const [modalVisible, setModalVisible] = useState(false);\n const [initialIndex, setInitialIndex] = useState(0);\n\n const [selectedUris, setSelectedUris] = useState<Set<string>>(new Set());\n\n const [visibleRange, setVisibleRange] = useState<[number, number]>([0, 0]);\n const visibleRangeMin = useMemo(() => visibleRange[0], [visibleRange]);\n const visibleRangeMax = useMemo(() => visibleRange[1], [visibleRange]);\n\n const [visibleHeaders, setVisibleHeaders] = useState<number[]>([0]);\n const visibleHeadersRangeMin = useMemo(() => Math.min(...visibleHeaders), [visibleHeaders]);\n const visibleHeadersRangeMax = useMemo(() => Math.max(...visibleHeaders), [visibleHeaders]);\n\n const handleSelectionChange = useCallback(\n (event: NativeSyntheticEvent<{ selected: string[] }>) => {\n setSelectedUris(new Set(event.nativeEvent.selected));\n onSelectionChange?.(event);\n },\n [onSelectionChange]\n );\n\n const handleOverlayPreloadRequest = useCallback(\n (event: NativeSyntheticEvent<{ range: [number, number] }>) => {\n const [start, end] = event.nativeEvent.range;\n setVisibleRange([start, end]);\n onOverlayPreloadRequested?.(event);\n },\n [onOverlayPreloadRequested]\n );\n\n const handleSectionHeadersVisible = useCallback(\n (event: NativeSyntheticEvent<{ sections: number[] }>) => {\n setVisibleHeaders(event.nativeEvent.sections);\n onSectionHeadersVisible?.(event);\n },\n [onSectionHeadersVisible]\n );\n\n const handleThumbnailPress = useCallback(\n (event: NativeSyntheticEvent<GalleryItem>) => {\n if (thumbnailPressActionRef.current === 'open') {\n openImageViewer(event.nativeEvent.index);\n }\n onThumbnailPress?.(event);\n },\n [onThumbnailPress, openImageViewer]\n );\n\n const handleModalClose = useCallback((event: NativeSyntheticEvent<GalleryItem>) => {\n const index = event.nativeEvent.index;\n setModalVisible(false);\n internalRef.current?.centerOnIndex(index);\n }, []);\n\n const thumbnailOverlays = useMemo(\n () =>\n assets.flat().map((uri, index) =>\n ThumbnailOverlayComponent ? (\n <MemoizedThumbnailOverlayComponent\n // biome-ignore lint/suspicious/noArrayIndexKey: we need to force re-render on order change\n key={`${uri}-${index}`}\n OverlayComponent={ThumbnailOverlayComponent}\n uri={uri}\n index={index}\n width={thumbnailWidth}\n height={thumbnailHeight}\n selected={selectedUris.has(uri)}\n debugLabels={debugLabels}\n isNull={\n !(\n index >= visibleRangeMin - OVERLAYS_BUFFER &&\n index <= visibleRangeMax + OVERLAYS_BUFFER\n )\n }\n // isNull={false}\n />\n ) : null\n ),\n [\n assets,\n ThumbnailOverlayComponent,\n thumbnailWidth,\n thumbnailHeight,\n selectedUris,\n visibleRangeMin,\n visibleRangeMax,\n debugLabels,\n ]\n );\n\n const sectionHeaders = useMemo(() => {\n if (!SectionHeaderComponent || !isNestedArray(assets)) return null;\n return assets.map((group, index) => (\n <MemoizedSectionHeader\n key={JSON.stringify(group)}\n SectionHeader={SectionHeaderComponent}\n index={index}\n width={width}\n height={Number.parseFloat((sectionHeaderStyle?.height ?? 0).toString())}\n debugLabels={debugLabels}\n isNull={\n !(\n index >= visibleHeadersRangeMin - OVERLAYS_BUFFER &&\n index <= visibleHeadersRangeMax + OVERLAYS_BUFFER\n )\n }\n />\n ));\n }, [\n SectionHeaderComponent,\n assets,\n sectionHeaderStyle?.height,\n debugLabels,\n width,\n visibleHeadersRangeMin,\n visibleHeadersRangeMax,\n ]);\n\n const children = useMemo(\n () => [sectionHeaders, thumbnailOverlays],\n [sectionHeaders, thumbnailOverlays]\n );\n\n const handlePreviewMenuOptionSelected = useCallback(\n (event: NativeSyntheticEvent<OnPreviewMenuOptionSelectedPayload>) => {\n const action = contextMenuOptions?.[event.nativeEvent.optionIndex]?.action;\n action?.({\n uri: event.nativeEvent.uri,\n index: event.nativeEvent.index,\n });\n },\n [contextMenuOptions]\n );\n\n const handleToggleSelection = useCallback(\n (uri: string, selected?: boolean) => {\n const shouldSetSelected = selected === undefined ? !selectedUris.has(uri) : selected;\n const newSet = new Set(selectedUris);\n if (shouldSetSelected) {\n newSet.add(uri);\n } else {\n newSet.delete(uri);\n }\n internalRef.current?.setSelected([...newSet]);\n },\n [selectedUris]\n );\n\n return (\n <>\n <NativeViewMemoized\n // key={assets.length}\n {...props}\n thumbnailStyle={thumbnailStyleProcessed}\n sectionHeaderStyle={sectionHeaderStyle}\n assets={assets}\n onSelectionChange={handleSelectionChange}\n onOverlayPreloadRequested={handleOverlayPreloadRequest}\n onSectionHeadersVisible={handleSectionHeadersVisible}\n onThumbnailPress={handleThumbnailPress}\n onPreviewMenuOptionSelected={handlePreviewMenuOptionSelected}\n contextMenuOptions={contextMenuOptions}\n onLayout={() => {\n if (initiallySelected) {\n internalRef.current?.setSelected(initiallySelected?.filter(isNotNullOrUndefined));\n }\n }}\n ref={internalRef}\n >\n {/* @ts-expect-error type of children is intentionally set to never | undefined */}\n {children}\n </NativeViewMemoized>\n <GalleryModal\n visible={modalVisible}\n uris={assets.flat()}\n initialIndex={initialIndex}\n onClose={handleModalClose}\n selectedUris={selectedUris}\n overlayComponent={FullscreenOverlayComponent}\n style={fullscreenViewOverlayStyle}\n toggleSelection={handleToggleSelection}\n />\n </>\n );\n }\n);\n\nfunction useThumbnailDimensions({\n thumbnailStyle,\n contentContainerStyle,\n columnsCount = 2,\n}: {\n thumbnailStyle: ExpoSimpleGalleryViewProps['thumbnailStyle'];\n contentContainerStyle: ExpoSimpleGalleryViewProps['contentContainerStyle'];\n columnsCount?: number;\n}) {\n const { width } = useWindowDimensions();\n const thumbnailStyleProcessed = useMemo(() => {\n if (!thumbnailStyle?.borderColor) return thumbnailStyle;\n const { borderColor } = thumbnailStyle;\n return {\n ...thumbnailStyle,\n borderColor: (processColor(borderColor) as ColorValue) ?? undefined,\n };\n }, [thumbnailStyle]);\n const { thumbnailWidth, thumbnailHeight } = useMemo(() => {\n const thumbnailAspectRatio =\n Number.parseFloat((thumbnailStyleProcessed?.aspectRatio as string) ?? '') || 1;\n\n const thumbnailsSpacing = contentContainerStyle?.gap\n ? Number.parseInt(contentContainerStyle?.gap.toString())\n : 0;\n const paddingLeft =\n contentContainerStyle?.paddingLeft ??\n contentContainerStyle?.paddingHorizontal ??\n contentContainerStyle?.padding ??\n 0;\n const paddingRight =\n contentContainerStyle?.paddingRight ??\n contentContainerStyle?.paddingHorizontal ??\n contentContainerStyle?.padding ??\n 0;\n const padding =\n Number.parseFloat(paddingLeft as string) + Number.parseFloat(paddingRight as string);\n const thumbnailWidth =\n (width - padding - (columnsCount - 1) * thumbnailsSpacing) / columnsCount;\n const thumbnailHeight = thumbnailWidth / thumbnailAspectRatio;\n return { thumbnailWidth, thumbnailHeight };\n }, [width, thumbnailStyleProcessed, columnsCount, contentContainerStyle]);\n return { thumbnailWidth, thumbnailHeight, thumbnailStyleProcessed };\n}\n"]}
|
|
@@ -40,38 +40,41 @@ final class ExpoSimpleGalleryView: ExpoView, ContextMenuActionsDelegate {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
override func mountChildComponentView(_ childComponentView: UIView, index: Int) {
|
|
43
|
-
DispatchQueue.main.async { [weak self] in
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
// DispatchQueue.main.async { [weak self] in
|
|
44
|
+
// guard let self else { return }
|
|
45
|
+
guard childComponentView.superview == nil else { return }
|
|
46
|
+
guard let label = childComponentView.accessibilityLabel else {
|
|
47
|
+
self.callSuperMountChildComponentView(childComponentView, index: index)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if label.starts(with: "GalleryViewOverlay_") {
|
|
52
|
+
guard let id = Int(label.replacingOccurrences(of: "GalleryViewOverlay_", with: "")) else {
|
|
48
53
|
return
|
|
49
54
|
}
|
|
55
|
+
let component = ReactMountingComponent(view: childComponentView, index: index)
|
|
56
|
+
self.overlays["thumbnail"]?[id] = component
|
|
50
57
|
|
|
51
|
-
if
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
if let cell = self.galleryView?.cell(withIndex: id) {
|
|
59
|
+
self.mount(to: cell, overlay: component)
|
|
60
|
+
}
|
|
61
|
+
} else if label.starts(with: "SectionHeaderOverlay_") {
|
|
62
|
+
guard let sectionId = Int(label.replacingOccurrences(of: "SectionHeaderOverlay_", with: ""))
|
|
63
|
+
else { return }
|
|
64
|
+
let component = ReactMountingComponent(view: childComponentView, index: index)
|
|
65
|
+
self.overlays["sectionHeader"]?[sectionId] = component
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if let galleryView = self.galleryView, galleryView.isGroupedLayout {
|
|
65
|
-
let indexPath = IndexPath(item: 0, section: sectionId)
|
|
66
|
-
if let headerView = galleryView.supplementaryView(
|
|
67
|
-
forElementKind: UICollectionView.elementKindSectionHeader,
|
|
68
|
-
at: indexPath) as? GallerySectionHeaderView
|
|
69
|
-
{
|
|
70
|
-
self.mount(to: headerView, overlay: component)
|
|
71
|
-
}
|
|
67
|
+
if let galleryView = self.galleryView, galleryView.isGroupedLayout {
|
|
68
|
+
let indexPath = IndexPath(item: 0, section: sectionId)
|
|
69
|
+
if let headerView = galleryView.supplementaryView(
|
|
70
|
+
forElementKind: UICollectionView.elementKindSectionHeader,
|
|
71
|
+
at: indexPath) as? GallerySectionHeaderView
|
|
72
|
+
{
|
|
73
|
+
self.mount(to: headerView, overlay: component)
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
}
|
|
77
|
+
// }
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
override func unmountChildComponentView(_ childComponentView: UIView, index: Int) {
|
|
@@ -80,10 +83,13 @@ final class ExpoSimpleGalleryView: ExpoView, ContextMenuActionsDelegate {
|
|
|
80
83
|
guard let label = childComponentView.accessibilityLabel else { return }
|
|
81
84
|
|
|
82
85
|
if label.starts(with: "GalleryViewOverlay_") {
|
|
83
|
-
guard let id = Int(label.replacingOccurrences(of: "GalleryViewOverlay_", with: "")) else {
|
|
86
|
+
guard let id = Int(label.replacingOccurrences(of: "GalleryViewOverlay_", with: "")) else {
|
|
87
|
+
return
|
|
88
|
+
}
|
|
84
89
|
overlays["thumbnail"]?[id] = nil
|
|
85
90
|
} else if label.starts(with: "SectionHeaderOverlay_") {
|
|
86
|
-
guard let sectionId = Int(label.replacingOccurrences(of: "SectionHeaderOverlay_", with: ""))
|
|
91
|
+
guard let sectionId = Int(label.replacingOccurrences(of: "SectionHeaderOverlay_", with: ""))
|
|
92
|
+
else { return }
|
|
87
93
|
overlays["sectionHeader"]?[sectionId] = nil
|
|
88
94
|
}
|
|
89
95
|
}
|
|
@@ -151,14 +157,29 @@ extension ExpoSimpleGalleryView: OverlayMountingDelegate {
|
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
func mount<T: OverlayContainer>(to container: T, overlay: ReactMountingComponent) {
|
|
154
|
-
DispatchQueue.main.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
|
|
161
|
+
// guard let self else { return }
|
|
162
|
+
|
|
163
|
+
// if overlay.view.superview == container.overlayContainer {
|
|
164
|
+
// // Already mounted, no need to remount
|
|
165
|
+
// return
|
|
166
|
+
// } else
|
|
167
|
+
|
|
168
|
+
if overlay.view.superview != nil {
|
|
169
|
+
// If the overlay is already mounted somewhere else, unmount it first
|
|
170
|
+
self.unmount(overlay: overlay)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// guard overlay.view.superview == nil else { return }
|
|
174
|
+
if self.getMountedOverlayComponent(for: container) != nil {
|
|
175
|
+
self.unmount(from: container)
|
|
161
176
|
}
|
|
177
|
+
// guard self.getMountedOverlayComponent(for: container)?.view != overlay.view else { return }
|
|
178
|
+
// TODO: fix remounting after props (uris list) update
|
|
179
|
+
// container.overlayContainer.mountChildComponentView(overlay.view, index: overlay.index)
|
|
180
|
+
container.overlayContainer.addSubview(overlay.view)
|
|
181
|
+
overlay.view.didMoveToSuperview()
|
|
182
|
+
// }
|
|
162
183
|
}
|
|
163
184
|
|
|
164
185
|
func unmount<T: OverlayContainer>(from container: T) {
|
|
@@ -169,10 +190,16 @@ extension ExpoSimpleGalleryView: OverlayMountingDelegate {
|
|
|
169
190
|
}
|
|
170
191
|
|
|
171
192
|
func unmount(overlay: ReactMountingComponent) {
|
|
193
|
+
guard overlay.view.superview != nil else { return }
|
|
194
|
+
print("Unmounting overlay: \(overlay.view.accessibilityLabel ?? "unknown")")
|
|
195
|
+
print("Overlay index: \(overlay.index)")
|
|
196
|
+
print("Overlay parent: \(String(describing: overlay.view.superview))")
|
|
197
|
+
overlay.view.willMove(toSuperview: nil)
|
|
172
198
|
overlay.view.removeFromSuperview()
|
|
173
199
|
}
|
|
174
200
|
|
|
175
|
-
func getMountedOverlayComponent<T: OverlayContainer>(for container: T) -> ReactMountingComponent?
|
|
201
|
+
func getMountedOverlayComponent<T: OverlayContainer>(for container: T) -> ReactMountingComponent?
|
|
202
|
+
{
|
|
176
203
|
let (index, view) =
|
|
177
204
|
container.overlayContainer.subviews.enumerated().first(where: { $0.element is ExpoView }) ?? (
|
|
178
205
|
0, nil
|
|
@@ -46,14 +46,18 @@ extension GalleryGridView {
|
|
|
46
46
|
|
|
47
47
|
reloadData()
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
let
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
|
|
50
|
+
guard let self = self else { return }
|
|
51
|
+
|
|
52
|
+
if !uris.isEmpty {
|
|
53
|
+
let visibleItems = self.indexPathsForVisibleItems.map { $0.item }
|
|
54
|
+
if let minItem = visibleItems.min(), let maxItem = visibleItems.max() {
|
|
55
|
+
let range = (minItem, maxItem)
|
|
56
|
+
self.overlayPreloadingDelegate?.galleryGrid(self, prefetchOverlaysFor: range)
|
|
57
|
+
} else {
|
|
58
|
+
let initialRange = (0, min(uris.count - 1, 30))
|
|
59
|
+
self.overlayPreloadingDelegate?.galleryGrid(self, prefetchOverlaysFor: initialRange)
|
|
60
|
+
}
|
|
57
61
|
}
|
|
58
62
|
}
|
|
59
63
|
}
|
|
@@ -68,21 +72,25 @@ extension GalleryGridView {
|
|
|
68
72
|
|
|
69
73
|
reloadData()
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
let
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
|
|
76
|
+
guard let self = self else { return }
|
|
77
|
+
|
|
78
|
+
if !uris.isEmpty {
|
|
79
|
+
let visibleIndexPaths = self.indexPathsForVisibleItems
|
|
80
|
+
let flatIndices = visibleIndexPaths.compactMap { indexPath -> Int? in
|
|
81
|
+
// Find the corresponding flat index for this indexPath
|
|
82
|
+
sectionData.firstIndex { dict in
|
|
83
|
+
dict["sectionIndex"] == indexPath.section && dict["itemIndex"] == indexPath.item
|
|
84
|
+
}
|
|
77
85
|
}
|
|
78
|
-
}
|
|
79
86
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
if let minItem = flatIndices.min(), let maxItem = flatIndices.max() {
|
|
88
|
+
let range = (minItem, maxItem)
|
|
89
|
+
self.overlayPreloadingDelegate?.galleryGrid(self, prefetchOverlaysFor: range)
|
|
90
|
+
} else {
|
|
91
|
+
let initialRange = (0, min(uris.count - 1, 30))
|
|
92
|
+
self.overlayPreloadingDelegate?.galleryGrid(self, prefetchOverlaysFor: initialRange)
|
|
93
|
+
}
|
|
86
94
|
}
|
|
87
95
|
}
|
|
88
96
|
}
|
|
@@ -16,9 +16,9 @@ final class GalleryGridView: UICollectionView {
|
|
|
16
16
|
weak var overlayMountingDelegate: OverlayMountingDelegate?
|
|
17
17
|
weak var gestureEventDelegate: GestureEventDelegate?
|
|
18
18
|
weak var contextMenuActionsDelegate: ContextMenuActionsDelegate?
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
var contextMenuOptions: (Int, String) -> [UIAction] = { _, _ in [] }
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
var selectedAssets = Set<String>()
|
|
23
23
|
var lastVisitedIndexPath: IndexPath?
|
|
24
24
|
var firstVisitedCellWasSelected = false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-simple-gallery",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Image gallery view",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -14,12 +14,7 @@
|
|
|
14
14
|
"expo-module": "expo-module",
|
|
15
15
|
"open:ios": "xed example/ios"
|
|
16
16
|
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"react-native",
|
|
19
|
-
"expo",
|
|
20
|
-
"expo-simple-gallery",
|
|
21
|
-
"ExpoSimpleGallery"
|
|
22
|
-
],
|
|
17
|
+
"keywords": ["react-native", "expo", "expo-simple-gallery", "ExpoSimpleGallery"],
|
|
23
18
|
"repository": "https://github.com/sincerely-manny/expo-simple-gallery",
|
|
24
19
|
"bugs": {
|
|
25
20
|
"url": "https://github.com/sincerely-manny/expo-simple-gallery/issues"
|
|
@@ -29,11 +24,11 @@
|
|
|
29
24
|
"homepage": "https://github.com/sincerely-manny/expo-simple-gallery#readme",
|
|
30
25
|
"devDependencies": {
|
|
31
26
|
"@biomejs/biome": "^1.9.4",
|
|
32
|
-
"@types/react": "
|
|
33
|
-
"expo": "~
|
|
27
|
+
"@types/react": "19.0.0",
|
|
28
|
+
"expo": "~53.0.0",
|
|
34
29
|
"expo-module-scripts": "^4.0.3",
|
|
35
|
-
"react-native": "0.
|
|
36
|
-
"typescript": "^5.
|
|
30
|
+
"react-native": "0.79.2",
|
|
31
|
+
"typescript": "^5.8.0"
|
|
37
32
|
},
|
|
38
33
|
"peerDependencies": {
|
|
39
34
|
"expo": "*",
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireNativeViewManager } from 'expo-modules-core';
|
|
2
2
|
import { type ComponentType, useCallback, useMemo, useState } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
Modal,
|
|
5
|
-
type NativeSyntheticEvent,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
View,
|
|
8
|
-
} from 'react-native';
|
|
3
|
+
import { Modal, type NativeSyntheticEvent, StyleSheet, View } from 'react-native';
|
|
9
4
|
import type { GalleryItem } from './ExpoSimpleGallery.types';
|
|
10
|
-
import type {
|
|
11
|
-
GalleryModalProps,
|
|
12
|
-
GalleryViewerProps,
|
|
13
|
-
} from './ExpoSimpleGalleryModal.types';
|
|
5
|
+
import type { GalleryModalProps, GalleryViewerProps } from './ExpoSimpleGalleryModal.types';
|
|
14
6
|
|
|
15
7
|
const GalleryViewer: ComponentType<GalleryViewerProps> =
|
|
16
|
-
|
|
8
|
+
requireNativeViewManager('GalleryImageViewer');
|
|
17
9
|
|
|
18
10
|
export function GalleryModal({
|
|
19
11
|
visible,
|
|
@@ -27,10 +19,7 @@ export function GalleryModal({
|
|
|
27
19
|
}: GalleryModalProps) {
|
|
28
20
|
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
29
21
|
const [currentUri, setCurrentUri] = useState(uris[initialIndex] || '');
|
|
30
|
-
const selected = useMemo(
|
|
31
|
-
() => selectedUris.has(currentUri),
|
|
32
|
-
[selectedUris, currentUri]
|
|
33
|
-
);
|
|
22
|
+
const selected = useMemo(() => selectedUris.has(currentUri), [selectedUris, currentUri]);
|
|
34
23
|
|
|
35
24
|
const handlePageChange = useCallback(
|
|
36
25
|
(event: NativeSyntheticEvent<{ index: number; uri: string }>) => {
|
|
@@ -56,12 +45,7 @@ export function GalleryModal({
|
|
|
56
45
|
);
|
|
57
46
|
|
|
58
47
|
return (
|
|
59
|
-
<Modal
|
|
60
|
-
visible={visible}
|
|
61
|
-
transparent={true}
|
|
62
|
-
animationType="fade"
|
|
63
|
-
onRequestClose={onClose}
|
|
64
|
-
>
|
|
48
|
+
<Modal visible={visible} transparent={true} animationType="fade" onRequestClose={onClose}>
|
|
65
49
|
<View style={[styles.container, style]}>
|
|
66
50
|
<GalleryViewer
|
|
67
51
|
style={styles.viewer}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireNativeViewManager } from 'expo-modules-core';
|
|
2
2
|
import {
|
|
3
3
|
type ComponentType,
|
|
4
4
|
forwardRef,
|
|
@@ -32,7 +32,7 @@ import { MemoizedThumbnailOverlayComponent } from './components/MemoizedThumbnai
|
|
|
32
32
|
|
|
33
33
|
const NativeView: ComponentType<
|
|
34
34
|
ExpoSimpleGalleryViewProps & RefAttributes<ExpoSimpleGalleryMethods>
|
|
35
|
-
> =
|
|
35
|
+
> = requireNativeViewManager('ExpoSimpleGallery');
|
|
36
36
|
|
|
37
37
|
const NativeViewMemoized = memo(NativeView);
|
|
38
38
|
|
|
@@ -61,12 +61,11 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
61
61
|
forwardedRef
|
|
62
62
|
) {
|
|
63
63
|
const { width } = useWindowDimensions();
|
|
64
|
-
const { thumbnailWidth, thumbnailHeight, thumbnailStyleProcessed } =
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
});
|
|
64
|
+
const { thumbnailWidth, thumbnailHeight, thumbnailStyleProcessed } = useThumbnailDimensions({
|
|
65
|
+
thumbnailStyle,
|
|
66
|
+
contentContainerStyle: props.contentContainerStyle,
|
|
67
|
+
columnsCount: props.columnsCount,
|
|
68
|
+
});
|
|
70
69
|
|
|
71
70
|
const openImageViewer = useCallback((index: number) => {
|
|
72
71
|
setInitialIndex(index);
|
|
@@ -97,9 +96,7 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
97
96
|
) => {
|
|
98
97
|
internalRef.current?.setThumbnailLongPressAction(action);
|
|
99
98
|
},
|
|
100
|
-
setThumbnailPanAction: async (
|
|
101
|
-
action: ExpoSimpleGalleryViewProps['thumbnailPanAction']
|
|
102
|
-
) => {
|
|
99
|
+
setThumbnailPanAction: async (action: ExpoSimpleGalleryViewProps['thumbnailPanAction']) => {
|
|
103
100
|
internalRef.current?.setThumbnailPanAction(action);
|
|
104
101
|
},
|
|
105
102
|
setContextMenuOptions: async (options: UIAction[]) => {
|
|
@@ -121,14 +118,8 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
121
118
|
const visibleRangeMax = useMemo(() => visibleRange[1], [visibleRange]);
|
|
122
119
|
|
|
123
120
|
const [visibleHeaders, setVisibleHeaders] = useState<number[]>([0]);
|
|
124
|
-
const visibleHeadersRangeMin = useMemo(
|
|
125
|
-
|
|
126
|
-
[visibleHeaders]
|
|
127
|
-
);
|
|
128
|
-
const visibleHeadersRangeMax = useMemo(
|
|
129
|
-
() => Math.max(...visibleHeaders),
|
|
130
|
-
[visibleHeaders]
|
|
131
|
-
);
|
|
121
|
+
const visibleHeadersRangeMin = useMemo(() => Math.min(...visibleHeaders), [visibleHeaders]);
|
|
122
|
+
const visibleHeadersRangeMax = useMemo(() => Math.max(...visibleHeaders), [visibleHeaders]);
|
|
132
123
|
|
|
133
124
|
const handleSelectionChange = useCallback(
|
|
134
125
|
(event: NativeSyntheticEvent<{ selected: string[] }>) => {
|
|
@@ -165,20 +156,19 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
165
156
|
[onThumbnailPress, openImageViewer]
|
|
166
157
|
);
|
|
167
158
|
|
|
168
|
-
const handleModalClose = useCallback(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
[]
|
|
174
|
-
);
|
|
159
|
+
const handleModalClose = useCallback((event: NativeSyntheticEvent<GalleryItem>) => {
|
|
160
|
+
const index = event.nativeEvent.index;
|
|
161
|
+
setModalVisible(false);
|
|
162
|
+
internalRef.current?.centerOnIndex(index);
|
|
163
|
+
}, []);
|
|
175
164
|
|
|
176
165
|
const thumbnailOverlays = useMemo(
|
|
177
166
|
() =>
|
|
178
167
|
assets.flat().map((uri, index) =>
|
|
179
168
|
ThumbnailOverlayComponent ? (
|
|
180
169
|
<MemoizedThumbnailOverlayComponent
|
|
181
|
-
|
|
170
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: we need to force re-render on order change
|
|
171
|
+
key={`${uri}-${index}`}
|
|
182
172
|
OverlayComponent={ThumbnailOverlayComponent}
|
|
183
173
|
uri={uri}
|
|
184
174
|
index={index}
|
|
@@ -216,9 +206,7 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
216
206
|
SectionHeader={SectionHeaderComponent}
|
|
217
207
|
index={index}
|
|
218
208
|
width={width}
|
|
219
|
-
height={Number.parseFloat(
|
|
220
|
-
(sectionHeaderStyle?.height ?? 0).toString()
|
|
221
|
-
)}
|
|
209
|
+
height={Number.parseFloat((sectionHeaderStyle?.height ?? 0).toString())}
|
|
222
210
|
debugLabels={debugLabels}
|
|
223
211
|
isNull={
|
|
224
212
|
!(
|
|
@@ -245,8 +233,7 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
245
233
|
|
|
246
234
|
const handlePreviewMenuOptionSelected = useCallback(
|
|
247
235
|
(event: NativeSyntheticEvent<OnPreviewMenuOptionSelectedPayload>) => {
|
|
248
|
-
const action =
|
|
249
|
-
contextMenuOptions?.[event.nativeEvent.optionIndex]?.action;
|
|
236
|
+
const action = contextMenuOptions?.[event.nativeEvent.optionIndex]?.action;
|
|
250
237
|
action?.({
|
|
251
238
|
uri: event.nativeEvent.uri,
|
|
252
239
|
index: event.nativeEvent.index,
|
|
@@ -257,8 +244,7 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
257
244
|
|
|
258
245
|
const handleToggleSelection = useCallback(
|
|
259
246
|
(uri: string, selected?: boolean) => {
|
|
260
|
-
const shouldSetSelected =
|
|
261
|
-
selected === undefined ? !selectedUris.has(uri) : selected;
|
|
247
|
+
const shouldSetSelected = selected === undefined ? !selectedUris.has(uri) : selected;
|
|
262
248
|
const newSet = new Set(selectedUris);
|
|
263
249
|
if (shouldSetSelected) {
|
|
264
250
|
newSet.add(uri);
|
|
@@ -273,6 +259,7 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
273
259
|
return (
|
|
274
260
|
<>
|
|
275
261
|
<NativeViewMemoized
|
|
262
|
+
// key={assets.length}
|
|
276
263
|
{...props}
|
|
277
264
|
thumbnailStyle={thumbnailStyleProcessed}
|
|
278
265
|
sectionHeaderStyle={sectionHeaderStyle}
|
|
@@ -285,9 +272,7 @@ export default forwardRef<ExpoSimpleGalleryMethods, ExpoSimpleGalleryViewProps>(
|
|
|
285
272
|
contextMenuOptions={contextMenuOptions}
|
|
286
273
|
onLayout={() => {
|
|
287
274
|
if (initiallySelected) {
|
|
288
|
-
internalRef.current?.setSelected(
|
|
289
|
-
initiallySelected?.filter(isNotNullOrUndefined)
|
|
290
|
-
);
|
|
275
|
+
internalRef.current?.setSelected(initiallySelected?.filter(isNotNullOrUndefined));
|
|
291
276
|
}
|
|
292
277
|
}}
|
|
293
278
|
ref={internalRef}
|
|
@@ -330,9 +315,7 @@ function useThumbnailDimensions({
|
|
|
330
315
|
}, [thumbnailStyle]);
|
|
331
316
|
const { thumbnailWidth, thumbnailHeight } = useMemo(() => {
|
|
332
317
|
const thumbnailAspectRatio =
|
|
333
|
-
Number.parseFloat(
|
|
334
|
-
(thumbnailStyleProcessed?.aspectRatio as string) ?? ''
|
|
335
|
-
) || 1;
|
|
318
|
+
Number.parseFloat((thumbnailStyleProcessed?.aspectRatio as string) ?? '') || 1;
|
|
336
319
|
|
|
337
320
|
const thumbnailsSpacing = contentContainerStyle?.gap
|
|
338
321
|
? Number.parseInt(contentContainerStyle?.gap.toString())
|
|
@@ -348,8 +331,7 @@ function useThumbnailDimensions({
|
|
|
348
331
|
contentContainerStyle?.padding ??
|
|
349
332
|
0;
|
|
350
333
|
const padding =
|
|
351
|
-
Number.parseFloat(paddingLeft as string) +
|
|
352
|
-
Number.parseFloat(paddingRight as string);
|
|
334
|
+
Number.parseFloat(paddingLeft as string) + Number.parseFloat(paddingRight as string);
|
|
353
335
|
const thumbnailWidth =
|
|
354
336
|
(width - padding - (columnsCount - 1) * thumbnailsSpacing) / columnsCount;
|
|
355
337
|
const thumbnailHeight = thumbnailWidth / thumbnailAspectRatio;
|