mattermost-mobile-upstream/app/components/block_renderer/utils/image.ts
Daniel Espino García 84ea188366
Mattermost Blocks (#9764)
* Mattermost Blocks

* Move block renderer to its own components folder

* Sync translation layer

* UX fixes

* Refactor button to use the button component

* Code review

* Fix CI

* Add animations to collapse blocks

* Add unit tests

* Add e2e tests and related fixes

* Address coderabbit comments

* Address UX comments

* Address feedback

* Address coderabbit comments

* Fix snapshots

* Sync with webapp translation

* Add node limit to button markdown node

* Address feedback

* i18n-extract

* Fix test

* Move image utils to the utils folder

* Remove unneeded style

* Revert build script change

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2026-06-29 18:42:16 +02:00

100 lines
3.1 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {IMAGE_MAX_HEIGHT} from '@constants/image';
import {calculateDimensions} from '@utils/images';
/** Preset caps loosely aligned with Adaptive Cards `Image` sizes; `stretch` matches legacy attachment `image_url`. */
export const MM_IMAGE_SIZE_CAPS: Record<MmImageSize, {maxWidth: number; maxHeight: number} | null> = {
auto: null,
xsmall: {maxWidth: 108, maxHeight: 64},
small: {maxWidth: 204, maxHeight: 120},
medium: {maxWidth: 320, maxHeight: 184},
large: {maxWidth: 428, maxHeight: 240},
stretch: {maxWidth: 500, maxHeight: 350},
};
export function resolveMmImageCaps(block: MmImageBlock): {maxWidth?: number; maxHeight?: number} {
const size = block.size ?? 'stretch';
const preset = MM_IMAGE_SIZE_CAPS[size];
const maxWidth = block.max_width ?? preset?.maxWidth;
const maxHeight = block.max_height ?? preset?.maxHeight;
if (size === 'auto' && block.max_width === undefined && block.max_height === undefined) {
return {};
}
const out: {maxWidth?: number; maxHeight?: number} = {};
if (maxWidth !== undefined) {
out.maxWidth = maxWidth;
}
if (maxHeight !== undefined) {
out.maxHeight = maxHeight;
}
return out;
}
export type MmBlocksImageLayout = {
width: number;
height: number;
galleryWidth: number;
galleryHeight: number;
};
export function computeMmBlocksImageLayout(
caps: {maxWidth?: number; maxHeight?: number},
layoutWidth: number | undefined,
metadata: PostImage | undefined,
viewPortWidth: number,
): MmBlocksImageLayout {
const viewport = layoutWidth ? Math.min(layoutWidth, viewPortWidth) : viewPortWidth;
const maxW = caps.maxWidth ?? viewport;
const maxH = caps.maxHeight ?? IMAGE_MAX_HEIGHT;
if (metadata?.width && metadata?.height) {
const {width, height} = calculateDimensions(
metadata.height,
metadata.width,
Math.min(viewport, maxW),
maxH,
);
return {
width,
height,
galleryWidth: metadata.width,
galleryHeight: metadata.height,
};
}
const width = Math.min(maxW, viewport);
const height = Math.min(maxH, Math.round(width * 0.75));
return {
width,
height,
galleryWidth: width,
galleryHeight: height,
};
}
export function refineMmBlocksImageLayoutFromIntrinsic(
intrinsicWidth: number,
intrinsicHeight: number,
caps: {maxWidth?: number; maxHeight?: number},
layoutWidth: number | undefined,
viewPortWidth: number,
): MmBlocksImageLayout {
const viewport = layoutWidth ? Math.min(layoutWidth, viewPortWidth) : viewPortWidth;
const maxW = caps.maxWidth ?? viewport;
const maxH = caps.maxHeight ?? IMAGE_MAX_HEIGHT;
const {width, height} = calculateDimensions(
intrinsicHeight,
intrinsicWidth,
Math.min(viewport, maxW),
maxH,
);
return {
width,
height,
galleryWidth: intrinsicWidth,
galleryHeight: intrinsicHeight,
};
}