diff --git a/web/modals/threads/sidebars/sidebar.react.js b/web/modals/threads/sidebars/sidebar.react.js index c8f13113e..6d710b290 100644 --- a/web/modals/threads/sidebars/sidebar.react.js +++ b/web/modals/threads/sidebars/sidebar.react.js @@ -1,91 +1,101 @@ // @flow import classNames from 'classnames'; import * as React from 'react'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import type { ChatThreadItem } from 'lib/selectors/chat-selectors.js'; import { useMessagePreview } from 'lib/shared/message-utils.js'; import { shortAbsoluteDate } from 'lib/utils/date-utils.js'; import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; import css from './sidebars-modal.css'; import Button from '../../../components/button.react.js'; +import ThreadAvatar from '../../../components/thread-avatar.react.js'; import { getDefaultTextMessageRules } from '../../../markdown/rules.react.js'; import { useOnClickThread } from '../../../selectors/thread-selectors.js'; type Props = { +sidebar: ChatThreadItem, +isLastItem?: boolean, }; function Sidebar(props: Props): React.Node { const { sidebar, isLastItem } = props; const { threadInfo, lastUpdatedTime, mostRecentMessageInfo } = sidebar; const { unread } = threadInfo.currentUser; const { popModal } = useModalContext(); const navigateToThread = useOnClickThread(threadInfo); const onClickThread = React.useCallback( event => { popModal(); navigateToThread(event); }, [popModal, navigateToThread], ); const sidebarInfoClassName = classNames({ [css.sidebarInfo]: true, [css.unread]: unread, }); + const previewTextClassName = classNames({ + [css.longTextEllipsis]: true, + [css.avatarOffset]: true, + }); + const lastActivity = React.useMemo( () => shortAbsoluteDate(lastUpdatedTime), [lastUpdatedTime], ); const messagePreviewResult = useMessagePreview( mostRecentMessageInfo, threadInfo, getDefaultTextMessageRules().simpleMarkdownRules, ); const lastMessage = React.useMemo(() => { if (!messagePreviewResult) { return
No messages
; } const { message, username } = messagePreviewResult; const previewText = username ? `${username.text}: ${message.text}` : message.text; return ( <> -
{previewText}
+
{previewText}
{lastActivity}
); - }, [lastActivity, messagePreviewResult]); + }, [lastActivity, messagePreviewResult, previewTextClassName]); const { uiName } = useResolvedThreadInfo(threadInfo); + return ( ); } export default Sidebar; diff --git a/web/modals/threads/sidebars/sidebars-modal.css b/web/modals/threads/sidebars/sidebars-modal.css index c9ab9e196..8744e7b95 100644 --- a/web/modals/threads/sidebars/sidebars-modal.css +++ b/web/modals/threads/sidebars/sidebars-modal.css @@ -1,73 +1,83 @@ div.sidebarListContainer { display: flex; flex-direction: column; line-height: var(--line-height-text); width: 383px; height: 458px; } div.sidebarList { overflow: auto; color: var(--sidebars-modal-color); } div.noSidebars { padding: 16px; text-align: center; color: var(--sidebars-modal-color); } button.sidebarContainer { padding: 0 16px; column-gap: 8px; align-items: flex-start; width: 100%; font-size: inherit; text-align: inherit; line-height: inherit; color: inherit; background: inherit; } button.sidebarContainer:hover { color: var(--sidebars-modal-color-hover); } div.sidebarInfo { flex: 1; display: flex; flex-direction: column; overflow: hidden; padding: 8px 0; } +div.avatarContainer { + display: flex; + align-items: center; + gap: 8px; +} + +div.avatarOffset { + margin-left: 24px; +} + div.longTextEllipsis { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } div.lastMessage { display: flex; justify-content: space-between; column-gap: 14px; } div.noMessage { text-align: center; font-style: italic; } div.lastActivity { white-space: nowrap; } div.unread { color: var(--fg); font-weight: var(--semi-bold); } img.sidebarArrow { position: relative; top: -12px; } diff --git a/web/modals/threads/subchannels/subchannel.react.js b/web/modals/threads/subchannels/subchannel.react.js index b2dc9ea75..8ecd3aa5d 100644 --- a/web/modals/threads/subchannels/subchannel.react.js +++ b/web/modals/threads/subchannels/subchannel.react.js @@ -1,88 +1,89 @@ // @flow import classNames from 'classnames'; import * as React from 'react'; import { useModalContext } from 'lib/components/modal-provider.react.js'; -import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; import { type ChatThreadItem } from 'lib/selectors/chat-selectors.js'; import { useMessagePreview } from 'lib/shared/message-utils.js'; import { shortAbsoluteDate } from 'lib/utils/date-utils.js'; import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; import css from './subchannels-modal.css'; import Button from '../../../components/button.react.js'; +import ThreadAvatar from '../../../components/thread-avatar.react.js'; import { getDefaultTextMessageRules } from '../../../markdown/rules.react.js'; import { useOnClickThread } from '../../../selectors/thread-selectors.js'; type Props = { +chatThreadItem: ChatThreadItem, }; function Subchannel(props: Props): React.Node { const { chatThreadItem } = props; const { threadInfo, mostRecentMessageInfo, lastUpdatedTimeIncludingSidebars, } = chatThreadItem; const { unread } = threadInfo.currentUser; const subchannelTitleClassName = classNames({ [css.subchannelInfo]: true, [css.unread]: unread, }); const { popModal } = useModalContext(); const navigateToThread = useOnClickThread(threadInfo); const onClickThread = React.useCallback( event => { popModal(); navigateToThread(event); }, [popModal, navigateToThread], ); const lastActivity = React.useMemo( () => shortAbsoluteDate(lastUpdatedTimeIncludingSidebars), [lastUpdatedTimeIncludingSidebars], ); const messagePreviewResult = useMessagePreview( mostRecentMessageInfo, threadInfo, getDefaultTextMessageRules().simpleMarkdownRules, ); const lastMessage = React.useMemo(() => { if (!messagePreviewResult) { return
No messages
; } const { message, username } = messagePreviewResult; const previewText = username ? `${username.text}: ${message.text}` : message.text; return ( <>
{previewText}
{lastActivity}
); }, [lastActivity, messagePreviewResult]); const { uiName } = useResolvedThreadInfo(threadInfo); + return ( ); } export default Subchannel;