Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix badges on narrow images and videos #1614

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/app/components/message/attachment/Attachment.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const Attachment = recipe({
backgroundColor: color.SurfaceVariant.Container,
color: color.SurfaceVariant.OnContainer,
borderRadius: config.radii.R400,
overflow: 'hidden',
maxWidth: '100%',
width: toRem(400),
},
Expand All @@ -32,7 +31,6 @@ export const AttachmentBox = style([
maxWidth: '100%',
maxHeight: toRem(600),
width: toRem(400),
overflow: 'hidden',
},
]);

Expand Down
24 changes: 17 additions & 7 deletions src/app/organisms/room/RoomTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ import {
selectTab,
} from '../../../client/action/navigation';
import { useForceUpdate } from '../../hooks/useForceUpdate';
import { parseGeoUri, scaleYDimension } from '../../utils/common';
import { parseGeoUri, scaleDimension } from '../../utils/common';
import { useMatrixEventRenderer } from '../../hooks/useMatrixEventRenderer';
import { useRoomMsgContentRenderer } from '../../hooks/useRoomMsgContentRenderer';
import { IAudioContent, IImageContent, IVideoContent } from '../../../types/matrix/common';
Expand Down Expand Up @@ -1100,13 +1100,16 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
if (typeof mxcUrl !== 'string') {
return null;
}
const height = scaleYDimension(imgInfo?.w || 400, 400, imgInfo?.h || 400);
const dim = scaleDimension(imgInfo?.w || 400, imgInfo?.h || 400, 32, 32, 400, 600);

return (
<Attachment>
<Attachment style={{
width: toRem(dim.w)
}}>
<AttachmentBox
style={{
height: toRem(height < 48 ? 48 : height),
width: toRem(dim.w),
height: toRem(dim.h),
}}
>
<ImageContent
Expand All @@ -1116,6 +1119,8 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
url={mxcUrl}
encInfo={content.file}
autoPlay={mediaAutoLoad}
imageWidth={dim.w}
imageHeight={dim.h}
/>
</AttachmentBox>
</Attachment>
Expand All @@ -1135,13 +1140,16 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
return null;
}

const height = scaleYDimension(videoInfo.w || 400, 400, videoInfo.h || 400);
const dim = scaleDimension(videoInfo.w || 400, videoInfo.h || 400, 48, 48, 400, 600);

