From 51d38ffd6045f56826747d6ad2948c955c7cdb0c Mon Sep 17 00:00:00 2001 From: "ildar.timerbaev" Date: Thu, 21 Mar 2024 23:34:16 +0600 Subject: [PATCH 1/4] Chats: added message forwarding between contacts and channels --- src/common/constants/contributors.json | 10 +- .../features/chats/components/chat-input.tsx | 4 +- .../chats/components/chat-message-item.tsx | 23 +++- .../chats-direct-messages/index.tsx | 77 ++++++++--- .../components/forward-message-dialog.tsx | 128 ++++++++++++++++++ src/common/i18n/locales/en-US.json | 4 + 6 files changed, 217 insertions(+), 29 deletions(-) create mode 100644 src/common/features/chats/components/forward-message-dialog.tsx diff --git a/src/common/constants/contributors.json b/src/common/constants/contributors.json index d5a2730187b..d58a6fc4992 100644 --- a/src/common/constants/contributors.json +++ b/src/common/constants/contributors.json @@ -495,20 +495,20 @@ "name": "gamingumar", "contributes": ["Developer (Mobile)"] }, - { + { "name": "asgharali", "contributes": ["Guest Curator"] }, - { + { "name": "aliakbar2", "contributes": ["Guest Curator"] }, - { + { "name": "untilwelearn", "contributes": ["Guest Curator"] }, - { + { "name": "sirenahippie", "contributes": ["Guest Curator"] - } + } ] diff --git a/src/common/features/chats/components/chat-input.tsx b/src/common/features/chats/components/chat-input.tsx index 5cb53455557..b349e9e3ac7 100644 --- a/src/common/features/chats/components/chat-input.tsx +++ b/src/common/features/chats/components/chat-input.tsx @@ -95,7 +95,7 @@ export default function ChatInput({ currentChannel, currentContact }: Props) { if (isDisabled || isSendMessageLoading || isFilesUploading || !nextMessage) { return; } - await sendMessage(nextMessage); + await sendMessage({ message: nextMessage }); setFiles([]); setUploadedFileLinks([]); // Re-focus to input because when DOM changes and input position changes then @@ -124,7 +124,7 @@ export default function ChatInput({ currentChannel, currentContact }: Props) { gifImagesStyle={GifImagesStyle} shGif={true} changeState={(gifState) => setShowGifPicker(gifState!)} - fallback={(e) => sendMessage(e)} + fallback={(e) => sendMessage({ message: e })} /> )} {(files.length > 0 || uploadedFileLinks.length > 0) && !showGifPicker && ( diff --git a/src/common/features/chats/components/chat-message-item.tsx b/src/common/features/chats/components/chat-message-item.tsx index fdcdf9fe15f..ccb00515a52 100644 --- a/src/common/features/chats/components/chat-message-item.tsx +++ b/src/common/features/chats/components/chat-message-item.tsx @@ -23,8 +23,9 @@ import { import { format } from "date-fns"; import { useInViewport } from "react-in-viewport"; import "./_chat-message-item.scss"; -import { makePath } from "../../../components/profile-link"; +import ProfileLink, { makePath } from "../../../components/profile-link"; import { Link } from "react-router-dom"; +import { history } from "../../../store"; interface Props { type: "sender" | "receiver"; @@ -52,7 +53,7 @@ export function ChatMessageItem({ className = "" }: Props) { const ref = useRef(null); - const { global, activeUser } = useMappedStore(); + const { global, activeUser, addAccount } = useMappedStore(); const { publicKey } = useKeysQuery(); const [holdStarted, setHoldStarted] = useState(false); @@ -74,6 +75,7 @@ export function ChatMessageItem({ const { inViewport } = useInViewport(ref); const { data: nostrUserProfiles } = useNostrGetUserProfileQuery(message.creator); + const { data: nostrForwardedUserProfiles } = useNostrGetUserProfileQuery(message.forwardedFrom); const profile = useMemo( () => nostrUserProfiles?.find((p) => p.creator === message.creator), @@ -171,6 +173,23 @@ export function ChatMessageItem({ {profile!!.name} )} + {message.forwardedFrom && ( +
+ {_t("chat.forwarded-from")} + {nostrForwardedUserProfiles?.[0]?.name && ( + + + ({nostrForwardedUserProfiles[0].name}) + + + )} +
+ )}
(); + const { publicKey } = useKeysQuery(); const directMessagesQuery = useDirectMessagesQuery(props.currentContact); + // Message where users interacted with context menu + const [currentInteractingMessageId, setCurrentInteractingMessageId] = useState(); + const groupedDirectMessages = useMemo(() => groupMessages(directMessages), [directMessages]); useDebounce( @@ -44,6 +54,8 @@ export default function ChatsDirectMessages(props: Props) { } }, [directMessages]); + console.log(groupedDirectMessages); + return ( <>
@@ -53,32 +65,57 @@ export default function ChatsDirectMessages(props: Props) { {diff > 0 && } {messages.map((message, j) => ( - - setTimeout( - () => - groupedDirectMessages?.length - 1 === i && messages.length - 1 === j - ? document - .querySelector(`[data-message-id="${message.id}"]`) - ?.scrollIntoView({ block: "nearest" }) - : {}, - 300 - ) - } - onInViewport={(inViewport) => - i === 0 && j === 0 && setNeedFetchNextPage(inViewport) + closeOnClickOutside={true} + show={currentInteractingMessageId === message.id} + setShow={(v) => + setCurrentInteractingMessageId(v ? currentInteractingMessageId : undefined) } - /> + > + setCurrentInteractingMessageId(message.id)} + onAppear={() => + setTimeout( + () => + groupedDirectMessages?.length - 1 === i && messages.length - 1 === j + ? document + .querySelector(`[data-message-id="${message.id}"]`) + ?.scrollIntoView({ block: "nearest" }) + : {}, + 300 + ) + } + onInViewport={(inViewport) => + i === 0 && j === 0 && setNeedFetchNextPage(inViewport) + } + /> + + } + label={_t("chat.forward")} + onClick={() => setForwardingMessage(message)} + /> + + ))} ); })} + setForwardingMessage(undefined)} + />
); diff --git a/src/common/features/chats/components/forward-message-dialog.tsx b/src/common/features/chats/components/forward-message-dialog.tsx new file mode 100644 index 00000000000..d25bb7d2f8d --- /dev/null +++ b/src/common/features/chats/components/forward-message-dialog.tsx @@ -0,0 +1,128 @@ +import { Modal, ModalBody, ModalHeader } from "@ui/modal"; +import { List } from "@ui/list"; +import { ChatSidebarDirectContact } from "./chats-sidebar/chat-sidebar-direct-contact"; +import { ChatSidebarChannel } from "./chats-sidebar/chat-sidebar-channel"; +import React, { useEffect, useState } from "react"; +import { + Channel, + DirectContact, + Message, + useChannelsQuery, + useDirectContactsQuery, + useSendMessage +} from "@ecency/ns-query"; +import { _t } from "../../../i18n"; +import { Spinner } from "@ui/spinner"; +import { error, success } from "../../../components/feedback"; + +interface Props { + show: boolean; + setShow: (v: boolean) => void; + message: Message; +} + +export function ForwardMessageDialog({ show, setShow, message }: Props) { + const { data: contacts } = useDirectContactsQuery(); + const { data: channels } = useChannelsQuery(); + + const [selectedChannel, setSelectedChannel] = useState(); + const [selectedContact, setSelectedContact] = useState(); + + const { + mutateAsync: forwardMessage, + isLoading: isMessageForwarding, + isSuccess: isMessageForwardSuccess, + isError: isMessageForwardError + } = useSendMessage(selectedChannel, selectedContact); + + useEffect(() => { + if (isMessageForwardError) { + error(_t("g.error")); + setShow(false); + } + }, [isMessageForwardError]); + + useEffect(() => { + if (isMessageForwardSuccess) { + success(_t("g.success")); + setShow(false); + } + }, [isMessageForwardSuccess]); + + useEffect(() => { + if (selectedContact) { + setTimeout( + () => forwardMessage({ message: message.content, forwardedFrom: message.creator }), + 1 + ); + } + }, [selectedContact]); + + useEffect(() => { + if (selectedChannel) { + setTimeout( + () => forwardMessage({ message: message.content, forwardedFrom: message.creator }), + 1 + ); + } + }, [selectedChannel]); + + return ( + setShow(false)}> + +
{_t("chat.message-forwarding")}
+
+ +
+
{_t("chat.select-contact-or-channel")}
+ {(contacts?.length ?? 0) > 0 && ( +
+
+ {_t("chat.direct-messages")} +
+ + {contacts?.map((contact) => ( +
setSelectedContact(contact)} + > + +
+ ))} +
+
+ )} + {channels.length > 0 && ( +
+
+ {_t("chat.communities")} +
+ + {channels.map((channel) => ( +
setSelectedChannel(selectedChannel)} + > + +
+ ))} +
+
+ )} + + {isMessageForwarding && ( +
+ +
+ )} +
+
+
+ ); +} diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 155a9eacbf7..2d554ad5171 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -1933,6 +1933,10 @@ "fetch-error": "While you were away, network change detected. Reload page now to fetch new data", "pin": "Pin", "unpin": "Unpin", + "select-contact-or-channel": "Select contact or channel", + "message-forwarding": "Message forwarding", + "forward": "Forward message", + "forwarded-from": "Forwarded message", "welcome": { "title": "Welcome to Chats", "description": "Create or import an account start using Chats", From 6e7e5715d967b7f5feb1bbe2914bee21c6e9db74 Mon Sep 17 00:00:00 2001 From: "ildar.timerbaev" Date: Thu, 21 Mar 2024 23:36:05 +0600 Subject: [PATCH 2/4] Increase ns-query version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61095decacb..19b81a86a0e 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "start:prod": "NODE_ENV=production node build/server.js" }, "dependencies": { - "@ecency/ns-query": "^1.1.7", + "@ecency/ns-query": "^1.1.8", "@ecency/render-helper": "^2.2.30", "@ecency/render-helper-amp": "^1.1.0", "@emoji-mart/data": "^1.1.2", From 802c3cd0f957146f36baa8b0f1e69e08fe64d815 Mon Sep 17 00:00:00 2001 From: "ildar.timerbaev" Date: Thu, 21 Mar 2024 23:37:48 +0600 Subject: [PATCH 3/4] Chats: updated message forwarding --- .../chats/components/chat-channel-messages.tsx | 15 +++++++++++++++ .../components/chats-direct-messages/index.tsx | 2 -- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/common/features/chats/components/chat-channel-messages.tsx b/src/common/features/chats/components/chat-channel-messages.tsx index 5efee6e2fb8..a76d2732baf 100644 --- a/src/common/features/chats/components/chat-channel-messages.tsx +++ b/src/common/features/chats/components/chat-channel-messages.tsx @@ -8,6 +8,7 @@ import { Spinner } from "@ui/spinner"; import { Channel, checkContiguousMessage, + Message, PublicMessage, useHideMessageInChannel, useJoinedCommunityTeamQuery, @@ -21,6 +22,8 @@ import { differenceInCalendarDays } from "date-fns"; import useDebounce from "react-use/lib/useDebounce"; import { useCommunityCache } from "../../../core"; import { ROLES } from "../../../store/communities"; +import { ForwardMessageDialog } from "./forward-message-dialog"; +import { UilMessage } from "@iconscout/react-unicons"; interface Props { publicMessages: PublicMessage[]; @@ -36,6 +39,7 @@ export function ChatsChannelMessages({ publicMessages, currentChannel, isPage }: // Message where users interacted with context menu const [currentInteractingMessageId, setCurrentInteractingMessageId] = useState(); const [needFetchNextPage, setNeedFetchNextPage] = useState(false); + const [forwardingMessage, setForwardingMessage] = useState(); const { data: community } = useCommunityCache(currentChannel?.communityName); const { data: joinedCommunityTeamKeys, isSuccess: isJoinedCommunityTeamKeysFetched } = @@ -127,6 +131,11 @@ export function ChatsChannelMessages({ publicMessages, currentChannel, isPage }: className="top-[70%]" align={message.creator === publicKey ? "right" : "left"} > + } + label={_t("chat.forward")} + onClick={() => setForwardingMessage(message)} + /> : hideSvg} label={_t("chat.hide-message")} @@ -147,6 +156,12 @@ export function ChatsChannelMessages({ publicMessages, currentChannel, isPage }: ))} ))} + + setForwardingMessage(undefined)} + />
); diff --git a/src/common/features/chats/components/chats-direct-messages/index.tsx b/src/common/features/chats/components/chats-direct-messages/index.tsx index cd42658e3c2..829035dbc43 100644 --- a/src/common/features/chats/components/chats-direct-messages/index.tsx +++ b/src/common/features/chats/components/chats-direct-messages/index.tsx @@ -54,8 +54,6 @@ export default function ChatsDirectMessages(props: Props) { } }, [directMessages]); - console.log(groupedDirectMessages); - return ( <>
From 6b62f397c1616f47c05c44cbc819ebcf79e6f346 Mon Sep 17 00:00:00 2001 From: feruzm Date: Fri, 22 Mar 2024 06:54:25 +0530 Subject: [PATCH 4/4] update lockfile --- package.json | 2 +- yarn.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 19b81a86a0e..87054f51705 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@ecency/ns-query": "^1.1.8", - "@ecency/render-helper": "^2.2.30", + "@ecency/render-helper": "^2.2.32", "@ecency/render-helper-amp": "^1.1.0", "@emoji-mart/data": "^1.1.2", "@emoji-mart/react": "^1.1.1", diff --git a/yarn.lock b/yarn.lock index 1b2485c877b..742c84d7524 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1381,10 +1381,10 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@ecency/ns-query@^1.1.7": - version "1.1.7" - resolved "https://registry.yarnpkg.com/@ecency/ns-query/-/ns-query-1.1.7.tgz#9c7c6dacf858badf7d0651031170fcab6f9d2cd1" - integrity sha512-sNPdFd+hvWGftulBrryeCtxCXJ4LzoidRaWSnYcrjxknd7W3dUZoc1OubGBI8lo45i/9k/tXweqiEjDlQZXO2g== +"@ecency/ns-query@^1.1.8": + version "1.1.8" + resolved "https://registry.yarnpkg.com/@ecency/ns-query/-/ns-query-1.1.8.tgz#5e224c5aa0116f143a0734fc3723916e10ca90f3" + integrity sha512-EEIEsPlKmHr3UyrOSk9/d8TbcrUeCdvqFYb+2TVdIJOQKYJA4YB2z4AWjUfIafbYpX/XAnP6aDH6ZqrPaKRSlA== dependencies: "@tanstack/react-query" "^4.29.7" axios "^0.21.2" @@ -1413,10 +1413,10 @@ xmldom "^0.5.0" xss "^1.0.8" -"@ecency/render-helper@^2.2.30": - version "2.2.30" - resolved "https://registry.yarnpkg.com/@ecency/render-helper/-/render-helper-2.2.30.tgz#33b890910dc90f77e84e7e6bfa6d14dd31371b9b" - integrity sha512-+JAPXFSHiquEMmerZe0t4k1gnHwouyba25v+cfIR3kL6KRToy1P5wcBhKyFr85uGx5VEBEFHDiK6Q8mtydNJfg== +"@ecency/render-helper@^2.2.32": + version "2.2.32" + resolved "https://registry.yarnpkg.com/@ecency/render-helper/-/render-helper-2.2.32.tgz#46cce2bb370dfa3dfab8c2140d8fde4829b5edb0" + integrity sha512-ac17/bPssVOEv8jbdib6z/ZOtzh+ANDK64KS/uK4XX/Ohn64YZvqtEWSv+j9IAOVHcUcGSyGVfYNMpa2JKoehw== dependencies: he "^1.2.0" lolight "^1.4.0"