From a6a3ac3b24c5bddda4c109d3047c2c41113b0931 Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:17:44 +0530 Subject: [PATCH] redesign thread selector --- .../thread-selector/ThreadSelector.tsx | 90 --------------- .../components/thread-selector/styles.css.ts | 20 ---- src/app/features/room/RoomTimeline.tsx | 10 +- .../thread-selector/ThreadSelector.tsx | 105 ++++++++++++++++++ .../room/message}/thread-selector/index.ts | 0 .../message/thread-selector/styles.css.ts | 37 ++++++ .../room/threads-menu/ThreadsMenu.tsx | 5 +- src/app/hooks/useRoomThreads.ts | 2 +- 8 files changed, 154 insertions(+), 115 deletions(-) delete mode 100644 src/app/components/thread-selector/ThreadSelector.tsx delete mode 100644 src/app/components/thread-selector/styles.css.ts create mode 100644 src/app/features/room/message/thread-selector/ThreadSelector.tsx rename src/app/{components => features/room/message}/thread-selector/index.ts (100%) create mode 100644 src/app/features/room/message/thread-selector/styles.css.ts diff --git a/src/app/components/thread-selector/ThreadSelector.tsx b/src/app/components/thread-selector/ThreadSelector.tsx deleted file mode 100644 index 75eb1590..00000000 --- a/src/app/components/thread-selector/ThreadSelector.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { Avatar, Box, Icon, Icons, Text } from 'folds'; -import React, { ReactNode } from 'react'; -import classNames from 'classnames'; -import { IThreadBundledRelationship, Room } from 'matrix-js-sdk'; -import { ContainerColor } from '../../styles/ContainerColor.css'; -import * as css from './styles.css'; -import { UserAvatar } from '../user-avatar'; -import { getMemberAvatarMxc, getMemberDisplayName } from '../../utils/room'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; -import { useMediaAuthentication } from '../../hooks/useMediaAuthentication'; -import { getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix'; - -export function ThreadSelectorContainer({ children }: { children: ReactNode }) { - return {children}; -} - -type ThreadSelectorProps = { - room: Room; - senderId: string; - threadDetail: IThreadBundledRelationship; - outlined?: boolean; -}; - -export function ThreadSelector({ room, senderId, threadDetail, outlined }: ThreadSelectorProps) { - const mx = useMatrixClient(); - const useAuthentication = useMediaAuthentication(); - const senderAvatarMxc = getMemberAvatarMxc(room, senderId); - - const latestEvent = threadDetail.latest_event; - const latestSenderId = latestEvent.sender; - const latestSenderAvatarMxc = getMemberAvatarMxc(room, latestSenderId); - const latestDisplayName = - getMemberDisplayName(room, latestSenderId) ?? - getMxIdLocalPart(latestSenderId) ?? - latestSenderId; - - const latestEventTs = latestEvent.origin_server_ts; - - return ( - - - - } - /> - - {latestSenderId && ( - - } - /> - - )} - - - - {threadDetail.count} {threadDetail.count === 1 ? 'Reply' : 'Replies'} - - - {/* TODO: date */} - Last Reply by {latestDisplayName} at {new Date(latestEventTs).getTime()} - - - - - ); -} diff --git a/src/app/components/thread-selector/styles.css.ts b/src/app/components/thread-selector/styles.css.ts deleted file mode 100644 index fe580b68..00000000 --- a/src/app/components/thread-selector/styles.css.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { style } from '@vanilla-extract/css'; -import { color, config } from 'folds'; - -export const ThreadSelectorContainer = style({ - paddingTop: config.space.S100, -}); - -export const ThreadSelector = style({ - padding: config.space.S200, - borderRadius: config.radii.R400, -}); - -export const ThreadSectorOutlined = style({ - borderWidth: config.borderWidth.B300, -}); - -export const ThreadRepliesCount = style({ - color: color.Primary.Main, - flexShrink: 0, -}); diff --git a/src/app/features/room/RoomTimeline.tsx b/src/app/features/room/RoomTimeline.tsx index 93c3cf66..71674b0f 100644 --- a/src/app/features/room/RoomTimeline.tsx +++ b/src/app/features/room/RoomTimeline.tsx @@ -127,7 +127,7 @@ import { useAccessiblePowerTagColors, useGetMemberPowerTag } from '../../hooks/u import { useTheme } from '../../hooks/useTheme'; import { useRoomCreatorsTag } from '../../hooks/useRoomCreatorsTag'; import { usePowerLevelTags } from '../../hooks/usePowerLevelTags'; -import { ThreadSelector, ThreadSelectorContainer } from '../../components/thread-selector'; +import { ThreadSelector, ThreadSelectorContainer } from './message/thread-selector'; const TimelineFloat = as<'div', css.TimelineFloatVariants>( ({ position, className, ...props }, ref) => ( @@ -1113,7 +1113,13 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli {threadDetail && ( - + )} diff --git a/src/app/features/room/message/thread-selector/ThreadSelector.tsx b/src/app/features/room/message/thread-selector/ThreadSelector.tsx new file mode 100644 index 00000000..3701948c --- /dev/null +++ b/src/app/features/room/message/thread-selector/ThreadSelector.tsx @@ -0,0 +1,105 @@ +import { Avatar, Box, Icon, Icons, Line, Text } from 'folds'; +import React, { ReactNode } from 'react'; +import classNames from 'classnames'; +import { IThreadBundledRelationship, Room } from 'matrix-js-sdk'; +import * as css from './styles.css'; +import { UserAvatar } from '../../../../components/user-avatar'; +import { getMemberAvatarMxc, getMemberDisplayName } from '../../../../utils/room'; +import { useMatrixClient } from '../../../../hooks/useMatrixClient'; +import { useMediaAuthentication } from '../../../../hooks/useMediaAuthentication'; +import { getMxIdLocalPart, mxcUrlToHttp } from '../../../../utils/matrix'; +import { Time } from '../../../../components/message'; + +export function ThreadSelectorContainer({ children }: { children: ReactNode }) { + return {children}; +} + +type ThreadSelectorProps = { + room: Room; + threadDetail: IThreadBundledRelationship; + outlined?: boolean; + hour24Clock: boolean; + dateFormatString: string; +}; + +export function ThreadSelector({ + room, + threadDetail, + outlined, + hour24Clock, + dateFormatString, +}: ThreadSelectorProps) { + const mx = useMatrixClient(); + const useAuthentication = useMediaAuthentication(); + + const latestEvent = threadDetail.latest_event; + + const latestSenderId = latestEvent.sender; + const latestSenderAvatarMxc = getMemberAvatarMxc(room, latestSenderId); + const latestDisplayName = + getMemberDisplayName(room, latestSenderId) ?? + getMxIdLocalPart(latestSenderId) ?? + latestSenderId; + + const latestEventTs = latestEvent.origin_server_ts; + + return ( + + + + + {threadDetail.count} {threadDetail.count === 1 ? 'Thread Reply' : 'Thread Replies'} + + + {latestSenderId && ( + <> + + + + + } + /> + + + + + Latest by {latestDisplayName} at{' '} + + + + + + )} + + ); +} diff --git a/src/app/components/thread-selector/index.ts b/src/app/features/room/message/thread-selector/index.ts similarity index 100% rename from src/app/components/thread-selector/index.ts rename to src/app/features/room/message/thread-selector/index.ts diff --git a/src/app/features/room/message/thread-selector/styles.css.ts b/src/app/features/room/message/thread-selector/styles.css.ts new file mode 100644 index 00000000..fbd15ecc --- /dev/null +++ b/src/app/features/room/message/thread-selector/styles.css.ts @@ -0,0 +1,37 @@ +import { style } from '@vanilla-extract/css'; +import { color, config, toRem } from 'folds'; +import { ContainerColor } from '../../../../styles/ContainerColor.css'; + +export const ThreadSelectorContainer = style({ + marginTop: config.space.S200, +}); + +export const ThreadSelector = style([ + ContainerColor({ variant: 'SurfaceVariant' }), + { + padding: `${config.space.S200} ${config.space.S300}`, + borderRadius: config.radii.R400, + cursor: 'pointer', + + selectors: { + '&:hover, &:focus-visible': { + backgroundColor: color.SurfaceVariant.ContainerHover, + }, + '&:active': { + backgroundColor: color.SurfaceVariant.ContainerActive, + }, + }, + }, +]); + +export const ThreadSectorOutlined = style({ + borderWidth: config.borderWidth.B300, +}); + +export const ThreadSelectorDivider = style({ + height: toRem(16), +}); + +export const ThreadRepliesCount = style({ + color: color.Primary.Main, +}); diff --git a/src/app/features/room/threads-menu/ThreadsMenu.tsx b/src/app/features/room/threads-menu/ThreadsMenu.tsx index 5ff308e6..375b97da 100644 --- a/src/app/features/room/threads-menu/ThreadsMenu.tsx +++ b/src/app/features/room/threads-menu/ThreadsMenu.tsx @@ -80,7 +80,7 @@ import { } from '../../../hooks/useMemberPowerTag'; import { useRoomCreatorsTag } from '../../../hooks/useRoomCreatorsTag'; import { useRoomMyThreads } from '../../../hooks/useRoomThreads'; -import { ThreadSelector, ThreadSelectorContainer } from '../../../components/thread-selector'; +import { ThreadSelector, ThreadSelectorContainer } from '../message/thread-selector'; type ThreadMessageProps = { room: Room; @@ -287,9 +287,10 @@ export const ThreadsMenu = forwardRef( )} diff --git a/src/app/hooks/useRoomThreads.ts b/src/app/hooks/useRoomThreads.ts index d5ef24d6..a8ed0933 100644 --- a/src/app/hooks/useRoomThreads.ts +++ b/src/app/hooks/useRoomThreads.ts @@ -14,7 +14,7 @@ export const useRoomMyThreads = (room: Room): MatrixEvent[] | undefined => { null, 30, Direction.Backward, - ThreadFilterType.My + ThreadFilterType.All ), [mx, room] )