Timeline-refactor-fixes (#1438)

* fix type

* fix missing member from reaction

* stop context menu event propagation in msg modal

* prevent encode blur hash from freezing app

* replace roboto font with inter and fix weight

* add recent emoji when selecting emoji

* fix room latest evt hook

* add option to drop typing status
This commit is contained in:
Ajay Bura 2023-10-07 18:19:01 +11:00 committed by GitHub
parent f9b895b32c
commit 1bdb7f4e3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 138 additions and 64 deletions

View file

@ -167,7 +167,7 @@ export const getFirstLinkedTimeline = (
export const getLinkedTimelines = (timeline: EventTimeline): EventTimeline[] => {
const firstTimeline = getFirstLinkedTimeline(timeline, Direction.Backward);
const timelines = [];
const timelines: EventTimeline[] = [];
for (
let nextTimeline: EventTimeline | null = firstTimeline;

View file

@ -19,7 +19,7 @@ import { getMemberDisplayName } from '../../utils/room';
import { getMxIdLocalPart } from '../../utils/matrix';
import * as css from './RoomViewFollowing.css';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useRoomLatestEvent } from '../../hooks/useRoomLatestEvent';
import { useRoomLatestRenderedEvent } from '../../hooks/useRoomLatestRenderedEvent';
import { useRoomEventReaders } from '../../hooks/useRoomEventReaders';
import { EventReaders } from '../../components/event-readers';
@ -30,7 +30,7 @@ export const RoomViewFollowing = as<'div', RoomViewFollowingProps>(
({ className, room, ...props }, ref) => {
const mx = useMatrixClient();
const [open, setOpen] = useState(false);
const latestEvent = useRoomLatestEvent(room);
const latestEvent = useRoomLatestRenderedEvent(room);
const latestEventReaders = useRoomEventReaders(room, latestEvent?.getId());
const followingMembers = latestEventReaders
.map((readerId) => room.getMember(readerId))

View file

@ -22,3 +22,6 @@ export const RoomViewTyping = style([
animation: `${SlideUpAnime} 100ms ease-in-out`,
},
]);
export const TypingText = style({
flexGrow: 1,
});

View file

@ -1,8 +1,8 @@
import React, { useMemo } from 'react';
import { Box, Text, as } from 'folds';
import { Box, Icon, IconButton, Icons, Text, as } from 'folds';
import { Room } from 'matrix-js-sdk';
import classNames from 'classnames';
import { useAtomValue } from 'jotai';
import { useAtomValue, useSetAtom } from 'jotai';
import { roomIdToTypingMembersAtom, selectRoomTypingMembersAtom } from '../../state/typingMembers';
import { TypingIndicator } from '../../components/typing-indicator';
import { getMemberDisplayName } from '../../utils/room';
@ -15,6 +15,7 @@ export type RoomViewTypingProps = {
};
export const RoomViewTyping = as<'div', RoomViewTypingProps>(
({ className, room, ...props }, ref) => {
const setTypingMembers = useSetAtom(roomIdToTypingMembersAtom);
const mx = useMatrixClient();
const typingMembers = useAtomValue(
useMemo(() => selectRoomTypingMembersAtom(room.roomId, roomIdToTypingMembersAtom), [room])
@ -29,6 +30,18 @@ export const RoomViewTyping = as<'div', RoomViewTypingProps>(
return null;
}
const handleDropAll = () => {
// some homeserver does not timeout typing status
// we have given option so user can drop their typing status
typingMembers.forEach((member) =>
setTypingMembers({
type: 'DELETE',
roomId: room.roomId,
member,
})
);
};
return (
<Box
className={classNames(css.RoomViewTyping, className)}
@ -38,7 +51,7 @@ export const RoomViewTyping = as<'div', RoomViewTypingProps>(
ref={ref}
>
<TypingIndicator />
<Text size="T300" truncate>
<Text className={css.TypingText} size="T300" truncate>
{typingNames.length === 1 && (
<>
<b>{typingNames[0]}</b>
@ -96,6 +109,9 @@ export const RoomViewTyping = as<'div', RoomViewTypingProps>(
</>
)}
</Text>
<IconButton title="Drop Typing Status" size="300" radii="Pill" onClick={handleDropAll}>
<Icon size="50" src={Icons.Cross} />
</IconButton>
</Box>
);
}

View file

@ -94,7 +94,7 @@ function ReadTextFile({ body, mimeType, url, encInfo }: Omit<FileContentProps, '
clickOutsideDeactivates: true,
}}
>
<Modal size="500">
<Modal size="500" onContextMenu={(evt: any) => evt.stopPropagation()}>
<TextViewer
name={body}
text={textState.data}
@ -159,7 +159,7 @@ function ReadPdfFile({ body, mimeType, url, encInfo }: Omit<FileContentProps, 'i
clickOutsideDeactivates: true,
}}
>
<Modal size="500">
<Modal size="500" onContextMenu={(evt: any) => evt.stopPropagation()}>
<PdfViewer
name={body}
src={pdfState.data}

View file

@ -81,7 +81,7 @@ export const ImageContent = as<'div', ImageContentProps>(
clickOutsideDeactivates: true,
}}
>
<Modal size="500">
<Modal size="500" onContextMenu={(evt: any) => evt.stopPropagation()}>
<ImageViewer
src={srcState.data}
alt={body}

View file

@ -12,6 +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';
const generateThumbnailContent = async (
mx: MatrixClient,
@ -52,7 +53,7 @@ export const getImageMsgContent = async (
body: file.name,
};
if (imgEl) {
const blurHash = encodeBlurHash(imgEl);
const blurHash = encodeBlurHash(imgEl, 512, scaleYDimension(imgEl.width, 512, imgEl.height));
const [thumbError, thumbContent] = await to(
generateThumbnailContent(
mx,
@ -107,7 +108,11 @@ export const getVideoMsgContent = async (
)
);
if (thumbContent && thumbContent.thumbnail_info) {
thumbContent.thumbnail_info[MATRIX_BLUR_HASH_PROPERTY_NAME] = encodeBlurHash(videoEl);
thumbContent.thumbnail_info[MATRIX_BLUR_HASH_PROPERTY_NAME] = encodeBlurHash(
videoEl,
512,
scaleYDimension(videoEl.videoWidth, 512, videoEl.videoHeight)
);
}
if (thumbError) console.warn(thumbError);
content.info = {

View file

@ -99,10 +99,9 @@ export const ReactionViewer = as<'div', ReactionViewerProps>(
const senderId = mEvent.getSender();
if (!senderId) return null;
const member = room.getMember(senderId);
if (!member) return null;
const name = getName(member);
const name = (member ? getName(member) : getMxIdLocalPart(senderId)) ?? senderId;
const avatarUrl = member.getAvatarUrl(
const avatarUrl = member?.getAvatarUrl(
mx.baseUrl,
100,
100,
@ -113,12 +112,12 @@ export const ReactionViewer = as<'div', ReactionViewerProps>(
return (
<MenuItem
key={member.userId}
key={senderId}
style={{ padding: `0 ${config.space.S200}` }}
radii="400"
onClick={() => {
requestClose();
openProfileViewer(member.userId, room.roomId);
openProfileViewer(senderId, room.roomId);
}}
before={
<Avatar size="200">
@ -127,7 +126,7 @@ export const ReactionViewer = as<'div', ReactionViewerProps>(
) : (
<AvatarFallback
style={{
background: colorMXID(member.userId),
background: colorMXID(senderId),
color: 'white',
}}
>