From 7466c31728c9ade1d94c4efa1d890e8f00e7df14 Mon Sep 17 00:00:00 2001 From: Pedro Tiburcio Date: Tue, 11 Feb 2025 18:33:09 -0500 Subject: [PATCH 1/4] feat: delete chat room messages --- packages/components/CHANGELOG.md | 6 +++ .../DefaultHoverOverlay/index.tsx | 7 +-- .../DefaultHoverOverlay/types.ts | 7 ++- .../ThreeDotsMenuHoverOverlay/index.tsx | 18 +++++-- .../ThreeDotsMenuHoverOverlay/types.ts | 7 ++- .../__storybook__/ActionsOverlay.mdx | 5 +- .../ActionsOverlay/__storybook__/stories.tsx | 4 +- .../__shared__/web/ActionsOverlay/index.tsx | 21 ++++---- .../__shared__/web/ActionsOverlay/types.ts | 7 ++- .../comments/web/CommentItem/index.tsx | 2 +- .../common/graphql/fragments/MessageItem.ts | 1 + .../common/graphql/mutations/MessageDelete.ts | 50 +++++++++++++++++ .../useMessagesListSubscription.tsx | 2 +- .../modules/messages/common/index.ts | 2 + .../web/ChatRoomsList/ChatRoomItem/index.tsx | 2 +- .../UserMessage/MessageItem/index.tsx | 54 ++++++++++++++++--- .../UserMessage/MessageItem/types.ts | 1 + .../MessagesGroup/UserMessage/index.tsx | 1 + packages/components/schema.graphql | 27 +++++++--- 19 files changed, 183 insertions(+), 41 deletions(-) create mode 100644 packages/components/modules/messages/common/graphql/mutations/MessageDelete.ts diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 21304243..92ab2ff6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,11 @@ # @baseapp-frontend/components +## 1.0.9 + +### Patch Changes + +- Enabled deletion of chat room messages + ## 1.0.8 ### Patch Changes diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/DefaultHoverOverlay/index.tsx b/packages/components/modules/__shared__/web/ActionsOverlay/DefaultHoverOverlay/index.tsx index 067a40e3..37838c86 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/DefaultHoverOverlay/index.tsx +++ b/packages/components/modules/__shared__/web/ActionsOverlay/DefaultHoverOverlay/index.tsx @@ -9,8 +9,9 @@ import { DefaultHoverOverlayProps } from './types' const DefaultHoverOverlay: FC = ({ offsetRight, offsetTop, - enableDelete, + showDeleteButton, isDeletingItem, + disableDeleteButton, handleDeleteDialogOpen, actions = [], handleLongPressItemOptionsClose, @@ -20,10 +21,10 @@ const DefaultHoverOverlay: FC = ({ offsetTop={offsetTop} aria-label="actions overlay" > - {enableDelete && ( + {showDeleteButton && ( diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/DefaultHoverOverlay/types.ts b/packages/components/modules/__shared__/web/ActionsOverlay/DefaultHoverOverlay/types.ts index 09570fc0..a582f082 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/DefaultHoverOverlay/types.ts +++ b/packages/components/modules/__shared__/web/ActionsOverlay/DefaultHoverOverlay/types.ts @@ -3,7 +3,12 @@ import { ActionOverlayProps } from '../types' export interface DefaultHoverOverlayProps extends Pick< ActionOverlayProps, - 'actions' | 'offsetRight' | 'offsetTop' | 'enableDelete' | 'isDeletingItem' + | 'actions' + | 'offsetRight' + | 'offsetTop' + | 'showDeleteButton' + | 'isDeletingItem' + | 'disableDeleteButton' > { handleDeleteDialogOpen: () => void handleLongPressItemOptionsClose: () => void diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/ThreeDotsMenuHoverOverlay/index.tsx b/packages/components/modules/__shared__/web/ActionsOverlay/ThreeDotsMenuHoverOverlay/index.tsx index 30055a00..bbedf53b 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/ThreeDotsMenuHoverOverlay/index.tsx +++ b/packages/components/modules/__shared__/web/ActionsOverlay/ThreeDotsMenuHoverOverlay/index.tsx @@ -12,8 +12,9 @@ import { ThreeDotsMenuHoverOverlayProps } from './types' const ThreeDotsMenuHoverOverlay: FC = ({ offsetRight, offsetTop, - enableDelete, + showDeleteButton, isDeletingItem, + disableDeleteButton, handleDeleteDialogOpen, actions = [], handleClosePopover, @@ -54,10 +55,17 @@ const ThreeDotsMenuHoverOverlay: FC = ({ ) })} - {enableDelete && ( - - - + {showDeleteButton && ( + + + Delete diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/ThreeDotsMenuHoverOverlay/types.ts b/packages/components/modules/__shared__/web/ActionsOverlay/ThreeDotsMenuHoverOverlay/types.ts index 65658d82..737f6d75 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/ThreeDotsMenuHoverOverlay/types.ts +++ b/packages/components/modules/__shared__/web/ActionsOverlay/ThreeDotsMenuHoverOverlay/types.ts @@ -5,7 +5,12 @@ import { ActionOverlayProps } from '../types' export interface ThreeDotsMenuHoverOverlayProps extends Pick< ActionOverlayProps, - 'actions' | 'offsetRight' | 'offsetTop' | 'enableDelete' | 'isDeletingItem' + | 'actions' + | 'offsetRight' + | 'offsetTop' + | 'showDeleteButton' + | 'isDeletingItem' + | 'disableDeleteButton' > { handleDeleteDialogOpen: () => void handleClosePopover: () => void diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/__storybook__/ActionsOverlay.mdx b/packages/components/modules/__shared__/web/ActionsOverlay/__storybook__/ActionsOverlay.mdx index 5a5fa808..bc192278 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/__storybook__/ActionsOverlay.mdx +++ b/packages/components/modules/__shared__/web/ActionsOverlay/__storybook__/ActionsOverlay.mdx @@ -19,9 +19,10 @@ import { Meta } from '@storybook/addon-docs' - **actions** (OverlayAction[]): The list of actions desired for the child component. Note that to implement a delete action, the component provides a enabler, loading and click handler props specifically for that action (see props below). - **title** (string): Title for the child component (currently only used on the delete dialog). - **children** (ReactNode): The child component to be wrapped. -- **enableDelete** (boolean): Enables the delete action inside the tooltip/swippable drawer. +- **showDeleteButton** (boolean): Renders the delete action inside the tooltip/swippable drawer. - **isDeletingItem** (boolean): Mutation loading state for the delete action. - **handleDeleteItem** (function): Callback function to handle deletion. +- **disableDeleteButton** (function): Disables the delete button. - **offsetTop** (number): Number to offset the top positioning of the default tooltip position (only affects tooltip). - **offsetRight** (number): Number to offset the right positioning of the default tooltip position (only affects tooltip). - **ContainerProps** (BoxProps): Props for the parent `Box` component that wraps the child component. @@ -45,7 +46,7 @@ export const DefaultActionsOverlay = ( return ( {}} actions={[ { diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/__storybook__/stories.tsx b/packages/components/modules/__shared__/web/ActionsOverlay/__storybook__/stories.tsx index 1c820747..e78e4759 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/__storybook__/stories.tsx +++ b/packages/components/modules/__shared__/web/ActionsOverlay/__storybook__/stories.tsx @@ -19,7 +19,7 @@ export const DefaultActionsOverlay: Story = { name: 'ActionsOverlay', args: { title: 'Button', - enableDelete: true, + showDeleteButton: true, handleDeleteItem: () => {}, offsetRight: 0, offsetTop: 0, @@ -42,7 +42,7 @@ export const ActionsOverlayWithThreeDotsMenu: Story = { name: 'ActionsOverlay with ThreeDotsMenu', args: { title: 'Button', - enableDelete: true, + showDeleteButton: true, isDeletingItem: false, handleDeleteItem: () => {}, ContainerProps: { diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/index.tsx b/packages/components/modules/__shared__/web/ActionsOverlay/index.tsx index 96d189bb..4910273e 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/index.tsx +++ b/packages/components/modules/__shared__/web/ActionsOverlay/index.tsx @@ -22,13 +22,15 @@ const ActionsOverlay = forwardRef( actions = [], children, title = 'Item', - enableDelete = false, + showDeleteButton = false, isDeletingItem = false, + disableDeleteButton = false, handleDeleteItem = () => {}, offsetTop = 0, offsetRight = 0, ContainerProps = {}, SwipeableDrawerProps = {}, + DeleteDialogProps = {}, SwipeableDrawer = DefaultSwipeableDrawer, hoverOverlayMode = HOVER_OVERLAY_MODES.default, }, @@ -110,6 +112,7 @@ const ActionsOverlay = forwardRef( } onClose={handleDeleteDialogClose} open={isDeleteDialogOpen} + {...DeleteDialogProps} /> ) @@ -128,7 +131,7 @@ const ActionsOverlay = forwardRef( aria-label="actions overlay" {...SwipeableDrawerProps} > - + {actions?.map(({ label, icon, onClick, disabled, hasPermission, closeOnClick }) => { if (!hasPermission) return null @@ -158,12 +161,12 @@ const ActionsOverlay = forwardRef( ) })} - {enableDelete && ( + {showDeleteButton && ( <> @@ -171,9 +174,7 @@ const ActionsOverlay = forwardRef( - - {`Delete ${title}`} - + Delete @@ -190,8 +191,9 @@ const ActionsOverlay = forwardRef( {...{ offsetRight, offsetTop, - enableDelete, + showDeleteButton, isDeletingItem, + disableDeleteButton, handleDeleteDialogOpen, actions, handleLongPressItemOptionsClose, @@ -206,8 +208,9 @@ const ActionsOverlay = forwardRef( {...{ offsetRight, offsetTop, - enableDelete, + showDeleteButton, isDeletingItem, + disableDeleteButton, handleDeleteDialogOpen, actions, handleClosePopover, diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/types.ts b/packages/components/modules/__shared__/web/ActionsOverlay/types.ts index 1c5318af..240f9183 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/types.ts +++ b/packages/components/modules/__shared__/web/ActionsOverlay/types.ts @@ -1,6 +1,7 @@ import { FC } from 'react' -import type { SwipeableDrawerProps } from '@baseapp-frontend/design-system/components/web/drawers' +import { ConfirmDialogProps } from '@baseapp-frontend/design-system/components/web/dialogs' +import { SwipeableDrawerProps } from '@baseapp-frontend/design-system/components/web/drawers' import { ValueOf } from '@baseapp-frontend/utils' import { BoxProps } from '@mui/material' @@ -24,10 +25,12 @@ export type LongPressHandler = { export interface ActionOverlayProps extends ActionOverlayTooltipContainerProps { actions: OverlayAction[] title: string - enableDelete?: boolean | null + showDeleteButton?: boolean | null isDeletingItem?: boolean + disableDeleteButton?: boolean handleDeleteItem?: () => void ContainerProps?: Partial + DeleteDialogProps?: Partial SwipeableDrawer?: FC SwipeableDrawerProps?: Partial hoverOverlayMode?: ValueOf diff --git a/packages/components/modules/comments/web/CommentItem/index.tsx b/packages/components/modules/comments/web/CommentItem/index.tsx index c9a0bfcf..c5829e81 100644 --- a/packages/components/modules/comments/web/CommentItem/index.tsx +++ b/packages/components/modules/comments/web/CommentItem/index.tsx @@ -127,7 +127,7 @@ const CommentItem: FC = ({ ) => Disposable, + boolean, +] => { + const { sendToast } = useNotification() + const [commitMutation, isMutationInFlight] = useMutation( + MessageDeleteMutationQuery, + ) + + const commit = (config: UseMutationConfig) => + commitMutation({ + ...config, + onCompleted: (response, errors) => { + errors?.forEach((error) => { + sendToast(error.message, { type: 'error' }) + }) + + config?.onCompleted?.(response, errors) + }, + onError: (error) => { + sendToast(error.message, { type: 'error' }) + config?.onError?.(error) + }, + }) + + return [commit, isMutationInFlight] +} diff --git a/packages/components/modules/messages/common/graphql/subscriptions/useMessagesListSubscription.tsx b/packages/components/modules/messages/common/graphql/subscriptions/useMessagesListSubscription.tsx index a3c1ccb2..20d81ff8 100644 --- a/packages/components/modules/messages/common/graphql/subscriptions/useMessagesListSubscription.tsx +++ b/packages/components/modules/messages/common/graphql/subscriptions/useMessagesListSubscription.tsx @@ -4,7 +4,7 @@ import { ConnectionHandler, graphql, useSubscription } from 'react-relay' export const newMessageSubscription = graphql` subscription useMessagesListSubscription($roomId: ID!, $connections: [ID!]!) { - chatRoomOnNewMessage(roomId: $roomId) { + chatRoomOnMessage(roomId: $roomId) { message @prependEdge(connections: $connections) { node { ...MessageItemFragment diff --git a/packages/components/modules/messages/common/index.ts b/packages/components/modules/messages/common/index.ts index aea0bf83..79d19b2a 100644 --- a/packages/components/modules/messages/common/index.ts +++ b/packages/components/modules/messages/common/index.ts @@ -7,6 +7,8 @@ export { default as withChatRoomProvider } from './context/withChatRoomProvider' export * from './graphql/mutations/ArchiveChatRoom' export * from './graphql/mutations/CreateChatRoom' +export * from './graphql/mutations/MessageDelete' +export * from './graphql/mutations/MessageUpdate' export * from './graphql/mutations/ReadMessages' export * from './graphql/mutations/SendMessage' export * from './graphql/mutations/UnreadChat' diff --git a/packages/components/modules/messages/web/ChatRoomsList/ChatRoomItem/index.tsx b/packages/components/modules/messages/web/ChatRoomsList/ChatRoomItem/index.tsx index 60ea6d4e..79883293 100644 --- a/packages/components/modules/messages/web/ChatRoomsList/ChatRoomItem/index.tsx +++ b/packages/components/modules/messages/web/ChatRoomsList/ChatRoomItem/index.tsx @@ -107,7 +107,7 @@ const ChatRoomItem: FC = ({ closeOnClick: true, }, ]} - enableDelete + showDeleteButton handleDeleteItem={() => {}} isDeletingItem={false} ref={chatCardRef} diff --git a/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/index.tsx b/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/index.tsx index 4486817f..96ea4e72 100644 --- a/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/index.tsx +++ b/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/index.tsx @@ -2,6 +2,7 @@ import { FC, useRef, useState } from 'react' import { useCurrentProfile } from '@baseapp-frontend/authentication' import { + BlockIcon, CopyIcon, DownloadIcon, PenEditIcon, @@ -13,28 +14,63 @@ import { useFragment } from 'react-relay' import { ActionsOverlay, HOVER_OVERLAY_MODES } from '../../../../../../__shared__/web' import { MessageItemFragment } from '../../../../../common' +import { useMessageDeleteMutation } from '../../../../../common/graphql/mutations/MessageDelete' import MessageUpdate from '../../../../MessageUpdate' import { MessageItemContainer } from './styled' import { MessageItemProps } from './types' -const MessageItem: FC = ({ messageRef, isFirstGroupedMessage }) => { +const MessageItem: FC = ({ + messageRef, + isFirstGroupedMessage, + isGroup = false, +}) => { const { currentProfile } = useCurrentProfile() const message = useFragment(MessageItemFragment, messageRef) const isOwnMessage = currentProfile?.id === message?.profile?.id + const deletedMessage = message?.deleted const messageCardRef = useRef(null) const { sendToast } = useNotification() const [isEditMode, setIsEditMode] = useState(false) + const [commitUpdate, isMutationInFlight] = useMessageDeleteMutation() + + const onDeleteClick = async () => { + if (isMutationInFlight) return + + commitUpdate({ + variables: { + input: { + id: message.id, + }, + }, + onCompleted: (response, errors) => { + if (!errors) { + sendToast('Your message was deleted', { type: 'error' }) + } + }, + }) + } + + const deleteDialogContent = isGroup + ? 'The message will be deleted for everyone in this chat.' + : 'The message will be deleted for both you and the other person.' + const renderMessageContent = () => { if (isEditMode) { return setIsEditMode(false)} /> } + let messageColor = isOwnMessage ? 'text.primary' : 'primary.contrastText' + + if (deletedMessage) { + messageColor = 'text.disabled' + } + return ( = ({ messageRef, isFirstGroupedMessage } overflowWrap: 'anywhere', }} > + {deletedMessage && } + {deletedMessage && ' '} {message?.content} ) @@ -62,7 +100,7 @@ const MessageItem: FC = ({ messageRef, isFirstGroupedMessage } hasPermission: true, }, { - disabled: false, + disabled: deletedMessage || !isOwnMessage, icon: , label: 'Edit', onClick: () => { @@ -80,9 +118,13 @@ const MessageItem: FC = ({ messageRef, isFirstGroupedMessage } }, ]} hoverOverlayMode={HOVER_OVERLAY_MODES.threeDotsMenu} - enableDelete - handleDeleteItem={() => {}} // TODO: Implement delete message - isDeletingItem={false} + showDeleteButton + handleDeleteItem={() => onDeleteClick()} + isDeletingItem={isMutationInFlight} + disableDeleteButton={!isOwnMessage || deletedMessage} + DeleteDialogProps={{ + content: `Are you sure you want to delete this message? ${deleteDialogContent}`, + }} ContainerProps={{ flexDirection: isOwnMessage ? 'row' : 'row-reverse', }} diff --git a/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/types.ts b/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/types.ts index 5e8cd310..b5e15a8b 100644 --- a/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/types.ts +++ b/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/types.ts @@ -5,6 +5,7 @@ import { MessageItemFragment$key } from '../../../../../../../__generated__/Mess export interface MessageItemProps { messageRef: MessageItemFragment$key isFirstGroupedMessage?: boolean + isGroup?: boolean } export interface MessageItemContainerProps extends BoxProps { diff --git a/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx b/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx index 2ac246a2..e48ed57e 100644 --- a/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx +++ b/packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx @@ -97,6 +97,7 @@ const UserMessage: FC = ({ )} diff --git a/packages/components/schema.graphql b/packages/components/schema.graphql index 21058516..be14653e 100644 --- a/packages/components/schema.graphql +++ b/packages/components/schema.graphql @@ -154,6 +154,19 @@ type ChatRoomCreatePayload { clientMutationId: String } +input ChatRoomDeleteMessageInput { + id: ID! + clientMutationId: String +} + +type ChatRoomDeleteMessagePayload { + """May contain more than one error for same field.""" + errors: [ErrorType] + _debug: DjangoDebug + deletedMessage: MessageEdge + clientMutationId: String +} + """A Relay edge containing a `ChatRoom` and its cursor.""" type ChatRoomEdge { """The item at the end of the edge""" @@ -177,18 +190,17 @@ type ChatRoomEditMessagePayload { clientMutationId: String } -type ChatRoomOnMessagesCountUpdate { - profile: Profile +type ChatRoomOnMessage { + message: MessageEdge } -type ChatRoomOnNewMessage { - message: MessageEdge +type ChatRoomOnMessagesCountUpdate { + profile: Profile } type ChatRoomOnRoomUpdate { room: ChatRoomEdge removedParticipants: [ChatRoomParticipant] - addedParticipants: [ChatRoomParticipant] } type ChatRoomParticipant implements Node { @@ -312,7 +324,6 @@ type ChatRoomUpdatePayload { _debug: DjangoDebug room: ChatRoomEdge removedParticipants: [ChatRoomParticipant] - addedParticipants: [ChatRoomParticipant] clientMutationId: String } @@ -651,6 +662,7 @@ type Message implements Node { verb: Verbs room: ChatRoom inReplyTo: Message + deleted: Boolean! extraData: JSONString pk: Int! actionObject: Node @@ -702,6 +714,7 @@ type Mutation { chatRoomUpdate(input: ChatRoomUpdateInput!): ChatRoomUpdatePayload chatRoomSendMessage(input: ChatRoomSendMessageInput!): ChatRoomSendMessagePayload chatRoomEditMessage(input: ChatRoomEditMessageInput!): ChatRoomEditMessagePayload + chatRoomDeleteMessage(input: ChatRoomDeleteMessageInput!): ChatRoomDeleteMessagePayload chatRoomReadMessages(input: ChatRoomReadMessagesInput!): ChatRoomReadMessagesPayload chatRoomUnread(input: ChatRoomUnreadInput!): ChatRoomUnreadPayload chatRoomArchive(input: ChatRoomArchiveInput!): ChatRoomArchivePayload @@ -1650,7 +1663,7 @@ type RoleUpdatePayload { } type Subscription { - chatRoomOnNewMessage(roomId: ID!): ChatRoomOnNewMessage + chatRoomOnMessage(roomId: ID!): ChatRoomOnMessage chatRoomOnRoomUpdate(profileId: ID!): ChatRoomOnRoomUpdate chatRoomOnMessagesCountUpdate(profileId: ID!): ChatRoomOnMessagesCountUpdate onNotificationChange: OnNotificationChange From 59257d0a4604a931f4f38578b130a6f200ab6749 Mon Sep 17 00:00:00 2001 From: Ronan <62265281+Ronan-Fernandes@users.noreply.github.com> Date: Fri, 14 Feb 2025 09:29:08 -0300 Subject: [PATCH 2/4] BA-2197: default social input send behavior (#199) * Default social input send behavior * Versioning --- packages/components/schema.graphql | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/components/schema.graphql b/packages/components/schema.graphql index be14653e..b67ed8eb 100644 --- a/packages/components/schema.graphql +++ b/packages/components/schema.graphql @@ -154,20 +154,9 @@ type ChatRoomCreatePayload { clientMutationId: String } -input ChatRoomDeleteMessageInput { - id: ID! - clientMutationId: String -} - -type ChatRoomDeleteMessagePayload { - """May contain more than one error for same field.""" - errors: [ErrorType] - _debug: DjangoDebug - deletedMessage: MessageEdge - clientMutationId: String -} - -"""A Relay edge containing a `ChatRoom` and its cursor.""" +""" +A Relay edge containing a `ChatRoom` and its cursor. +""" type ChatRoomEdge { """The item at the end of the edge""" node: ChatRoom @@ -201,6 +190,7 @@ type ChatRoomOnMessagesCountUpdate { type ChatRoomOnRoomUpdate { room: ChatRoomEdge removedParticipants: [ChatRoomParticipant] + addedParticipants: [ChatRoomParticipant] } type ChatRoomParticipant implements Node { @@ -324,6 +314,7 @@ type ChatRoomUpdatePayload { _debug: DjangoDebug room: ChatRoomEdge removedParticipants: [ChatRoomParticipant] + addedParticipants: [ChatRoomParticipant] clientMutationId: String } From 329bcdb032bf5c6735e1f630e8a995bb8ab494c2 Mon Sep 17 00:00:00 2001 From: Pedro Tiburcio Date: Tue, 14 Jan 2025 08:51:09 -0500 Subject: [PATCH 3/4] fix: chat rooms refetch issue --- .../messages/web/ChatRoomsList/index.tsx | 91 ++++++++++++------- packages/components/schema.graphql | 19 +++- 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/packages/components/modules/messages/web/ChatRoomsList/index.tsx b/packages/components/modules/messages/web/ChatRoomsList/index.tsx index c21e2563..fdc6a92b 100644 --- a/packages/components/modules/messages/web/ChatRoomsList/index.tsx +++ b/packages/components/modules/messages/web/ChatRoomsList/index.tsx @@ -1,6 +1,14 @@ 'use client' -import { ChangeEventHandler, FC, useCallback, useMemo, useState, useTransition } from 'react' +import { + ChangeEventHandler, + FC, + useCallback, + useEffect, + useMemo, + useState, + useTransition, +} from 'react' import { LoadingState } from '@baseapp-frontend/design-system/components/web/displays' import { Searchbar as DefaultSearchbar } from '@baseapp-frontend/design-system/components/web/inputs' @@ -28,6 +36,7 @@ const ChatRoomsList: FC = ({ VirtuosoProps = {}, }) => { const [tab, setTab] = useState(CHAT_TAB_VALUES.active) + const [renderList, setRenderList] = useState(true) const [isRefetchPending, startRefetchTransition] = useTransition() const { data, loadNext, isLoadingNext, hasNext, refetch } = useRoomsList( @@ -44,39 +53,53 @@ const ChatRoomsList: FC = ({ const handleSearchChange: ChangeEventHandler = (e) => { const value = e.target.value || '' startTransition(() => { - refetch({ - q: value, - unreadMessages: isInUnreadTab, - archived: isInArchivedTab, - }) + refetch( + { + q: value, + unreadMessages: isInUnreadTab, + archived: isInArchivedTab, + }, + { fetchPolicy: 'network-only' }, + ) }) } const handleSearchClear = () => { startTransition(() => { reset() - refetch({ - q: '', - unreadMessages: isInUnreadTab, - archived: isInArchivedTab, - }) + refetch( + { + q: '', + unreadMessages: isInUnreadTab, + archived: isInArchivedTab, + }, + { fetchPolicy: 'network-only' }, + ) }) } const handleChange = (event: React.SyntheticEvent, newTab: string) => { setTab(newTab as ChatTabValues) startRefetchTransition(() => { + setRenderList(false) refetch( { q: searchValue, unreadMessages: newTab === CHAT_TAB_VALUES.unread, archived: newTab === CHAT_TAB_VALUES.archived, }, - { fetchPolicy: 'store-and-network' }, + { fetchPolicy: 'network-only' }, ) }) } + // Virtuoso has a bug where it does not recognize endReached if the data is changed while the component is still mounted. + // The `renderList` state is a workaround to force the component to dismount and remount, + // to ensure that Virtuoso will recognized endReached everytime the tab is changed + useEffect(() => { + setRenderList(true) + }, [data]) + const { id: selectedRoom, setChatRoom } = useChatRoom() const chatRooms = useMemo( () => data?.chatRooms?.edges?.filter((edge) => edge?.node).map((edge) => edge?.node) || [], @@ -126,29 +149,14 @@ const ChatRoomsList: FC = ({ ) const renderListContent = () => { - const emptyChatRoomsList = chatRooms.length === 0 - - if (!isPending && searchValue && emptyChatRoomsList) return + const hasEmptyStates = !isPending && chatRooms.length === 0 - if (!isPending && emptyChatRoomsList) return + if (hasEmptyStates) { + if (searchValue) return + return + } - return ( - renderItem(item)} - style={{ scrollbarWidth: 'none' }} - components={{ - Footer: renderLoadingState, - }} - endReached={() => { - if (hasNext) { - loadNext(5) - } - }} - {...VirtuosoProps} - /> - ) + return undefined } return ( @@ -194,6 +202,23 @@ const ChatRoomsList: FC = ({ {renderListContent()} + {renderList && ( + renderItem(item)} + style={{ scrollbarWidth: 'none' }} + components={{ + Footer: renderLoadingState, + }} + endReached={() => { + if (hasNext) { + loadNext(5) + } + }} + {...VirtuosoProps} + /> + )} ) } diff --git a/packages/components/schema.graphql b/packages/components/schema.graphql index b67ed8eb..be14653e 100644 --- a/packages/components/schema.graphql +++ b/packages/components/schema.graphql @@ -154,9 +154,20 @@ type ChatRoomCreatePayload { clientMutationId: String } -""" -A Relay edge containing a `ChatRoom` and its cursor. -""" +input ChatRoomDeleteMessageInput { + id: ID! + clientMutationId: String +} + +type ChatRoomDeleteMessagePayload { + """May contain more than one error for same field.""" + errors: [ErrorType] + _debug: DjangoDebug + deletedMessage: MessageEdge + clientMutationId: String +} + +"""A Relay edge containing a `ChatRoom` and its cursor.""" type ChatRoomEdge { """The item at the end of the edge""" node: ChatRoom @@ -190,7 +201,6 @@ type ChatRoomOnMessagesCountUpdate { type ChatRoomOnRoomUpdate { room: ChatRoomEdge removedParticipants: [ChatRoomParticipant] - addedParticipants: [ChatRoomParticipant] } type ChatRoomParticipant implements Node { @@ -314,7 +324,6 @@ type ChatRoomUpdatePayload { _debug: DjangoDebug room: ChatRoomEdge removedParticipants: [ChatRoomParticipant] - addedParticipants: [ChatRoomParticipant] clientMutationId: String } From 34b9312043ffadf18b4d47ba5d7982a481bfa122 Mon Sep 17 00:00:00 2001 From: Pedro Tiburcio Date: Mon, 10 Feb 2025 16:33:29 -0500 Subject: [PATCH 4/4] fix: decrease border radius on system messages --- .../modules/__shared__/web/ActionsOverlay/index.tsx | 11 +++++++++-- .../MessagesGroup/SystemMessage/styled.tsx | 2 +- packages/components/package.json | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/components/modules/__shared__/web/ActionsOverlay/index.tsx b/packages/components/modules/__shared__/web/ActionsOverlay/index.tsx index 4910273e..6366e9a2 100644 --- a/packages/components/modules/__shared__/web/ActionsOverlay/index.tsx +++ b/packages/components/modules/__shared__/web/ActionsOverlay/index.tsx @@ -172,9 +172,16 @@ const ActionsOverlay = forwardRef( > - + - Delete + + Delete + diff --git a/packages/components/modules/messages/web/MessagesList/MessagesGroup/SystemMessage/styled.tsx b/packages/components/modules/messages/web/MessagesList/MessagesGroup/SystemMessage/styled.tsx index 27165e4e..d1cf4ae4 100644 --- a/packages/components/modules/messages/web/MessagesList/MessagesGroup/SystemMessage/styled.tsx +++ b/packages/components/modules/messages/web/MessagesList/MessagesGroup/SystemMessage/styled.tsx @@ -3,7 +3,7 @@ import { Typography, styled } from '@mui/material' export const SystemMessageTypography = styled(Typography)(({ theme }) => ({ alignSelf: 'center', backgroundColor: theme.palette.grey[300], - borderRadius: theme.spacing(1), + borderRadius: theme.spacing(0.5), marginBottom: theme.spacing(1), marginTop: theme.spacing(2), padding: theme.spacing(0.5, 1), diff --git a/packages/components/package.json b/packages/components/package.json index 062a0930..80c96476 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/components", "description": "BaseApp components modules such as comments, notifications, messages, and more.", - "version": "1.0.8", + "version": "1.0.9", "sideEffects": false, "scripts": { "babel:transpile": "babel modules -d tmp-babel --extensions .ts,.tsx --ignore '**/__tests__/**','**/__storybook__/**'",