diff --git a/native/chat/settings/thread-settings-media-gallery.react.js b/native/chat/settings/thread-settings-media-gallery.react.js
--- a/native/chat/settings/thread-settings-media-gallery.react.js
+++ b/native/chat/settings/thread-settings-media-gallery.react.js
@@ -1,16 +1,26 @@
// @flow
+import { useNavigation, useRoute } from '@react-navigation/native';
import * as React from 'react';
import { View, useWindowDimensions } from 'react-native';
+import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
import { FlatList } from 'react-native-gesture-handler';
import { fetchThreadMedia } from 'lib/actions/thread-actions.js';
-import type { MediaInfo } from 'lib/types/media-types';
+import type { MediaInfo, Media } from 'lib/types/media-types';
import { useServerCall } from 'lib/utils/action-utils.js';
import GestureTouchableOpacity from '../../components/gesture-touchable-opacity.react.js';
import Multimedia from '../../media/multimedia.react.js';
+import {
+ ImageModalRouteName,
+ VideoPlaybackModalRouteName,
+} from '../../navigation/route-names.js';
import { useStyles } from '../../themes/colors.js';
+import type {
+ LayoutCoordinates,
+ VerticalBounds,
+} from '../../types/layout-types.js';
const galleryItemGap = 8;
const numColumns = 3;
@@ -18,6 +28,7 @@
type ThreadSettingsMediaGalleryProps = {
+threadID: string,
+limit: number,
+ +verticalBounds: ?VerticalBounds,
};
function ThreadSettingsMediaGallery(
@@ -36,7 +47,7 @@
const galleryItemWidth =
(width - 32 - (numColumns - 1) * galleryItemGap) / numColumns;
- const { threadID, limit } = props;
+ const { threadID, limit, verticalBounds } = props;
const [mediaInfos, setMediaInfos] = React.useState([]);
const callFetchThreadMedia = useServerCall(fetchThreadMedia);
@@ -73,30 +84,16 @@
}, [galleryItemWidth, styles.media, styles.mediaContainer]);
const renderItem = React.useCallback(
- ({ item, index }) => {
- const containerStyle =
- index % numColumns === 0
- ? memoizedStyles.mediaContainer
- : memoizedStyles.mediaContainerWithMargin;
-
- const mediaInfoItem: MediaInfo = {
- ...item,
- index,
- };
-
- return (
-
-
-
-
-
- );
- },
- [
- memoizedStyles.media,
- memoizedStyles.mediaContainer,
- memoizedStyles.mediaContainerWithMargin,
- ],
+ ({ item, index }) => (
+
+ ),
+ [threadID, verticalBounds, memoizedStyles],
);
return (
@@ -110,6 +107,76 @@
);
}
+type MediaGalleryItemProps = {
+ +item: Media,
+ +index: number,
+ +memoizedStyles: {
+ +mediaContainer: ViewStyleProp,
+ +mediaContainerWithMargin: ViewStyleProp,
+ +media: ViewStyleProp,
+ },
+ +threadID: string,
+ +verticalBounds: ?VerticalBounds,
+};
+
+function MediaGalleryItem(props: MediaGalleryItemProps): React.Node {
+ const navigation = useNavigation();
+ const route = useRoute();
+ const ref = React.useRef(null);
+ const onLayout = React.useCallback(() => {}, []);
+ const { threadID, verticalBounds, memoizedStyles, item, index } = props;
+
+ const mediaInfo: MediaInfo = React.useMemo(
+ () => ({
+ ...(item: Media),
+ index,
+ }),
+ [item, index],
+ );
+
+ const navigateToMedia = React.useCallback(() => {
+ ref.current?.measure((x, y, width, height, pageX, pageY) => {
+ const initialCoordinates: LayoutCoordinates = {
+ x: pageX,
+ y: pageY,
+ width,
+ height,
+ };
+
+ navigation.navigate<'VideoPlaybackModal' | 'ImageModal'>({
+ name:
+ mediaInfo.type === 'video'
+ ? VideoPlaybackModalRouteName
+ : ImageModalRouteName,
+ key: `multimedia|${threadID}|${mediaInfo.id}`,
+ params: {
+ presentedFrom: route.key,
+ mediaInfo,
+ item,
+ initialCoordinates,
+ verticalBounds,
+ },
+ });
+ });
+ }, [navigation, route, threadID, mediaInfo, item, verticalBounds]);
+
+ const containerStyle =
+ index % numColumns === 0
+ ? memoizedStyles.mediaContainer
+ : memoizedStyles.mediaContainerWithMargin;
+
+ return (
+
+
+
+
+
+ );
+}
+
const unboundStyles = {
flatListContainer: {
paddingHorizontal: 16,
diff --git a/native/chat/settings/thread-settings.react.js b/native/chat/settings/thread-settings.react.js
--- a/native/chat/settings/thread-settings.react.js
+++ b/native/chat/settings/thread-settings.react.js
@@ -208,6 +208,7 @@
+key: string,
+threadInfo: ThreadInfo,
+limit: number,
+ +verticalBounds: ?VerticalBounds,
}
| {
+itemType: 'promoteSidebar' | 'leaveThread' | 'deleteThread',
@@ -635,7 +636,8 @@
mediaGalleryListDataSelector = createSelector(
(propsAndState: PropsAndState) => propsAndState.threadInfo,
- (threadInfo: ThreadInfo) => {
+ (propsAndState: PropsAndState) => propsAndState.verticalBounds,
+ (threadInfo: ThreadInfo, verticalBounds: ?VerticalBounds) => {
const listData: ChatSettingsItem[] = [];
const limit = 6;
@@ -652,6 +654,7 @@
key: 'mediaGallery',
threadInfo,
limit,
+ verticalBounds,
});
listData.push({
@@ -953,6 +956,7 @@
);
} else if (item.itemType === 'leaveThread') {