return (
<Attachment>
<Attachment style={{
width: toRem(dim.w)
}}>
<AttachmentBox
style={{
height: toRem(height < 48 ? 48 : height),
width: toRem(dim.w),
height: toRem(dim.h),
}}
>
<VideoContent
Expand All @@ -1151,6 +1159,8 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
url={mxcUrl}
encInfo={content.file}
loadThumbnail={mediaAutoLoad}
videoWidth={dim.w}
videoHeight={dim.h}
/>
</AttachmentBox>
</Attachment>
Expand Down
24 changes: 21 additions & 3 deletions src/app/organisms/room/message/ImageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
Tooltip,
TooltipProvider,
as,
toRem,
} from 'folds';
import classNames from 'classnames';
import { BlurhashCanvas } from 'react-blurhash';
Expand All @@ -36,6 +37,8 @@ export type ImageContentProps = {
info?: IImageInfo;
encInfo?: EncryptedAttachmentInfo;
autoPlay?: boolean;
imageWidth?: number;
imageHeight?: number;
};
export const ImageContent = as<'div', ImageContentProps>(
({ className, body, mimeType, url, info, encInfo, autoPlay, ...props }, ref) => {
Expand Down Expand Up @@ -70,6 +73,9 @@ export const ImageContent = as<'div', ImageContentProps>(
if (autoPlay) loadSrc();
}, [autoPlay, loadSrc]);

// if true: smaller view button & shows image size to the right of the box
const isNarrowImage = props.imageWidth && props.imageWidth <= 64;

return (
<Box className={classNames(css.RelativeBase, className)} {...props} ref={ref}>
{srcState.status === AsyncStatus.Success && (
Expand Down Expand Up @@ -109,14 +115,21 @@ export const ImageContent = as<'div', ImageContentProps>(
{!autoPlay && srcState.status === AsyncStatus.Idle && (
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
<Button
style={{
maxHeight: toRem(props.imageHeight || 32),
// paddingLeft/Right must be inline style to be able to override the library style
paddingLeft: (isNarrowImage ? "0" : undefined),
paddingRight: (isNarrowImage ? "0" : undefined),
width: (isNarrowImage ? "100%" : undefined),
}}
variant="Secondary"
fill="Solid"
fill={isNarrowImage ? "None" : "Solid"}
radii="300"
size="300"
onClick={loadSrc}
before={<Icon size="Inherit" src={Icons.Photo} filled />}
>
<Text size="B300">View</Text>
{!isNarrowImage && <Text size="B300">View</Text>}
</Button>
</Box>
)}
Expand Down Expand Up @@ -169,7 +182,12 @@ export const ImageContent = as<'div', ImageContentProps>(
</Box>
)}
{!load && typeof info?.size === 'number' && (
<Box className={css.AbsoluteFooter} justifyContent="End" alignContent="Center" gap="200">
<Box
className={isNarrowImage ? css.NarrowContentBadges : css.AbsoluteFooter}
justifyContent="End"
alignContent="Center"
gap="200"
>
<Badge variant="Secondary" fill="Soft">
<Text size="L400">{bytesToSize(info.size)}</Text>
</Badge>
Expand Down
10 changes: 6 additions & 4 deletions src/app/organisms/room/message/StickerContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
MessageDeletedContent,
} from '../../../components/message';
import { ImageContent } from './ImageContent';
import { scaleYDimension } from '../../../utils/common';
import { scaleDimension } from '../../../utils/common';
import { IImageContent } from '../../../../types/matrix/common';

type StickerContentProps = {
Expand All @@ -23,13 +23,13 @@ export const StickerContent = as<'div', StickerContentProps>(
if (typeof mxcUrl !== 'string') {
return <MessageBrokenContent />;
}
const height = scaleYDimension(imgInfo?.w || 152, 152, imgInfo?.h || 152);
const scaled = scaleDimension(imgInfo?.w || 152, imgInfo?.h || 152, 16, 16, 152, 152);

return (
<AttachmentBox
style={{
height: toRem(height < 48 ? 48 : height),
width: toRem(152),
height: toRem(scaled.h),
width: toRem(scaled.w),
}}
{...props}
ref={ref}
Expand All @@ -41,6 +41,8 @@ export const StickerContent = as<'div', StickerContentProps>(
mimeType={imgInfo?.mimetype}
url={mxcUrl}
encInfo={content.file}
imageWidth={scaled.w}
imageHeight={scaled.h}
/>
</AttachmentBox>
);
Expand Down
20 changes: 17 additions & 3 deletions src/app/organisms/room/message/VideoContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Tooltip,
TooltipProvider,
as,
toRem,
} from 'folds';
import classNames from 'classnames';
import { BlurhashCanvas } from 'react-blurhash';
Expand All @@ -35,6 +36,8 @@ export type VideoContentProps = {
encInfo?: EncryptedAttachmentInfo;
autoPlay?: boolean;
loadThumbnail?: boolean;
videoWidth?: number;
videoHeight?: number;
};
export const VideoContent = as<'div', VideoContentProps>(
({ className, body, mimeType, url, info, encInfo, autoPlay, loadThumbnail, ...props }, ref) => {
Expand Down Expand Up @@ -85,6 +88,9 @@ export const VideoContent = as<'div', VideoContentProps>(
if (loadThumbnail) loadThumbSrc();
}, [loadThumbnail, loadThumbSrc]);

// if true: smaller watch button & shows video size to the right of the box
const isNarrowVideo = props.videoWidth && props.videoWidth <= 64;

return (
<Box className={classNames(css.RelativeBase, className)} {...props} ref={ref}>
{typeof blurHash === 'string' && !load && (
Expand All @@ -104,14 +110,22 @@ export const VideoContent = as<'div', VideoContentProps>(
{!autoPlay && srcState.status === AsyncStatus.Idle && (
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
<Button
style={{
maxHeight: toRem(props.videoHeight || 32),
// paddingLeft/Right must be inline style to be able to override the library style
paddingLeft: (isNarrowVideo ? "0" : undefined),
paddingRight: (isNarrowVideo ? "0" : undefined),
width: (isNarrowVideo ? "100%" : undefined),
color: "white"
}}
variant="Secondary"
fill="Solid"
fill={isNarrowVideo ? "None" : "Solid"}
radii="300"
size="300"
onClick={loadSrc}
before={<Icon size="Inherit" src={Icons.Play} filled />}
>
<Text size="B300">Watch</Text>
{!isNarrowVideo && <Text size="B300">Watch</Text>}
</Button>
</Box>
)}
Expand Down Expand Up @@ -163,7 +177,7 @@ export const VideoContent = as<'div', VideoContentProps>(
)}
{!load && typeof info.size === 'number' && (
<Box
className={css.AbsoluteFooter}
className={isNarrowVideo ? css.NarrowContentBadges : css.AbsoluteFooter}
justifyContent="SpaceBetween"
alignContent="Center"
gap="200"
Expand Down
14 changes: 14 additions & 0 deletions src/app/organisms/room/message/styles.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ export const AbsoluteFooter = style([
},
]);

export const NarrowContentBadges = style([
DefaultReset,
{
position: 'absolute',
top: 0,
bottom: 0,
height: '100%',
alignItems: 'center',
left: '100%',
marginLeft: config.space.S200,
justifyContent: "start"
},
]);

export const ModalWide = style({
minWidth: '85vw',
minHeight: '90vh',
Expand Down
10 changes: 6 additions & 4 deletions src/app/organisms/room/msgContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import { encryptFile, getImageInfo, getThumbnailContent, getVideoInfo } from '../../utils/matrix';
import { TUploadItem } from '../../state/roomInputDrafts';
import { encodeBlurHash } from '../../utils/blurHash';
import { scaleYDimension } from '../../utils/common';
import { scaleDimension } from '../../utils/common';

const generateThumbnailContent = async (
mx: MatrixClient,
Expand Down Expand Up @@ -53,7 +53,8 @@ export const getImageMsgContent = async (
body: file.name,
};
if (imgEl) {
const blurHash = encodeBlurHash(imgEl, 512, scaleYDimension(imgEl.width, 512, imgEl.height));
const dim = scaleDimension(imgEl.width, imgEl.height, 32, 32, 512, 512);
const blurHash = encodeBlurHash(imgEl, dim.w, dim.h);

content.info = {
...getImageInfo(imgEl, file),
Expand Down Expand Up @@ -95,10 +96,11 @@ export const getVideoMsgContent = async (
)
);
if (thumbContent && thumbContent.thumbnail_info) {
const dim = scaleDimension(videoEl.width, videoEl.height, 32, 32, 512, 512);
thumbContent.thumbnail_info[MATRIX_BLUR_HASH_PROPERTY_NAME] = encodeBlurHash(
videoEl,
512,
scaleYDimension(videoEl.videoWidth, 512, videoEl.videoHeight)
dim.w,
dim.h,
);
}
if (thumbError) console.warn(thumbError);
Expand Down
15 changes: 11 additions & 4 deletions src/app/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,17 @@ export const binarySearch = <T>(items: T[], match: (item: T) => -1 | 0 | 1): T |
export const randomNumberBetween = (min: number, max: number) =>
Math.floor(Math.random() * (max - min + 1)) + min;

export const scaleYDimension = (x: number, scaledX: number, y: number): number => {
const scaleFactor = scaledX / x;
return scaleFactor * y;
};
export const scaleDimension = (inW: number, inH: number, minW: number, minH: number, maxW: number, maxH: number): {w: number, h: number} => {
let w = Math.max(minW, Math.min(maxW, inW));
const scaleFactor = w / inW;
let h = Math.max(minH, scaleFactor * inH);
if (h > maxH) {
w = w / h * maxH;
h = maxH;
}
w = Math.max(minW, Math.min(maxW, w));
return { w, h };
}

export const parseGeoUri = (location: string) => {
const [, data] = location.split(':');
Expand Down
Loading