diff --git a/src/v4/chat/components/AmityLiveChatHeader/index.tsx b/src/v4/chat/components/AmityLiveChatHeader/index.tsx deleted file mode 100644 index 93e238217..000000000 --- a/src/v4/chat/components/AmityLiveChatHeader/index.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React from 'react'; -import millify from 'millify'; -import { FormattedMessage, useIntl } from 'react-intl'; -import Chat from '~/v4/icons/Chat'; -import UserRegular from '~/v4/icons/UserRegular'; -import useConnectionStates from '~/social/hooks/useConnectionStates'; -import ConnectionSpinner from '~/v4/icons/ConnectionSpinner'; -import { Typography } from '~/v4/core/components'; -import styles from './styles.module.css'; -import useChatInfo from '~/v4/chat/hooks/useChatInfo'; -import { Avatar, AVATAR_SIZE } from '~/v4/core/components/Avatar/Avatar'; -import { useAmityComponent } from '~/v4/core/hooks/uikit/index'; - -interface AmityLiveChatHeaderProps { - channel: Amity.Channel | null; - pageId?: string; - componentId?: string; -} - -export const AmityLiveChatHeader = ({ channel, pageId = '*' }: AmityLiveChatHeaderProps) => { - const componentId = 'chat_header'; - const { themeStyles } = useAmityComponent({ pageId, componentId }); - - const { chatName, chatAvatar } = useChatInfo({ channel }); - const { formatMessage } = useIntl(); - const isOnline = useConnectionStates(); - - return ( -
- } /> -
-
- {chatName || formatMessage({ id: 'loading' })} -
-
- {isOnline ? ( - <> - - - {millify(channel?.memberCount || 0)}{' '} - - - - ) : ( - <> - - - - - - )} -
-
-
- ); -}; - -export default AmityLiveChatHeader; diff --git a/src/v4/chat/components/AmityLiveChatHeader/livechatHeader.stories.tsx b/src/v4/chat/components/AmityLiveChatHeader/livechatHeader.stories.tsx deleted file mode 100644 index 317f5ac81..000000000 --- a/src/v4/chat/components/AmityLiveChatHeader/livechatHeader.stories.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import useChannelsCollection from '~/chat/hooks/collections/useChannelsCollection'; -import { AmityLiveChatHeader } from '.'; - -export default { - title: 'V4/AmityLiveChatHeader', -}; - -const SampleLiveChatHeader = () => { - const { channels, hasMore, loadMore, isLoading } = useChannelsCollection({ - membership: 'all', - sortBy: 'lastActivity', - types: ['live'], - limit: 1, - }); - - if (isLoading) return
Loading...
; - if (channels.length === 0) - return
No channels
; - return ( -
- -
- ); -}; - -export const LiveChatHeader = { - render: () => , - name: 'AmityLiveChatHeader', -}; diff --git a/src/v4/chat/components/AmityLiveChatHeader/styles.module.css b/src/v4/chat/components/AmityLiveChatHeader/styles.module.css deleted file mode 100644 index 09580e17d..000000000 --- a/src/v4/chat/components/AmityLiveChatHeader/styles.module.css +++ /dev/null @@ -1,24 +0,0 @@ -.messageListHeader { - display: flex; - padding: var(--asc-spacing-m1); - padding-top: 0; - gap: var(--asc-spacing-s1); - align-items: center; -} - -.displayName { - color: var(--asc-color-base-inverse); -} - -.memberCount { - color: var(--asc-color-base-default); - display: flex; - align-items: center; -} - -.memberIcon { - width: 0.75rem; - height: 0.75rem; - margin-right: var(--asc-spacing-xxs2); - fill: var(--asc-color-base-default); -} diff --git a/src/v4/chat/components/AmityLiveChatMessageComposeBar/index.tsx b/src/v4/chat/components/AmityLiveChatMessageComposeBar/index.tsx deleted file mode 100644 index cb118f8a9..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageComposeBar/index.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import { MessageRepository } from '@amityco/ts-sdk'; -import React, { RefObject, useEffect, useRef, useState } from 'react'; -import ArrowTop from '~/v4/icons/ArrowTop'; -import HomeIndicator from '../HomeIndicator'; -import styles from './styles.module.css'; -import InputText from '~/v4/core/components/InputText'; -import useMention from '~/v4/chat/hooks/useMention'; -import { useIntl } from 'react-intl'; -import useChannelPermission from '~/v4/chat/hooks/useChannelPermission'; -import { useCustomization } from '~/v4/core/providers/CustomizationProvider'; -import { useConfirmContext } from '~/v4/core/providers/ConfirmProvider'; -import { useLiveChatNotifications } from '~/v4/chat/providers/LiveChatNotificationProvider'; -import { useAmityComponent } from '~/v4/core/hooks/uikit'; - -const COMPOSEBAR_MAX_CHARACTER_LIMIT = 200; - -type ComposeActionTypes = { - replyMessage?: Amity.Message; - mentionMessage?: Amity.Message; - clearReplyMessage?: () => void; - clearMention?: () => void; -}; - -interface AmityLiveChatMessageComposeBarProps { - channel: Amity.Channel; - composeAction: ComposeActionTypes; - suggestionRef?: RefObject; - disabled?: boolean; - pageId?: string; -} - -type ComposeBarMention = { - id: string; - display: string; - childIndex: number; - index: number; - plainTextIndex: number; -}; - -export const AmityLiveChatMessageComposeBar = ({ - pageId = '*', - channel, - suggestionRef, - composeAction: { replyMessage, mentionMessage, clearReplyMessage, clearMention }, - disabled, -}: AmityLiveChatMessageComposeBarProps) => { - const [mentionList, setMentionList] = useState<{ - [key: ComposeBarMention['id']]: ComposeBarMention; - }>({}); - - const componentId = 'message_composer'; - const { themeStyles, config } = useAmityComponent({ pageId, componentId }); - - const { confirm } = useConfirmContext(); - const notification = useLiveChatNotifications(); - - const commentInputRef = useRef(null); - - const { queryMentionees, mentionees, onChange, markup, metadata, text } = useMention({ - targetId: channel.channelId, - targetType: 'channel', - }); - - const { isModerator } = useChannelPermission(channel.channelId); - - const { formatMessage } = useIntl(); - - const sendMessage = async () => { - if (!channel) return; - if (text?.trim().length === 0) return; - - if (text.trim().length > (config?.message_limit || COMPOSEBAR_MAX_CHARACTER_LIMIT)) { - confirm({ - title: formatMessage({ id: 'livechat.error.tooLongMessage.title' }), - content: formatMessage({ id: 'livechat.error.tooLongMessage.description' }), - okText: formatMessage({ id: 'general.action.ok' }), - }); - return; - } - - try { - await MessageRepository.createMessage({ - tags: [], - subChannelId: channel.channelId, - data: { text: text.trim() }, - dataType: 'text', - mentionees, - metadata, - parentId: replyMessage?.messageId || undefined, - }); - - onChange({ text: '', plainText: '', mentions: [] }); - } catch (error) { - const errorMessage = (error as Error).message; - let notificationMessage = formatMessage({ id: 'livechat.error.sendingMessage.error' }); - - if (errorMessage === 'Amity SDK (400308): Text contain blocked word') { - notificationMessage = formatMessage({ id: 'livechat.error.sendingMessage.blockedWord' }); - } else if ( - errorMessage === 'Amity SDK (400309): Data contain link that is not in whitelist' - ) { - notificationMessage = formatMessage({ id: 'livechat.error.sendingMessage.notAllowLink' }); - } else if (errorMessage === 'Amity SDK (400302): User is muted') { - notificationMessage = formatMessage({ id: 'livechat.member.muted.error' }); - } - - notification.error({ - content: notificationMessage, - }); - - return; - } - - setMentionList({}); - clearReplyMessage && clearReplyMessage(); - }; - - useEffect(() => { - commentInputRef.current?.focus(); - }, []); - - return ( -
-
-
- queryMentionees(query)} - onChange={(e) => { - onChange({ - text: e.text, - plainText: e.plainText, - mentions: e.mentions, - }); - }} - value={markup} - queryMentionees={queryMentionees} - mentionColor={styles.mentionText} - /> -
-
- sendMessage()} /> - {/* {message.length > 0 ? ( - - ) : ( - - )} */} -
-
- -
- ); -}; - -export default AmityLiveChatMessageComposeBar; diff --git a/src/v4/chat/components/AmityLiveChatMessageComposeBar/livechatMessageComposeBar.stories.tsx b/src/v4/chat/components/AmityLiveChatMessageComposeBar/livechatMessageComposeBar.stories.tsx deleted file mode 100644 index 693604f08..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageComposeBar/livechatMessageComposeBar.stories.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import useChannelsCollection from '~/chat/hooks/collections/useChannelsCollection'; -import { AmityLiveChatMessageComposeBar } from '.'; - -export default { - title: 'V4/AmityLiveChatMessageComposeBar', -}; - -const SampleLiveChatHeader = () => { - const { channels, hasMore, loadMore, isLoading } = useChannelsCollection({ - membership: 'all', - sortBy: 'lastActivity', - types: ['live'], - limit: 1, - }); - - if (isLoading) return
Loading...
; - if (channels.length === 0) - return
No channels
; - return ( -
- -
- ); -}; - -export const LiveChatHeader = { - render: () => , - name: 'AmityLiveChatMessageComposeBar', -}; diff --git a/src/v4/chat/components/AmityLiveChatMessageComposeBar/styles.module.css b/src/v4/chat/components/AmityLiveChatMessageComposeBar/styles.module.css deleted file mode 100644 index 61c896bb0..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageComposeBar/styles.module.css +++ /dev/null @@ -1,75 +0,0 @@ -.sendButton { - border-radius: var(--asc-border-radius-xxl); - width: 1rem; - height: 1rem; - background-color: var(--asc-color-primary-default); - cursor: pointer; - padding: var(--asc-spacing-xxs2); - fill: white; -} - -.reactionButton { - width: 2rem; - height: 2rem; - cursor: pointer; -} - -.sendButtonContainer { - display: flex; - align-items: center; - gap: var(--asc-spacing-s2); - width: 2rem; - height: 2rem; -} - -.composeBarContainer { - min-height: 3.5rem; - z-index: 99; - background-color: inherit; -} - -.composeBar { - display: flex; - align-items: center; - gap: var(--asc-spacing-s2); - padding: var(--asc-spacing-s1) var(--asc-spacing-s2); - background-color: inherit; - box-shadow: 0 -1px 0 0 var(--asc-color-base-shade4); -} - -.textInputContainer { - display: flex; - width: calc(100% - 2.8rem); - - & > div { - width: 100%; - border-radius: var(--asc-border-radius-xxl); - background: var(--asc-color-secondary-shade4); - - textarea { - padding: 0.563rem 1rem; - background-color: transparent; - } - } -} - -.composeBarLoading { - width: 100%; - height: var(--asc-spacing-l1); - padding: var(--asc-spacing-s1) var(--asc-spacing-s2); - border-radius: var(--asc-border-radius-sm); - border: var(--asc-border-radius-none); - background-color: var(--asc-color-secondary-default); - color: var(--asc-color-base-inverse); - display: flex; - align-items: center; - - span { - padding-left: var(--asc-spacing-s1); - font-weight: var(--asc-text-font-weight-light); - } -} - -.mentionText { - color: var(--asc-color-primary-default); -} diff --git a/src/v4/chat/components/AmityLiveChatMessageList/index.tsx b/src/v4/chat/components/AmityLiveChatMessageList/index.tsx deleted file mode 100644 index 84e7a7e69..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageList/index.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import React from 'react'; -import InfiniteScroll from 'react-infinite-scroll-component'; -import styles from './styles.module.css'; -import LivechatLoadingIndicator from '~/v4/chat/components/LivechatLoadingIndicator'; -import useSDK from '~/core/hooks/useSDK'; -import AmityLiveChatMessageSenderView from '../AmityLiveChatMessageSenderView'; -import AmityLiveChatMessageReceiverView from '../AmityLiveChatMessageReceiverView'; -import { deleteMessage, flagMessage } from '~/v4/utils'; -import useMessagesCollection from '~/chat/hooks/collections/useMessagesCollection'; -import { FormattedMessage, useIntl } from 'react-intl'; -import { Typography } from '~/v4/core/components'; -import Redo from '~/v4/icons/Redo'; -import { unFlagMessage } from '~/v4/utils/unFlagMessage'; -import { useConfirmContext } from '~/v4/core/providers/ConfirmProvider'; -import { useLiveChatNotifications } from '~/v4/chat/providers/LiveChatNotificationProvider'; -import { useCopyMessage } from '~/v4/core/hooks'; -import { useAmityComponent } from '~/v4/core/hooks/uikit'; - -interface AmityLiveChatMessageListProps { - pageId?: string; - channel: Amity.Channel; - replyMessage: (message: Amity.Message<'text'>) => void; -} - -export const AmityLiveChatMessageList = ({ - pageId = '*', - channel, - replyMessage, -}: AmityLiveChatMessageListProps) => { - const componentId = 'message_list'; - - const sdk = useSDK(); - const containerRef = React.useRef(null); - const { formatMessage } = useIntl(); - const [height, setHeight] = React.useState(undefined); - const { confirm } = useConfirmContext(); - const notification = useLiveChatNotifications(); - const copyMessage = useCopyMessage(); - - const { themeStyles } = useAmityComponent({ pageId, componentId }); - - const { - messages: rawMessages, - hasMore, - loadMore, - isLoading, - error, - } = useMessagesCollection({ - subChannelId: channel.channelId, - sortBy: 'segmentDesc', - limit: 10, - includeDeleted: true, - }); - - const messages = rawMessages as Amity.Message<'text'>[]; - - const onDeleteMessage = (messageId: string) => { - confirm({ - title: formatMessage({ id: 'livechat.modal.delete.message.title' }), - content: formatMessage({ id: 'livechat.modal.delete.message.content' }), - cancelText: formatMessage({ id: 'cancel' }), - okText: formatMessage({ id: 'delete' }), - onOk: () => - deleteMessage(messageId, { - onError: () => - notification.error({ - content: formatMessage({ id: 'livechat.delete.message.error' }), - }), - }), - }); - }; - - React.useEffect(() => { - const updateHeight = () => { - if (containerRef.current) { - setHeight(containerRef.current.clientHeight); - } - }; - - const resizeObserver = new ResizeObserver(updateHeight); - if (containerRef.current) { - resizeObserver.observe(containerRef.current); - } - - return () => { - if (containerRef.current) { - resizeObserver.unobserve(containerRef.current); - } - }; - }, []); - - if (error) { - return ( -
-
- -
- - - -
- ); - } - - return ( -
- {containerRef.current && ( - - -
- ) : null - } - inverse={true} - dataLength={messages.length} - height={containerRef.current.clientHeight} - > - {messages.map((message, i) => { - if (message.creatorId === sdk.currentUserId) - return ( - replyMessage(message), - onDelete: () => onDeleteMessage(message.messageId), - onCopy: () => message.data?.text && copyMessage(message.data?.text), - } - : undefined - } - key={message.messageId} - containerRef={containerRef} - pageId={pageId} - componentId={componentId} - /> - ); - - return ( - replyMessage(message), - onDelete: () => onDeleteMessage(message.messageId), - onCopy: () => message.data?.text && copyMessage(message.data?.text), - onFlag: () => - flagMessage( - message.messageId, - () => - notification.success({ - content: formatMessage({ id: 'livechat.report.message.success' }), - }), - () => - notification.error({ - content: formatMessage({ id: 'livechat.report.message.error' }), - }), - ), - onUnflag: () => - unFlagMessage( - message.messageId, - () => - notification.success({ - content: formatMessage({ id: 'livechat.unReport.message.success' }), - }), - () => - notification.error({ - content: formatMessage({ id: 'livechat.unReport.message.error' }), - }), - ), - }} - key={message.messageId} - containerRef={containerRef} - pageId={pageId} - componentId={componentId} - /> - ); - })} - - )} - - ); -}; - -export default AmityLiveChatMessageList; diff --git a/src/v4/chat/components/AmityLiveChatMessageList/livechatMessageList.stories.tsx b/src/v4/chat/components/AmityLiveChatMessageList/livechatMessageList.stories.tsx deleted file mode 100644 index 40567970b..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageList/livechatMessageList.stories.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import useChannelsCollection from '~/chat/hooks/collections/useChannelsCollection'; -import { AmityLiveChatMessageList } from '.'; - -export default { - title: 'V4/AmityLiveChatMessageList', -}; - -const SampleLiveChatMessageList = () => { - const { channels, hasMore, loadMore, isLoading } = useChannelsCollection({ - membership: 'all', - sortBy: 'lastActivity', - types: ['live'], - limit: 1, - }); - - if (isLoading) return
Loading...
; - if (channels.length === 0) - return
No channels
; - return ( -
- console.log('reply', message)} - /> -
- ); -}; - -export const LiveChatMessageList = { - render: () => , - name: 'AmityLiveChatMessageList', -}; diff --git a/src/v4/chat/components/AmityLiveChatMessageList/styles.module.css b/src/v4/chat/components/AmityLiveChatMessageList/styles.module.css deleted file mode 100644 index bda68abe2..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageList/styles.module.css +++ /dev/null @@ -1,39 +0,0 @@ -.infiniteScrollContainer { - display: flex; - flex-direction: column-reverse; - flex-grow: 1; - overflow-y: hidden; -} - -.loadingIndicatorWrap { - margin: auto; - padding-top: var(--asc-spacing-m1); - padding-bottom: var(--asc-spacing-m1); -} - -.loadingIndicator { - width: 1.25rem; - height: 1.25rem; -} - -.infiniteScrollInner { - display: flex; - flex-direction: column-reverse; - overflow: auto; -} - -.customStatusContainer { - display: flex; - flex-direction: column; - justify-content: center; - width: 100%; - height: 100%; - align-items: center; - color: var(--asc-color-secondary-shade2); - font-weight: var(--asc-text-font-weight-light); - font-size: var(--asc-text-font-size-md); -} - -.iconContainer { - margin-bottom: var(--asc-spacing-m1); -} diff --git a/src/v4/chat/components/AmityLiveChatMessageReceiverView/index.tsx b/src/v4/chat/components/AmityLiveChatMessageReceiverView/index.tsx deleted file mode 100644 index 74859a42a..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageReceiverView/index.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import useUser from '~/core/hooks/useUser'; -import useImage from '~/core/hooks/useImage'; -import LiveChatMessageContent from '../LiveChatMessageContent'; -import { AmityMessageActionType } from '../LiveChatMessageContent/MessageAction'; - -interface AmityLiveChatMessageReceiverViewProps { - pageId?: string; - componentId?: string; - message: Amity.Message; - containerRef: React.RefObject; - action: AmityMessageActionType; -} - -export const AmityLiveChatMessageReceiverView = ({ - pageId = '*', - componentId = '*', - message, - containerRef, - action, -}: AmityLiveChatMessageReceiverViewProps) => { - const user = useUser(message.creatorId); - const avatarFileUrl = useImage({ fileId: user?.avatarFileId, imageSize: 'small' }); - - return ( - } - userDisplayName={user?.displayName} - avatarUrl={avatarFileUrl} - containerRef={containerRef} - action={action} - /> - ); -}; - -export default AmityLiveChatMessageReceiverView; diff --git a/src/v4/chat/components/AmityLiveChatMessageReceiverView/messageReceiver.stories.tsx b/src/v4/chat/components/AmityLiveChatMessageReceiverView/messageReceiver.stories.tsx deleted file mode 100644 index cc6817283..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageReceiverView/messageReceiver.stories.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React, { useState, useRef, useEffect } from 'react'; -import useChannelsCollection from '~/chat/hooks/collections/useChannelsCollection'; -import useMessagesCollection from '~/chat/hooks/collections/useMessagesCollection'; -import AmityLiveChatMessageReceiverView from '.'; - -export default { - title: 'V4/AmityMessageReceiverView', -}; - -const SampleMessageReceiverView = () => { - const ref = useRef(null); - const { channels, isLoading: isLoadingChannel } = useChannelsCollection({ - membership: 'all', - sortBy: 'lastActivity', - types: ['live'], - limit: 1, - }); - - const { messages, isLoading: isLoadingMessage } = useMessagesCollection({ - subChannelId: channels.length > 0 ? channels[0].defaultSubChannelId : '', - limit: 1, - }); - - if (isLoadingChannel) return
Loading...
; - if (channels.length === 0) return
No channels
; - if (isLoadingMessage) return
Loading...
; - if (messages.length === 0) return
No messages
; - - return ( -
- -
- ); -}; - -export const LiveChatStory = { - render: () => , - name: 'AmityLiveChatMessageReceiver', -}; diff --git a/src/v4/chat/components/AmityLiveChatMessageSenderView/index.tsx b/src/v4/chat/components/AmityLiveChatMessageSenderView/index.tsx deleted file mode 100644 index 1b5f8f870..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageSenderView/index.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import useUser from '~/core/hooks/useUser'; -import useImage from '~/core/hooks/useImage'; -import LiveChatMessageContent from '../LiveChatMessageContent'; -import { AmityMessageActionType } from '../LiveChatMessageContent/MessageAction'; - -interface AmityLiveChatMessageSenderViewProps { - pageId?: string; - componentId?: string; - message: Amity.Message; - containerRef: React.RefObject; - action?: AmityMessageActionType; -} - -export const AmityLiveChatMessageSenderView = ({ - pageId = '*', - componentId = '*', - message, - containerRef, - action, -}: AmityLiveChatMessageSenderViewProps) => { - const user = useUser(message.creatorId); - const avatarFileUrl = useImage({ fileId: user?.avatarFileId, imageSize: 'small' }); - - return ( - } - userDisplayName={user?.displayName} - avatarUrl={avatarFileUrl} - containerRef={containerRef} - action={action} - pageId={pageId} - componentId={componentId} - /> - ); -}; - -export default AmityLiveChatMessageSenderView; diff --git a/src/v4/chat/components/AmityLiveChatMessageSenderView/messageSender.stories.tsx b/src/v4/chat/components/AmityLiveChatMessageSenderView/messageSender.stories.tsx deleted file mode 100644 index 65e4cc4c2..000000000 --- a/src/v4/chat/components/AmityLiveChatMessageSenderView/messageSender.stories.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React, { useRef } from 'react'; -import useChannelsCollection from '~/chat/hooks/collections/useChannelsCollection'; -import useMessagesCollection from '~/chat/hooks/collections/useMessagesCollection'; -import AmityLiveChatMessageSenderView from '.'; - -export default { - title: 'V4/AmityMessageSenderView', -}; - -const SampleMessageSenderView = () => { - const ref = useRef(null); - const { channels, isLoading: isLoadingChannel } = useChannelsCollection({ - membership: 'all', - sortBy: 'lastActivity', - types: ['live'], - limit: 1, - }); - - const { messages, isLoading: isLoadingMessage } = useMessagesCollection({ - subChannelId: channels.length > 0 ? channels[0].defaultSubChannelId : '', - limit: 1, - }); - - if (isLoadingChannel) return
Loading...
; - if (channels.length === 0) return
No channels
; - if (isLoadingMessage) return
Loading...
; - if (messages.length === 0) return
No messages
; - - return ( -
- -
- ); -}; - -export const LiveChatStory = { - render: () => , - name: 'AmityLiveChatMessageSender', -}; diff --git a/src/v4/chat/components/HomeIndicator/index.tsx b/src/v4/chat/components/HomeIndicator/index.tsx deleted file mode 100644 index 3e848887e..000000000 --- a/src/v4/chat/components/HomeIndicator/index.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import styles from './styles.module.css'; - -const HomeIndecator = () => { - return ( -
-
-
- ); -}; - -export default HomeIndecator; diff --git a/src/v4/chat/components/HomeIndicator/styles.module.css b/src/v4/chat/components/HomeIndicator/styles.module.css deleted file mode 100644 index c8fc4e832..000000000 --- a/src/v4/chat/components/HomeIndicator/styles.module.css +++ /dev/null @@ -1,12 +0,0 @@ -.homeIndicatorContainer { - padding-top: 1.3125rem; - padding-bottom: 0.5rem; -} - -.homeIndicator { - margin: auto; - width: 8.375rem; - height: 0.3125rem; - border-radius: var(--asc-border-radius-full); - background-color: var(--asc-color-base-shade1); -} diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageAction/index.tsx b/src/v4/chat/components/LiveChatMessageContent/MessageAction/index.tsx deleted file mode 100644 index 38bfc9136..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageAction/index.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import React, { useRef } from 'react'; -import styles from './styles.module.css'; -import Kebub from '~/v4/icons/Kebub'; -import { useIntl } from 'react-intl'; -import Popover from '~/v4/core/components/Popover'; -import Reply from '~/v4/icons/Reply'; -import Copy from '~/v4/icons/Copy'; -import Bin from '~/v4/icons/Bin'; -import Flag from '~/v4/icons/Flag'; -import { Typography } from '~/v4/core/components'; - -export type AmityMessageActionType = { - onCopy?: () => void; - onFlag?: () => void; - onUnflag?: () => void; - onDelete?: () => void; - onReply?: () => void; - onMention?: () => void; -}; - -interface MessageActionProps { - isOwner: boolean; - isModerator: boolean; - isFlagged?: boolean; - action: AmityMessageActionType; - containerRef: React.RefObject; -} - -const MessageAction = ({ - isOwner, - isModerator, - isFlagged, - action, - containerRef, -}: MessageActionProps) => { - const [isPopoverOpen, setIsPopoverOpen] = React.useState(false); - const { formatMessage } = useIntl(); - const clickMeButtonRef = useRef(null); - - const onCopyMessage = () => { - action.onCopy && action.onCopy(); - setIsPopoverOpen(false); - }; - - const onReplyMessage = () => { - action.onReply && action.onReply(); - setIsPopoverOpen(false); - }; - - const onDeleteMessage = () => { - action.onDelete && action.onDelete(); - setIsPopoverOpen(false); - }; - - const onFlagMessage = () => { - action.onFlag && action.onFlag(); - setIsPopoverOpen(false); - }; - - const onUnFlagMessage = () => { - action.onUnflag && action.onUnflag(); - setIsPopoverOpen(false); - }; - - return ( - <> - setIsPopoverOpen(false)} - isOpen={isPopoverOpen} - align="start" - parentElement={containerRef?.current || undefined} - content={ - <> -
-
- - {formatMessage({ id: 'livechat.messageBubble.reply.button' })} - -
- -
-
-
- - {formatMessage({ id: 'livechat.messageBubble.copy.button' })} - -
- -
- {/* TODO: release 1.1 hide these action, will be implement in release 1.2 */} - {/* {!isOwner || ( -
{ - onMention && onMention(); - }} - > -
- {formatMessage({ id: 'livechat.messageBubble.mention.button' })} -
- -
- )} */} - {(isModerator || !isOwner) && ( -
-
- - {formatMessage({ - id: `${ - isFlagged - ? 'livechat.messageBubble.unReport.button' - : 'livechat.messageBubble.report.button' - }`, - })} - -
- -
- )} - {(isOwner || isModerator) && ( -
-
- - {formatMessage({ id: 'livechat.messageBubble.delete.button' })} - -
- -
- )} - - } - > -
{ - setIsPopoverOpen(!isPopoverOpen); - }} - > - -
-
- {/* */} - - ); -}; - -export default MessageAction; diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageAction/styles.module.css b/src/v4/chat/components/LiveChatMessageContent/MessageAction/styles.module.css deleted file mode 100644 index 01331658a..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageAction/styles.module.css +++ /dev/null @@ -1,66 +0,0 @@ -.optionButton { - display: flex; - - :hover { - cursor: pointer; - background-color: var(--asc-color-secondary-shade4); - border-radius: var(--asc-border-radius-sm); - } -} - -.optionIcon { - fill: var(--asc-color-secondary-shade2); - width: auto; - height: 1.25rem; -} - -.reactionIcon { - width: 1.25rem; - height: 1.25rem; -} - -.timestamp { - font-family: var(--asc-text-global-font-family); - color: var(--asc-color-base-shade2); - font-size: 0.5rem; - line-height: 0.75rem; - margin-bottom: var(--asc-spacing-s1); -} - -.messageActionButton { - cursor: pointer; - display: flex; - padding: var(--asc-spacing-s2) var(--asc-spacing-m1); - justify-content: space-between; -} - -.messageActionButtonText { - color: var(--asc-color-base-inverse); -} - -.messageDangerActionButtonText { - color: var(--asc-color-alert); -} - -.copyIcon { - fill: var(--asc-color-base-inverse); -} - -.replyIcon { - fill: var(--asc-color-base-inverse); -} - -.binIcon { - width: 1.25rem; - height: 1.25rem; - fill: var(--asc-color-alert); -} - -.mentionIcon { - width: 1.25rem; - height: 1.25rem; -} - -.flagIcon { - width: 1rem; -} diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageBubble/index.tsx b/src/v4/chat/components/LiveChatMessageContent/MessageBubble/index.tsx deleted file mode 100644 index e117e257d..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageBubble/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React from 'react'; -import styles from './styles.module.css'; -import useUser from '~/core/hooks/useUser'; -import useMessage from '~/chat/hooks/useMessage'; -import MessageTextWithMention from '../MessageTextWithMention'; -import { Typography } from '~/v4/core/components'; -import useSDK from '~/core/hooks/useSDK'; - -interface MessageBubbleProps { - message: Amity.Message<'text'>; -} - -const MessageBubble = ({ message }: MessageBubbleProps) => { - const userId = useSDK().currentUserId; - const isMentionToMe = message.metadata?.mentioned?.some( - (mention: { index: number; userId: string; type: 'user' | 'channel'; length: number }) => - mention.userId === userId || mention.type === 'channel', - ); - - if (message && message.parentId) { - const parentMessage = useMessage(message.parentId) as Amity.Message<'text'>; - const parentUser = useUser(parentMessage?.creatorId); - - if (!parentMessage || !parentUser) return null; - - return ( -
-
-
- {parentUser.displayName} -
- - {parentMessage.data?.text} - -
-
- -
-
- ); - } - - return ( -
- -
- ); -}; - -export default MessageBubble; diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageBubble/styles.module.css b/src/v4/chat/components/LiveChatMessageContent/MessageBubble/styles.module.css deleted file mode 100644 index 089caff55..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageBubble/styles.module.css +++ /dev/null @@ -1,50 +0,0 @@ -.messageBubble { - padding: var(--asc-spacing-s1) 0.625rem; - border-radius: var(--asc-border-radius-lg); - border-top-left-radius: var(--asc-border-radius-none); - color: var(--asc-color-base-inverse); - background-color: var(--asc-color-base-shade4); - max-width: 7.5rem; - word-break: break-word; - overflow-wrap: break-word; - hyphens: auto; - white-space: pre-wrap; -} - -.messageBubble[data-mentioned='true'] { - border: 1px solid var(--asc-color-primary-default); -} - -.messageRepliedBubble { - width: 12.5rem; -} - -.messageParentContainer { - padding: var(--asc-spacing-s2); - border-radius: var(--asc-border-radius-lg) var(--asc-border-radius-lg) 0 0; - background-color: var(--asc-color-base-shade3); -} - -.messageParentDisplayName { - color: var(--asc-color-base-inverse); -} - -.messageParentText { - color: var(--asc-color-base-default); - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; -} - -.messageChildContainer { - border-radius: 0 0 var(--asc-border-radius-lg) var(--asc-border-radius-lg); - background-color: var(--asc-color-base-shade4); - color: var(--asc-color-base-inverse); - padding: var(--asc-spacing-s1) var(--asc-spacing-s2); -} - -.messageChildText { - -webkit-line-clamp: 2; - overflow: hidden; - text-overflow: ellipsis; -} diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageBubbleContainer/index.tsx b/src/v4/chat/components/LiveChatMessageContent/MessageBubbleContainer/index.tsx deleted file mode 100644 index 4031d2b1f..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageBubbleContainer/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import styles from './styles.module.css'; -import User from '~/v4/icons/User'; -import { Typography } from '~/v4/core/components'; -import { Avatar, AVATAR_SIZE } from '~/v4/core/components/Avatar'; - -interface MessageBubbleContainerProps { - avatarUrl?: string; - displayName?: string; - children: React.ReactNode; -} - -const MessageBubbleContainer = ({ - avatarUrl, - displayName, - children, -}: MessageBubbleContainerProps) => { - return ( -
- } /> - -
-
- {/* TODO: release 1.1 hide moderator badge, will be implemented in release 1.2 */} - {/* {isBadgeShow && } */} - {displayName} -
- - {children} -
-
- ); -}; - -export default MessageBubbleContainer; diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageBubbleContainer/styles.module.css b/src/v4/chat/components/LiveChatMessageContent/MessageBubbleContainer/styles.module.css deleted file mode 100644 index 163d6932c..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageBubbleContainer/styles.module.css +++ /dev/null @@ -1,23 +0,0 @@ -.messageItemContainer { - padding: var(--asc-spacing-s1) var(--asc-spacing-m1); - display: flex; - gap: var(--asc-spacing-s1); -} - -.userDisplayName { - display: flex; - gap: var(--asc-spacing-xxs2); - align-items: center; - color: var(--asc-color-secondary-shade2); - margin-bottom: var(--asc-spacing-xxs2); -} - -.avatar { - width: 2rem; - height: 2rem; -} - -.moderatorBadge { - width: 1rem; - height: 1rem; -} diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageReaction/index.tsx b/src/v4/chat/components/LiveChatMessageContent/MessageReaction/index.tsx deleted file mode 100644 index 356d7538a..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageReaction/index.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import React, { useCallback, useRef, useEffect, useState } from 'react'; -import { MessageQuickReaction } from '~/v4/chat/components/MessageQuickReaction'; -import { MessageReactionPicker } from '~/v4/chat/components/MessageReactionPicker'; -import { convertRemToPx, getCssVariableValue } from '~/v4/helpers/utils'; -import styles from './styles.module.css'; - -export const MessageReaction = ({ - pageId = '*', - componentId = '*', - message, - containerRef, -}: { - pageId?: string; - componentId?: string; - message: Amity.Message; - containerRef?: React.RefObject; -}) => { - const [isReactionPickerOpen, setIsReactionPickerOpen] = useState(false); - - const [isHoveredQuickReaction, setIsHoveredQuickReaction] = useState(false); - const [isHoveredReactionPicker, setIsHoveredReactionPicker] = useState(false); - - const [transform, setTransform] = React.useState(); - const ref = useRef(null); - - const isHoveredQuickReactionRef = useRef(isHoveredQuickReaction); - - useEffect(() => { - isHoveredQuickReactionRef.current = isHoveredQuickReaction; - }, [isHoveredQuickReaction]); - - const onOpenPicker = useCallback(() => { - if (!isHoveredQuickReactionRef.current) return; - - const timeoutId = setTimeout(() => { - if (isHoveredQuickReactionRef.current) { - setIsReactionPickerOpen(true); - } - }, 500); - - return () => clearTimeout(timeoutId); - }, []); - - const isHoveredReactionPickerRef = useRef(isHoveredReactionPicker); - - useEffect(() => { - isHoveredReactionPickerRef.current = isHoveredReactionPicker; - }, [isHoveredReactionPicker]); - - const onClosePicker = useCallback(() => { - setTimeout(() => { - if (!isHoveredReactionPickerRef.current) { - setIsReactionPickerOpen(false); - } - }, 1000); - }, []); - - const handleClickOutside = useCallback((event) => { - if (ref.current && !ref.current.contains(event.target)) { - setIsReactionPickerOpen(false); - } - }, []); - - const calculateTransform = () => { - if (!ref.current || !containerRef?.current) return 'translate(-50%, 0px)'; - - const parentRect = containerRef.current.getBoundingClientRect(); - const pickerRect = ref.current.getBoundingClientRect(); - - if (!parentRect || !pickerRect) return 'translate(-50%, 0px)'; - - const padding = convertRemToPx( - Number(getCssVariableValue('--asc-spacing-s1').replace('rem', '')), - ); - - const overflowRight = pickerRect.right - parentRect.right; - const overflowLeft = parentRect.left - pickerRect.left; - - if (overflowRight > 0) { - // If overflowing to the right, adjust the transform - return `translate(calc(-50% - ${overflowRight}px), 0px)`; - } else if (overflowLeft > 0) { - // If overflowing to the left, adjust the transform - return `translate(calc(-50% + ${overflowLeft}px), 0px)`; - } else { - // If not overflowing, keep the original transform - return 'translate(-50%, 0px)'; - } - }; - - const onMouseDown = (event: any) => { - handleClickOutside(event); - }; - - const onSelectReaction = () => { - setIsHoveredQuickReaction(false); - setIsHoveredReactionPicker(false); - setIsReactionPickerOpen(false); - }; - - useEffect(() => { - document.addEventListener('mousedown', onMouseDown); - document.addEventListener('touchstart', handleClickOutside); - return () => { - document.removeEventListener('mousedown', handleClickOutside); - document.removeEventListener('touchstart', handleClickOutside); - }; - }, []); - - useEffect(() => { - if (isHoveredQuickReaction) { - !isReactionPickerOpen && onOpenPicker(); - } else { - isReactionPickerOpen && onClosePicker(); - } - }, [isHoveredQuickReaction, isReactionPickerOpen]); - - return ( -
- {isReactionPickerOpen && ( -
setIsHoveredReactionPicker(true)} - onMouseLeave={() => { - setIsHoveredReactionPicker(false); - }} - > - -
- )} - -
{ - setIsHoveredQuickReaction(true); - }} - onMouseLeave={() => { - setIsHoveredQuickReaction(false); - }} - > - -
-
- ); -}; diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageReaction/styles.module.css b/src/v4/chat/components/LiveChatMessageContent/MessageReaction/styles.module.css deleted file mode 100644 index 5d1c882ec..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageReaction/styles.module.css +++ /dev/null @@ -1,15 +0,0 @@ -.reactionContainer { - position: relative; -} - -.reactionPickerWrap { - position: absolute; - bottom: 1.5rem; - left: 0.625rem; - transform: translate(-50%, 0); -} - -.reactionButton { - width: 1.25rem; - height: 1.25rem; -} diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageTextWithMention/index.tsx b/src/v4/chat/components/LiveChatMessageContent/MessageTextWithMention/index.tsx deleted file mode 100644 index 4cd103569..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageTextWithMention/index.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react'; -import styles from './styles.module.css'; -import { Typography } from '~/v4/core/components'; -import HyperLinkText from '~/v4/core/components/HyperlinkText/index'; - -interface MessageTextWithMentionProps { - message: Amity.Message<'text'>; - className?: string; -} - -const MessageTextWithMention = ({ message, className }: MessageTextWithMentionProps) => { - const mentionList = message.metadata?.mentioned as { - index: number; - userId: string; - type: 'user' | 'channel'; - length: number; - }[]; - const mentionListSorted = mentionList?.sort((a, b) => a.index - b.index); - - if (mentionListSorted?.length) { - const messageText = message.data?.text || ''; - const segments = []; - - let currentIndex = 0; - - mentionListSorted.forEach((mention) => { - const start = mention.index; - const end = mention.index + mention.length + 1; - const beforeMention = messageText.slice(currentIndex, start); - const mentionText = messageText.slice(start, end); - - if (beforeMention) { - segments.push({ text: beforeMention, isMention: false }); - } - - segments.push({ text: mentionText, isMention: true }); - currentIndex = end; - }); - - const afterLastMention = messageText.slice(currentIndex); - if (afterLastMention) { - segments.push({ text: afterLastMention, isMention: false }); - } - - return ( - - {segments.map((segment, index) => - segment.isMention ? ( - - {segment.text} - - ) : ( - - {segment.text} - - ), - )} - - ); - } - - return ( - - {message.data?.text} - - ); -}; - -export default MessageTextWithMention; diff --git a/src/v4/chat/components/LiveChatMessageContent/MessageTextWithMention/styles.module.css b/src/v4/chat/components/LiveChatMessageContent/MessageTextWithMention/styles.module.css deleted file mode 100644 index 9e77a66cd..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/MessageTextWithMention/styles.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.mentionText { - color: var(--asc-color-primary-default); -} - -.hyperlink { - color: var(--asc-color-primary-default); -} diff --git a/src/v4/chat/components/LiveChatMessageContent/index.tsx b/src/v4/chat/components/LiveChatMessageContent/index.tsx deleted file mode 100644 index 01bed88fc..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/index.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import React, { useState } from 'react'; -import styles from './styles.module.css'; -import { Typography } from '~/v4/core/components'; -import MessageAction, { AmityMessageActionType } from './MessageAction'; -import MessageBubbleContainer from './MessageBubbleContainer'; -import { FormattedTime, useIntl } from 'react-intl'; -import Bin from '~/v4/icons/Bin'; -import useSDK from '~/core/hooks/useSDK'; -import MessageBubble from './MessageBubble'; -import useChannelPermission from '~/v4/chat/hooks/useChannelPermission'; -import Flag from '~/v4/icons/Flag'; -import { MessageReaction } from './MessageReaction'; -import { MessageReactionPreview } from '~/v4/chat/components/MessageReactionPreview'; -import Sheet from 'react-modal-sheet'; -import { ReactionList } from '~/v4/social/components'; - -interface MessageItemProps { - pageId?: string; - componentId?: string; - message: Amity.Message<'text'>; - userDisplayName?: string; - avatarUrl?: string; - containerRef: React.RefObject; - action?: AmityMessageActionType; -} - -const LiveChatMessageContent = ({ - pageId = '*', - componentId = '*', - message, - avatarUrl, - userDisplayName, - containerRef, - action, -}: MessageItemProps) => { - const { formatMessage } = useIntl(); - const sdk = useSDK(); - const isOwner = message.creatorId === sdk.currentUserId; - const { isModerator } = useChannelPermission(message.channelId); - const [openReactionPanel, setOpenReactionPanel] = useState(undefined); - - return ( - <> - -
- {message.isDeleted ? ( -
- -
- - {formatMessage({ - id: 'livechat.deleted.message', - })} - -
-
- ) : ( -
- -
- setOpenReactionPanel(message)} - /> -
- {action && ( - 0} - /> - )} - - {message.flagCount > 0 && } -
- -
-
- )} -
-
- - {openReactionPanel && ( - setOpenReactionPanel(undefined)} - className={styles.reactionListSheet} - > - - - - - - - - - )} - - ); -}; - -export default LiveChatMessageContent; diff --git a/src/v4/chat/components/LiveChatMessageContent/styles.module.css b/src/v4/chat/components/LiveChatMessageContent/styles.module.css deleted file mode 100644 index 0cf5143fd..000000000 --- a/src/v4/chat/components/LiveChatMessageContent/styles.module.css +++ /dev/null @@ -1,86 +0,0 @@ -.messageItemContainer { - padding: var(--asc-spacing-s1) var(--asc-spacing-m1); - display: flex; - gap: var(--asc-spacing-s1); -} - -.messageItemContainerInner { - position: relative; -} - -.messageItemContainerInner[data-reactions='true'] { - margin-bottom: 1.313rem; -} - -.messageBubbleWrap { - display: flex; - align-items: flex-end; - gap: var(--asc-spacing-xxs3); -} - -.messageReaction { - position: absolute; - bottom: -1.313rem; -} - -.messageDeletedBubble { - display: flex; - align-items: center; - justify-content: center; - padding: var(--asc-spacing-xxs2) var(--asc-spacing-s1); - background-color: var(--asc-color-base-shade4); - gap: var(--asc-spacing-xxs2); - border-radius: var(--asc-border-radius-lg); - color: var(--asc-color-base-inverse); -} - -.messageOptionsWrap { - display: flex; - align-items: flex-start; - padding-bottom: var(--asc-spacing-xxs2); -} - -.binIcon { - height: 1rem; - width: 1rem; - fill: var(--asc-color-base-inverse); -} - -.optionIcon { - width: auto; - height: 1.25rem; -} - -.flagIcon { - height: 1rem; -} - -.timestamp { - font-family: var(--asc-text-global-font-family); - color: var(--asc-color-base-shade2); - margin-bottom: var(--asc-spacing-s1); - - /* This value is not available in global css */ - font-size: 0.5rem; - line-height: 0.75rem; -} - -.reactionListSheet { - z-index: 1001 !important; - max-height: 85%; - top: 15% !important; - - @media (width >= 768px) { - width: 375px !important; - } -} - -.reactionListContainer { - height: 100% !important; - background-color: var(--asc-color-base-background) !important; -} - -.reactionListBackdrop { - background-color: var(--asc-color-black) !important; - opacity: 0.5 !important; -} diff --git a/src/v4/chat/components/LiveChatNotification/index.tsx b/src/v4/chat/components/LiveChatNotification/index.tsx deleted file mode 100644 index 5b33fde89..000000000 --- a/src/v4/chat/components/LiveChatNotification/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { ReactNode } from 'react'; -import clsx from 'clsx'; -import styles from './styles.module.css'; -import { Typography } from '~/v4/core/components/index'; -import { useLiveChatNotificationData } from '~/v4/chat/providers/LiveChatNotificationProvider'; - -interface NotificationProps { - className?: string; - content: ReactNode; - icon?: ReactNode; -} - -const LiveChatNotification = ({ className, content, icon }: NotificationProps) => ( -
- {icon} - {content} -
-); - -export const LiveChatNotificationsContainer = () => { - const notifications = useLiveChatNotificationData(); - - return ( -
- {notifications.map((notificationData) => { - return ; - })} -
- ); -}; - -export default LiveChatNotification; diff --git a/src/v4/chat/components/LiveChatNotification/styles.module.css b/src/v4/chat/components/LiveChatNotification/styles.module.css deleted file mode 100644 index 336baa6ab..000000000 --- a/src/v4/chat/components/LiveChatNotification/styles.module.css +++ /dev/null @@ -1,35 +0,0 @@ -/* styles.module.css */ - -.notifications { - position: relative; - bottom: var(--asc-spacing-m1); - display: flex; - flex-direction: column; - align-items: center; - z-index: 99999; - pointer-events: none; -} - -.notificationContainer { - width: calc(100% - var(--asc-spacing-m1) * 4); - padding: 1.125rem var(--asc-spacing-m1); - display: flex; - align-items: center; - color: var(--asc-color-base-inverse); - border-radius: var(--asc-border-radius-md); - animation-duration: 0.3s; - animation-name: appear; - animation-fill-mode: forwards; - pointer-events: auto; - background-color: var(--asc-color-base-shade4); -} - -@keyframes appear { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} diff --git a/src/v4/chat/components/LivechatLoadingIndicator/index.tsx b/src/v4/chat/components/LivechatLoadingIndicator/index.tsx deleted file mode 100644 index c21b59a6a..000000000 --- a/src/v4/chat/components/LivechatLoadingIndicator/index.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import React from 'react'; -import styled, { keyframes } from 'styled-components'; - -const rotateAnimation = keyframes` - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -`; - -const StyledSpinner = styled.svg` - animation: ${rotateAnimation} 2s linear infinite; -`; - -const LivechatLoadingIndicator = (props: React.SVGProps) => { - return ( - - - - - - - - - - - - - - - - - ); -}; - -export default LivechatLoadingIndicator; diff --git a/src/v4/chat/components/UserAvatar/index.tsx b/src/v4/chat/components/UserAvatar/index.tsx deleted file mode 100644 index becd694f4..000000000 --- a/src/v4/chat/components/UserAvatar/index.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { FileRepository } from '@amityco/ts-sdk'; -import UiKitAvatar from '~/core/components/Avatar'; -import { SIZE_ALIAS } from '~/core/hocs/withSize'; - -export interface UserAvatarProps { - size?: typeof SIZE_ALIAS[keyof typeof SIZE_ALIAS] | null; - avatarUrl?: string | null; - avatarFileId?: string | null; - avatarFile?: File | null; - defaultImage?: string | null; - avatarCustomUrl?: string | null; -} - -const UserAvatar = ({ - size = SIZE_ALIAS.REGULAR, - avatarUrl, - avatarFileId, - avatarFile, - defaultImage, - avatarCustomUrl, -}: UserAvatarProps) => { - const [avatar, setAvatar] = useState(null); - const [backgroundImage, setBackgroundImage] = useState(null); - - useEffect(() => { - setAvatar(null); - setBackgroundImage(null); - const getAvatarProps = async () => { - if (avatarUrl) { - setAvatar(avatarUrl); - return; - } - if (avatarCustomUrl) { - setAvatar(avatarCustomUrl); - return; - } - if (avatarFile) { - const toBase64 = (file: File) => - new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = () => resolve(reader.result as string); - reader.onerror = reject; - }); - - const fileBase64 = await toBase64(avatarFile); - setAvatar(fileBase64); - return; - } - if (avatarFileId) { - const avatarFileUrl = await FileRepository.fileUrlWithSize(avatarFileId, 'small'); - setAvatar(avatarFileUrl); - return; - } - - if (defaultImage) { - setBackgroundImage(defaultImage); - return; - } - }; - getAvatarProps(); - }, [avatarUrl, avatarFileId, avatarFile, avatarCustomUrl]); - - return ; -}; - -export default UserAvatar; diff --git a/src/v4/chat/components/index.ts b/src/v4/chat/components/index.ts deleted file mode 100644 index 9b139945e..000000000 --- a/src/v4/chat/components/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export { AmityLiveChatHeader } from './AmityLiveChatHeader'; -export { AmityLiveChatMessageReceiverView } from './AmityLiveChatMessageReceiverView'; -export { AmityLiveChatMessageSenderView } from './AmityLiveChatMessageSenderView'; -export { AmityLiveChatMessageList } from './AmityLiveChatMessageList'; -export { AmityLiveChatMessageComposeBar } from './AmityLiveChatMessageComposeBar'; - -export { MessageReactionPicker } from './MessageReactionPicker'; -export { MessageQuickReaction } from './MessageQuickReaction'; -export { MessageReactionPreview } from './MessageReactionPreview'; - -import type { AmityMessageActionType } from './LiveChatMessageContent/MessageAction'; -export type { AmityMessageActionType }; diff --git a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatCustomState.tsx b/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatCustomState.tsx deleted file mode 100644 index e5d77c1ce..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatCustomState.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import styles from './styles.module.css'; - -const ChatCustomState = ({ children }: { children?: React.ReactNode }) => { - return
{children}
; -}; - -export default ChatCustomState; diff --git a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatLoadingState.tsx b/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatLoadingState.tsx deleted file mode 100644 index 30ea7d9d8..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatLoadingState.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { Typography } from '~/v4/core/components'; -import Spinner from '~/social/components/Spinner'; -import HomeIndicator from '~/v4/chat/components/HomeIndicator'; -import styles from './styles.module.css'; - -const ChatLoadingState = ({ children }: { children?: React.ReactNode }) => { - return ( - <> -
{children}
-
-
-
-
- - - - - - -
-
-
- -
- - ); -}; - -export default ChatLoadingState; diff --git a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatReadyState.tsx b/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatReadyState.tsx deleted file mode 100644 index 58c46e592..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatReadyState.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { AmityLiveChatMessageList } from '~/v4/chat/components/AmityLiveChatMessageList'; -import AmityLiveChatMessageComposeBar from '~/v4/chat/components/AmityLiveChatMessageComposeBar'; -import ReplyMessagePlaceholder from '~/v4/chat/pages/AmityLiveChatPage/ChatContainer/ReplyMessagePlaceholder'; -import useConnectionStates from '~/social/hooks/useConnectionStates'; -import ChatLoadingState from '~/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatLoadingState'; -import ChatCustomState from '~/v4/chat/pages/AmityLiveChatPage/ChatContainer/ChatCustomState'; -import styles from './styles.module.css'; -import { LiveChatNotificationsContainer } from '~/v4/chat/components/LiveChatNotification'; -import MutedIcon from '~/v4/icons/Muted'; -import { Typography } from '~/v4/core/components/Typography'; -import mentionStyles from '~/v4/core/components/InputText/styles.module.css'; -import { FormattedMessage } from 'react-intl'; -import CommentAltExclamation from '~/v4/icons/CommentAltExclamation'; -import useSearchChannelUser from '~/v4/chat/hooks/collections/useSearchChannelUser'; -import useSDK from '~/core/hooks/useSDK'; -import useChannelPermission from '~/v4/chat/hooks/useChannelPermission'; - -const ChatReadyState = ({ pageId = '*', channel }: { pageId?: string; channel: Amity.Channel }) => { - const isOnline = useConnectionStates(); - - const { isModerator } = useChannelPermission(channel.channelId); - - const currentUserId = useSDK().currentUserId; - const { channelMembers } = useSearchChannelUser(channel.channelId, ['member', 'banned', 'muted']); - const currentUserMembership = channelMembers.find((member) => member.userId === currentUserId); - - const [replyMessage, setReplyMessage] = useState | undefined>(undefined); - const [mentionMessage, setMentionMessage] = useState | undefined>( - undefined, - ); - - const [offsetBottom, setOffsetBottom] = useState(0); - const suggestionRef = useRef(null); - const composeBarRef = useRef(null); - - useEffect(() => { - if (composeBarRef.current?.clientHeight && composeBarRef.current?.clientHeight > 0) { - setOffsetBottom(composeBarRef.current.clientHeight - 30); - } - }, [composeBarRef.current?.clientHeight]); - - if (!isOnline) return ; - - if (currentUserMembership?.isBanned) - return ( - -
- - - - - - - -
-
- ); - - return ( - <> - - - {isOnline && ( - <> -
- {!isModerator && channel.isMuted ? ( -
- - - - -
- ) : currentUserMembership?.isMuted ? ( -
- - - - -
- ) : null} - - {replyMessage && ( - setReplyMessage(undefined)} - /> - )} - -
- -
- -
- setReplyMessage(undefined), - clearMention: () => setMentionMessage(undefined), - }} - /> -
- - )} - - ); -}; - -export default ChatReadyState; diff --git a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ReplyMessagePlaceholder.tsx b/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ReplyMessagePlaceholder.tsx deleted file mode 100644 index af51ca5b6..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/ReplyMessagePlaceholder.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import useUser from '~/core/hooks/useUser'; -import styles from './styles.module.css'; -import { FormattedMessage } from 'react-intl'; -import CloseIcon from '~/v4/icons/Close'; -import { Avatar } from '~/v4/core/components'; -import User from '~/v4/icons/User'; -import { AVATAR_SIZE } from '~/v4/core/components/Avatar/Avatar'; - -interface ReplyMessagePlaceholderProps { - replyMessage: Amity.Message<'text'>; - onDismiss: () => void; -} - -const ReplyMessagePlaceholder = ({ replyMessage, onDismiss }: ReplyMessagePlaceholderProps) => { - const profile = useUser(replyMessage.creatorId); - - if (!profile) return null; - - return ( -
-
- } /> -
-
-
- -
-
{replyMessage.data?.text}
-
-
- -
-
- ); -}; - -export default ReplyMessagePlaceholder; diff --git a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/index.tsx b/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/index.tsx deleted file mode 100644 index aa1b8c735..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/index.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import ChatLoadingState from './ChatLoadingState'; -import ChatReadyState from './ChatReadyState'; - -const ChatContainer = ({ - pageId = '*', - channel, -}: { - pageId?: string; - channel: Amity.Channel | null; -}) => { - if (!channel) return ; - return ; -}; - -export default ChatContainer; diff --git a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/styles.module.css b/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/styles.module.css deleted file mode 100644 index ba002e639..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/ChatContainer/styles.module.css +++ /dev/null @@ -1,136 +0,0 @@ -.composeBarContainer { - min-height: 3.5rem; - z-index: 99; - background-color: inherit; -} - -.composeBar { - display: flex; - align-items: center; - gap: var(--asc-spacing-s2); - padding: var(--asc-spacing-s1) var(--asc-spacing-s2); - background-color: inherit; - border-top: 1px solid var(--asc-color-base-shade2); -} - -.textInputContainer { - display: flex; - flex-grow: 1; - - & > div { - width: 100%; - border-radius: var(--asc-border-radius-xxl); - border: 1px solid var(--asc-color-base-background); - background: var(--asc-color-secondary-shade4); - - textarea { - padding: 0.563rem 1rem; - background-color: transparent; - } - } -} - -.composeBarLoading { - width: 100%; - height: var(--asc-spacing-l1); - padding: var(--asc-spacing-s1) var(--asc-spacing-s2); - border-radius: var(--asc-border-radius-sm); - border: var(--asc-border-radius-none); - background-color: var( - --live-chat-asc-color-secondary-default, - var(--asc-color-secondary-default) - ); - color: var(--asc-color-base-inverse); - display: flex; - align-items: center; - - span { - padding-left: var(--asc-spacing-s1); - font-weight: var(--asc-text-font-weight-light); - } -} - -.replyPlaceholderContainer { - display: flex; - font-family: var(--asc-text-global-font-family); - background-color: var(--asc-color-base-shade4); - color: var(--asc-color-base-inverse); - max-width: 100%; - padding: var(--asc-spacing-s2); - padding-left: var(--asc-spacing-m1); - gap: var(--asc-spacing-s2); - justify-content: space-between; - align-items: center; - - .replyAvatar { - flex: 0 0 auto; - } - - .replyProfile { - display: flex; - flex-direction: column; - color: var(--asc-color-base-inverse); - font-size: var(--asc-text-font-size-sm); - line-height: var(--asc-line-height-sm); - flex: 1; - overflow: hidden; - gap: 0.125rem; - - .replyProfileName { - font-weight: var(--asc-text-font-weight-bold); - } - - .replyProfileMessage { - font-weight: var(--asc-text-font-weight-light); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - } - - .replyDismiss { - flex: 0 0 auto; - cursor: pointer; - } -} - -.notificationPosition { - position: relative; - height: 0; -} - -.messageListPlaceholder { - height: 100%; -} - -.mutedChannelContainer { - display: flex; - font-family: var(--asc-text-global-font-family); - background-color: var(--asc-color-base-shade4); - color: var(--asc-color-base-shade1); - max-width: 100%; - padding: var(--asc-spacing-s2); - padding-left: var(--asc-spacing-m1); - gap: var(--asc-spacing-s2); - align-items: center; -} - -.mutedIcon { - color: var(--asc-color-base-shade3); -} - -.commentAltIcon { - color: var(--asc-color-base-shade2); -} - -.banStatePanel { - display: flex; - height: 100%; - flex-direction: column; - justify-content: center; - align-items: center; - text-align: center; - gap: var(--asc-spacing-s2); - padding: var(--asc-spacing-m1); - color: var(--asc-color-base-shade2); -} diff --git a/src/v4/chat/pages/AmityLiveChatPage/index.tsx b/src/v4/chat/pages/AmityLiveChatPage/index.tsx deleted file mode 100644 index 6aac7f660..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/index.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React, { useRef } from 'react'; -import useChannel from '~/v4/chat/hooks/useChannel'; -import AmityLiveChatHeader from '~/v4/chat/components/AmityLiveChatHeader'; -import ChatContainer from './ChatContainer'; -import styles from './styles.module.css'; -import { LiveChatNotificationProvider } from '~/v4/chat/providers/LiveChatNotificationProvider'; -import { useAmityPage } from '~/v4/core/hooks/uikit'; - -interface AmityLiveChatPageProps { - channelId: Amity.Channel['channelId']; -} - -export const AmityLiveChatPage = ({ channelId }: AmityLiveChatPageProps) => { - const channel = useChannel(channelId); - const pageId = 'live_chat'; - const { themeStyles } = useAmityPage({ pageId }); - const ref = useRef(null); - - return ( - -
-
- -
- -
-
- ); -}; - -export default AmityLiveChatPage; diff --git a/src/v4/chat/pages/AmityLiveChatPage/livechatPage.stories.tsx b/src/v4/chat/pages/AmityLiveChatPage/livechatPage.stories.tsx deleted file mode 100644 index 7c63683bf..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/livechatPage.stories.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import React, { useRef, useState } from 'react'; -import useChannelsCollection from '~/chat/hooks/collections/useChannelsCollection'; -import ChatItem from '~/chat/components/ChatItem'; -import InfiniteScroll from 'react-infinite-scroll-component'; -import { AmityLiveChatPage } from '.'; -import styles from '~/v4/chat/pages/AmityLiveChatPage/styles.module.css'; -import Sheet from 'react-modal-sheet'; - -export default { - title: 'V4/AmityLiveChatPage', -}; - -const LiveChatList = () => { - const [selectedChannel, setSelectedChannel] = useState(null); - const [open, setOpen] = useState(false); - const { channels, hasMore, loadMore, isLoading } = useChannelsCollection({ - membership: 'all', - sortBy: 'lastActivity', - types: ['live'], - }); - - const onSelectedChannel = (channelId: string) => { - setOpen(true); - setSelectedChannel(channelId); - }; - - const containerRef = useRef(null); - - return ( -
- {containerRef.current ? ( - Loading... : null} - inverse={true} - dataLength={channels.length} - style={{ display: 'flex', flexDirection: 'column-reverse' }} - height={containerRef.current.clientHeight} - > - {channels.map((channel) => ( - { - onSelectedChannel(data.channelId); - }} - /> - ))} - - ) : null} - - setOpen(false)} className={styles.messageListSheet}> - - - - - - - -
- ); -}; - -export const LiveChatStory = { - render: () => , - name: 'AmityLiveChatPage', -}; diff --git a/src/v4/chat/pages/AmityLiveChatPage/styles.module.css b/src/v4/chat/pages/AmityLiveChatPage/styles.module.css deleted file mode 100644 index 0bb535a12..000000000 --- a/src/v4/chat/pages/AmityLiveChatPage/styles.module.css +++ /dev/null @@ -1,24 +0,0 @@ -.messageListSheet { - z-index: 1000 !important; - - @media (width >= 768px) { - width: 375px !important; - } - - .messageListSheetContainer { - height: 100% !important; - background-color: var(--asc-color-base-background) !important; - } -} - -.messageListHeaderWrap { - box-shadow: var(--asc-box-shadow-01); -} - -.amtiyLivechatPage { - display: flex; - flex-direction: column; - background-color: var(--asc-color-base-background); - height: 100%; - overflow-y: hidden; -} diff --git a/src/v4/social/internal-components/Badege/Badge.module.css b/src/v4/social/internal-components/Badege/Badge.module.css deleted file mode 100644 index fdf079b3e..000000000 --- a/src/v4/social/internal-components/Badege/Badge.module.css +++ /dev/null @@ -1,10 +0,0 @@ -.badge { - display: inline-flex; - justify-content: center; - align-items: center; - gap: 3px; - background-color: var(--asc-color-primary-shade3); - color: var(--asc-color-primary-main); - border-radius: 20px; - padding: 0px 6px 0px 4px; -} \ No newline at end of file diff --git a/src/v4/social/internal-components/Badege/ui.stories.tsx b/src/v4/social/internal-components/Badege/ui.stories.tsx deleted file mode 100644 index 4c347bc5c..000000000 --- a/src/v4/social/internal-components/Badege/ui.stories.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { Badge } from './Badge'; -import { BadgeProps } from './types'; -import { ModeratorBadgeIcon } from '~/icons'; - -export default { - title: 'V4/Components/Badge', - component: Badge, - argTypes: { - icon: { - control: { - type: 'select', - options: ['crown', 'star', 'heart'], // Adjust the options based on your available icons - }, - }, - communityRole: { - control: 'text', - }, - }, -} as Meta; - -const Template: Story = (args) => ; - -export const Default = Template.bind({}); -Default.args = { - icon: , - communityRole: 'Moderator', -};