stream-chat-react-native-core
Version:
The official React Native and Expo components for Stream Chat, a service for building chat applications
190 lines (180 loc) • 4.61 kB
text/typescript
import type { Attachment } from 'stream-chat';
import { buildThumbnail } from './buildThumbnail';
import type { GallerySizeAndThumbnailGrid, GallerySizeConfig, ThumbnailGrid } from './types';
import { ChatConfigContextValue } from '../../../../contexts/chatConfigContext/ChatConfigContext';
/**
* Builds a grid of thumbnail images from image attachments.
* This function take a object parameter with following properties:
*
* @params
*
* - {number[][]} grid - Grid pattern of the gallery. Each numeric value in the array represents the flex value of corresponding image in grid.
* - {Attachment[]} images - Array of image attachments.
* - {GallerySizeConfig} sizeConfig - Theme config for the gallery.
* - {boolean} invertedDirections - Whether to invert the direction of the grid. By default grid is rendered with column as primary direction and row as secondary direction.
*
* @usage
*
* ```
* const { thumbnailGrid, invertedDirection } = buildThumbnailGrid({
* grid: [[1], [1]],
* images: [image1, image2],
* sizeConfig: {
* gridHeight: 200,
* gridWidth: 200,
* maxHeight: 200,
* maxWidth: 200,
* minHeight: 200,
* minWidth: 200,
* },
* })
*
* Rendering logic on UI:
*
* ```
* <View style={{ flexDirection: invertedDirection ? 'row' : 'column }}>
* {
* thumbnailGrid.forEach(rows => {
* return (
* <View style={{ flexDirection: invertedDirection ? 'column' : 'row' }}>
* {
* rows.forEach(thumbnail => (
* <Image
* source={{ uri: thumbnail.url }}
* resizeMode={thumbnail.resizeMode}
* width={thumbnail.width}
* height={thumbnail.height}
* />
* ))}
* </View>
* )});
* }
* </View>
* ```
*
* Lets look at different examples of grid and invertedDirections param:
*
* EXAMPLE 1:
*
* ```
* {
* grid: [[2, 1], [2, 1]]
* invertedDirections: false
* }
* ```
*
* Resulting thumbnail grid on rendered UI:
*
* __________________
* | | |
* | | |
* |------------------|
* | | |
* | | |
* ------------------
*
* EXAMPLE 2:
*
* ```
* {
* grid: [[2, 1], [2, 1]]
* invertedDirections: true
* }
* ```
* Resulting thumbnail grid on rendered UI:
* __________________
* | | |
* | | |
* | | |
* | | |
* |------------------|
* | | |
* | | |
* ------------------
*
* EXAMPLE 3:
*
* ```
* {
* grid: [[2, 1]]
* invertedDirections: false
* }
* ```
* Resulting thumbnail grid on rendered UI:
* __________________
* | |
* | |
* | |
* | |
* |------------------|
* | |
* | |
* ------------------
*
* EXAMPLE 4:
*
* ```
* {
* grid: [[2, 1]]
* invertedDirections: true
* }
* ```
* Resulting thumbnail grid on rendered UI:
* __________________
* | | |
* | | |
* | | |
* | | |
* | | |
* ------------------
*
* @return {GallerySizeAndThumbnailGrid}
*/
export function buildThumbnailGrid({
grid,
images,
invertedDirections = false,
resizableCDNHosts,
sizeConfig,
}: Pick<ChatConfigContextValue, 'resizableCDNHosts'> & {
grid: number[][];
images: Attachment[];
invertedDirections: boolean;
sizeConfig: GallerySizeConfig;
}): GallerySizeAndThumbnailGrid {
const { gridHeight, gridWidth } = sizeConfig;
let imageIndex = 0;
const thumbnailGrid: ThumbnailGrid = [];
const numOfColumns = grid.length;
grid.forEach((rows, colIndex) => {
const totalFlexValue = rows.reduce((acc, curr) => acc + curr, 0);
rows.forEach((flexValue) => {
const tHeight = invertedDirections
? gridHeight / numOfColumns
: gridHeight * (flexValue / totalFlexValue);
const tWidth = invertedDirections
? gridWidth * (flexValue / totalFlexValue)
: gridWidth / numOfColumns;
const currentImage = images[imageIndex];
const thumbnail = buildThumbnail({
flex: flexValue,
height: tHeight,
image: currentImage,
resizableCDNHosts,
resizeMode: 'cover',
width: tWidth,
});
if (!thumbnailGrid[colIndex]) {
thumbnailGrid[colIndex] = [];
}
thumbnailGrid[colIndex].push(thumbnail);
imageIndex++;
});
});
return {
height: gridHeight,
invertedDirections,
thumbnailGrid,
width: gridWidth,
};
}