From 6ec441f497d5f351378d34c4182a42f687c86f3d Mon Sep 17 00:00:00 2001 From: daria-github Date: Fri, 19 Jan 2024 09:35:55 -0800 Subject: [PATCH 1/5] convo list wip --- package-lock.json | 236 +++++++++++++----- package.json | 3 +- .../ConversationListController.tsx | 77 +++++- 3 files changed, 236 insertions(+), 80 deletions(-) diff --git a/package-lock.json b/package-lock.json index ee28d0a1..65a0390a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "date-fns": "^2.29.3", "dexie": "^3.2.4", "emojibase": "^6.1.0", + "ethers": "^6.10.0", "i18next": "^22.4.13", "i18next-browser-languagedetector": "^7.0.1", "i18next-http-backend": "^2.2.0", @@ -15016,6 +15017,53 @@ "node": ">=18" } }, + "node_modules/@xmtp/xmtp-js/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -20644,13 +20692,13 @@ } }, "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.10.0.tgz", + "integrity": "sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA==", "funding": [ { "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + "url": "https://github.com/sponsors/ethers-io/" }, { "type": "individual", @@ -20658,36 +20706,51 @@ } ], "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "@adraffy/ens-normalize": "1.10.0", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "node_modules/ethers/node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/ethjs-util": { @@ -44494,6 +44557,45 @@ "elliptic": "^6.5.4", "ethers": "^5.5.3", "long": "^5.2.0" + }, + "dependencies": { + "ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "requires": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + } } }, "@xtuc/ieee754": { @@ -48874,40 +48976,40 @@ } }, "ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.10.0.tgz", + "integrity": "sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA==", "requires": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "@adraffy/ens-normalize": "1.10.0", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.5.0" + }, + "dependencies": { + "@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} + } } }, "ethjs-util": { diff --git a/package.json b/package.json index 4d2f75d4..1f0ccfcb 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "cypress": "cypress run", "fmt:check": "prettier -c --ignore-path .gitignore --ignore-path .prettierignore .", "fmt:fix": "prettier -w --ignore-path .gitignore --ignore-path .prettierignore .", - "e2e:headless": "start-server-and-test dev http://localhost:5173 cypress", + "e2e:headless": "start-server-and-test dev http://localhost:5177 cypress", "test": "vitest run", "storybook": "storybook dev", "build-storybook": "build-storybook", @@ -47,6 +47,7 @@ "date-fns": "^2.29.3", "dexie": "^3.2.4", "emojibase": "^6.1.0", + "ethers": "^6.10.0", "i18next": "^22.4.13", "i18next-browser-languagedetector": "^7.0.1", "i18next-http-backend": "^2.2.0", diff --git a/src/controllers/ConversationListController.tsx b/src/controllers/ConversationListController.tsx index 30643741..d2646b84 100644 --- a/src/controllers/ConversationListController.tsx +++ b/src/controllers/ConversationListController.tsx @@ -1,5 +1,12 @@ -import { useEffect, useMemo } from "react"; -import { useConsent, useDb } from "@xmtp/react-sdk"; +import { useEffect, useMemo, useState } from "react"; +import { + getLastMessage, + getMessageByXmtpID, + useClient, + useConsent, + useDb, + useMessages, +} from "@xmtp/react-sdk"; import type { ActiveTab } from "../store/xmtp"; import { useXmtpStore } from "../store/xmtp"; import useListConversations from "../hooks/useListConversations"; @@ -7,6 +14,7 @@ import { ConversationList } from "../component-library/components/ConversationLi import { MessagePreviewCardController } from "./MessagePreviewCardController"; import useStreamAllMessages from "../hooks/useStreamAllMessages"; import { updateConversationIdentities } from "../helpers/conversation"; +import { useWalletClient } from "wagmi"; type ConversationListControllerProps = { setStartedFirstMessage: (startedFirstMessage: boolean) => void; @@ -25,8 +33,13 @@ export const ConversationListController = ({ const { isAllowed, isDenied } = useConsent(); const { db } = useDb(); + const [messages, setMessages] = useState([]); + const messagesDb = db.table("messages"); + useStreamAllMessages(); + const { client: walletAddress } = useClient(); const recipientInput = useXmtpStore((s) => s.recipientInput); + const activeTab = useXmtpStore((s) => s.activeTab); // when the conversations are loaded, update their identities @@ -57,25 +70,65 @@ export const ConversationListController = ({ return convos; }, [conversations, isAllowed, isDenied]); - const messagesToPass = useMemo( - () => - filteredConversations.filter((item: NodeWithConsent) => { - if (!isLoading && activeTab === "messages") { - return item.props.tab === "messages"; + let isFilterLoading = false; + + useEffect(() => { + // Fetch messages asynchronously + const fetchMessages = async () => + messagesDb + .where("senderAddress") + .equals(walletAddress?.address) + .toArray() + .then((messages) => { + // Process your messages here + setMessages(messages); + }) + .catch((error) => { + console.error("Error querying messages:", error); + }); + + void fetchMessages(); + }, [filteredConversations, messagesDb, walletAddress?.address]); + + const messagesToPass = useMemo(() => { + isFilterLoading = true; + const sortedConvos = filteredConversations.filter( + (item: NodeWithConsent) => { + console.log("MESSAGES", messages); + const hasSentMessages = messages.find( + (message) => message?.conversationTopic === item.props.convo.topic, + ); + if (activeTab === "messages") { + // Still want to keep blocked in blocked, even if those still have messages + return ( + item.props.tab === "messages" || + (item.props.tab === "requests" && hasSentMessages) + ); } - if (!isLoading && activeTab === "blocked") { + if (activeTab === "blocked") { return item.props.tab === "blocked"; } + // Find the sent messages in this conversation + return item.props.tab === "requests"; - }), - [filteredConversations, isLoading, activeTab], - ); + }, + ); + isFilterLoading = false; + return sortedConvos; + }, [ + filteredConversations, + isLoading, + activeTab, + walletAddress, + db, + isFilterLoading, + ]); return ( setStartedFirstMessage(true)} - isLoading={isLoading} + isLoading={isLoading || isFilterLoading} messages={messagesToPass} activeTab={activeTab} /> From cbc60c39246d34f4cf79dfd301b71f3690926f15 Mon Sep 17 00:00:00 2001 From: daria-github Date: Mon, 22 Jan 2024 11:23:04 -0800 Subject: [PATCH 2/5] updated consent flow --- .../components/AddressInput/AddressInput.tsx | 23 ++--- .../FullConversation/FullConversation.tsx | 7 +- src/controllers/AddressInputController.tsx | 10 +- .../ConversationListController.tsx | 98 +++++++++---------- src/store/xmtp.tsx | 5 + 5 files changed, 75 insertions(+), 68 deletions(-) diff --git a/src/component-library/components/AddressInput/AddressInput.tsx b/src/component-library/components/AddressInput/AddressInput.tsx index 954c146d..5e3076f9 100644 --- a/src/component-library/components/AddressInput/AddressInput.tsx +++ b/src/component-library/components/AddressInput/AddressInput.tsx @@ -1,7 +1,4 @@ -import { - ChevronLeftIcon, - InformationCircleIcon, -} from "@heroicons/react/outline"; +import { ChevronLeftIcon, XCircleIcon } from "@heroicons/react/outline"; import { useTranslation } from "react-i18next"; import { Avatar } from "../Avatar/Avatar"; import { classNames } from "../../../helpers"; @@ -41,10 +38,6 @@ interface AddressInputProps { * Upon submit, is something loading? */ isLoading?: boolean; - /** - * Is there a tooltip click event that needs to be handled? - */ - onTooltipClick?: () => void; /** * Input Value */ @@ -53,6 +46,10 @@ interface AddressInputProps { * Is there a left icon click event that needs to be handled? */ onLeftIconClick?: () => void; + /** + * Is there a right icon click event that needs to be handled? + */ + onRightIconClick?: () => void; } export const AddressInput = ({ @@ -61,9 +58,9 @@ export const AddressInput = ({ avatarUrlProps, onChange, isError, - onTooltipClick, value, onLeftIconClick, + onRightIconClick, }: AddressInputProps) => { const { t } = useTranslation(); const subtextColor = isError ? "text-red-600" : "text-gray-500"; @@ -127,8 +124,12 @@ export const AddressInput = ({ - {onTooltipClick && ( - + {onRightIconClick && ( + )} ); diff --git a/src/component-library/components/FullConversation/FullConversation.tsx b/src/component-library/components/FullConversation/FullConversation.tsx index 96effeb7..3876988a 100644 --- a/src/component-library/components/FullConversation/FullConversation.tsx +++ b/src/component-library/components/FullConversation/FullConversation.tsx @@ -35,7 +35,8 @@ const AcceptOrDeny = ({ address }: { address: string }) => { const { t } = useTranslation(); const { allow, deny } = useConsent(); const activeTab = useXmtpStore((s) => s.activeTab); - const setActiveTab = useXmtpStore((s) => s.setActiveTab); + const changedConsentCount = useXmtpStore((s) => s.changedConsentCount); + const setChangedConsentCount = useXmtpStore((s) => s.setChangedConsentCount); const [modalOpen, setModalOpen] = useState(true); @@ -51,8 +52,8 @@ const AcceptOrDeny = ({ address }: { address: string }) => { className="text-indigo-600 flex w-full justify-center border border-2 border-indigo-600 rounded-md p-2 hover:bg-indigo-600 hover:text-white" onClick={() => { void allow([address]); - setActiveTab("messages"); setModalOpen(false); + setChangedConsentCount(changedConsentCount + 1); }}> {t("consent.accept")} @@ -61,8 +62,8 @@ const AcceptOrDeny = ({ address }: { address: string }) => { className="text-red-600 flex w-full justify-center border border-2 border-red-600 rounded-md p-2 hover:bg-red-600 hover:text-white" onClick={() => { void deny([address]); - setActiveTab("blocked"); setModalOpen(false); + setChangedConsentCount(changedConsentCount + 1); }}> {t("consent.block")} diff --git a/src/controllers/AddressInputController.tsx b/src/controllers/AddressInputController.tsx index 133e2a1e..97e9c141 100644 --- a/src/controllers/AddressInputController.tsx +++ b/src/controllers/AddressInputController.tsx @@ -1,5 +1,5 @@ import { useEffect } from "react"; -import { useConversation } from "@xmtp/react-sdk"; +import { useConversation, useConsent } from "@xmtp/react-sdk"; import { AddressInput } from "../component-library/components/AddressInput/AddressInput"; import { getRecipientInputSubtext, shortAddress } from "../helpers"; import useWindowSize from "../hooks/useWindowSize"; @@ -20,7 +20,11 @@ export const AddressInputController = () => { const setRecipientInput = useXmtpStore((s) => s.setRecipientInput); const setStartedFirstMessage = useXmtpStore((s) => s.setStartedFirstMessage); const setConversationTopic = useXmtpStore((s) => s.setConversationTopic); + const changedConsentCount = useXmtpStore((s) => s.changedConsentCount); + const setChangedConsentCount = useXmtpStore((s) => s.setChangedConsentCount); + const { getCachedByPeerAddress, getCachedByTopic } = useConversation(); + const { deny } = useConsent(); // manage address input state useAddressInput(); @@ -100,6 +104,10 @@ export const AddressInputController = () => { setStartedFirstMessage(false); setConversationTopic(""); }} + onRightIconClick={() => { + void deny([recipientAddress]); + setChangedConsentCount(changedConsentCount + 1); + }} /> ); }; diff --git a/src/controllers/ConversationListController.tsx b/src/controllers/ConversationListController.tsx index d2646b84..52e78459 100644 --- a/src/controllers/ConversationListController.tsx +++ b/src/controllers/ConversationListController.tsx @@ -1,12 +1,6 @@ import { useEffect, useMemo, useState } from "react"; -import { - getLastMessage, - getMessageByXmtpID, - useClient, - useConsent, - useDb, - useMessages, -} from "@xmtp/react-sdk"; +import { useClient, useConsent, useDb } from "@xmtp/react-sdk"; +import type { CachedConversation, CachedMessage } from "@xmtp/react-sdk"; import type { ActiveTab } from "../store/xmtp"; import { useXmtpStore } from "../store/xmtp"; import useListConversations from "../hooks/useListConversations"; @@ -14,7 +8,6 @@ import { ConversationList } from "../component-library/components/ConversationLi import { MessagePreviewCardController } from "./MessagePreviewCardController"; import useStreamAllMessages from "../hooks/useStreamAllMessages"; import { updateConversationIdentities } from "../helpers/conversation"; -import { useWalletClient } from "wagmi"; type ConversationListControllerProps = { setStartedFirstMessage: (startedFirstMessage: boolean) => void; @@ -22,6 +15,7 @@ type ConversationListControllerProps = { type ConsentProps = { tab: ActiveTab; + convo: CachedConversation; }; type NodeWithConsent = React.ReactElement; @@ -33,12 +27,13 @@ export const ConversationListController = ({ const { isAllowed, isDenied } = useConsent(); const { db } = useDb(); - const [messages, setMessages] = useState([]); + const [messages, setMessages] = useState([]); const messagesDb = db.table("messages"); useStreamAllMessages(); const { client: walletAddress } = useClient(); const recipientInput = useXmtpStore((s) => s.recipientInput); + const changedConsentCount = useXmtpStore((s) => s.changedConsentCount); const activeTab = useXmtpStore((s) => s.activeTab); @@ -51,84 +46,81 @@ export const ConversationListController = ({ }; void runUpdate(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLoaded, activeTab]); - - const filteredConversations = useMemo(() => { - const convos = conversations.map((conversation) => ( - - )); - return convos; - }, [conversations, isAllowed, isDenied]); - - let isFilterLoading = false; + }, [isLoaded, activeTab, changedConsentCount]); useEffect(() => { - // Fetch messages asynchronously + // This may make more sense to come from the React SDK, but we're pulling from here for now const fetchMessages = async () => messagesDb .where("senderAddress") - .equals(walletAddress?.address) + .equals(walletAddress?.address as string) .toArray() - .then((messages) => { - // Process your messages here - setMessages(messages); + .then((dbMessages: CachedMessage[]) => { + setMessages(dbMessages); }) - .catch((error) => { + .catch((error: Error) => { console.error("Error querying messages:", error); }); void fetchMessages(); - }, [filteredConversations, messagesDb, walletAddress?.address]); + }, [conversations.length, messagesDb, walletAddress?.address]); const messagesToPass = useMemo(() => { - isFilterLoading = true; - const sortedConvos = filteredConversations.filter( + const conversationsWithTab = conversations.map( + (conversation: CachedConversation) => { + const tab = isAllowed(conversation.peerAddress) + ? "messages" + : isDenied(conversation.peerAddress) + ? "blocked" + : "requests"; + return ( + + ); + }, + ); + const sortedConvos = conversationsWithTab.filter( (item: NodeWithConsent) => { - console.log("MESSAGES", messages); const hasSentMessages = messages.find( (message) => message?.conversationTopic === item.props.convo.topic, ); + const isAddressBlocked = isDenied(item.props.convo.peerAddress); + const isAddressAllowed = isAllowed(item.props.convo.peerAddress); + if (activeTab === "messages") { // Still want to keep blocked in blocked, even if those still have messages - return ( - item.props.tab === "messages" || - (item.props.tab === "requests" && hasSentMessages) - ); + return isAddressAllowed || (!isAddressBlocked && hasSentMessages); } if (activeTab === "blocked") { - return item.props.tab === "blocked"; + return isAddressBlocked; } - // Find the sent messages in this conversation - - return item.props.tab === "requests"; + if (activeTab === "requests") { + return !hasSentMessages && !isAddressBlocked && !isAddressAllowed; + } + return null; }, ); - isFilterLoading = false; return sortedConvos; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ - filteredConversations, + conversations, + messages, isLoading, - activeTab, walletAddress, db, - isFilterLoading, + changedConsentCount, + isAllowed, + isDenied, ]); return ( setStartedFirstMessage(true)} - isLoading={isLoading || isFilterLoading} + isLoading={isLoading} messages={messagesToPass} activeTab={activeTab} /> diff --git a/src/store/xmtp.tsx b/src/store/xmtp.tsx index cf9f8bcb..608d84b2 100644 --- a/src/store/xmtp.tsx +++ b/src/store/xmtp.tsx @@ -39,6 +39,8 @@ interface XmtpState { setActiveMessage: (message?: CachedMessageWithId) => void; activeTab: ActiveTab; setActiveTab: (activeTab: ActiveTab) => void; + changedConsentCount: number; + setChangedConsentCount: (changedConsentCount: number) => void; } export const useXmtpStore = create((set) => ({ @@ -93,4 +95,7 @@ export const useXmtpStore = create((set) => ({ setActiveMessage: (activeMessage) => set(() => ({ activeMessage })), activeTab: "messages", setActiveTab: (activeTab) => set(() => ({ activeTab })), + changedConsentCount: 0, + setChangedConsentCount: (changedConsentCount) => + set(() => ({ changedConsentCount })), })); From 53b294a50ef379b86f4f8ae47751d899bb8e474b Mon Sep 17 00:00:00 2001 From: daria-github Date: Mon, 22 Jan 2024 11:24:54 -0800 Subject: [PATCH 3/5] revert package json changes --- package-lock.json | 100 ---------------------------------------------- package.json | 3 +- 2 files changed, 1 insertion(+), 102 deletions(-) diff --git a/package-lock.json b/package-lock.json index 65a0390a..ccca33b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,6 @@ "date-fns": "^2.29.3", "dexie": "^3.2.4", "emojibase": "^6.1.0", - "ethers": "^6.10.0", "i18next": "^22.4.13", "i18next-browser-languagedetector": "^7.0.1", "i18next-http-backend": "^2.2.0", @@ -20691,68 +20690,6 @@ "rlp": "^2.2.3" } }, - "node_modules/ethers": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.10.0.tgz", - "integrity": "sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/ethers-io/" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@types/node": "18.15.13", - "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", - "ws": "8.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" - }, - "node_modules/ethers/node_modules/aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" - }, - "node_modules/ethers/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/ethers/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/ethjs-util": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", @@ -48975,43 +48912,6 @@ } } }, - "ethers": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.10.0.tgz", - "integrity": "sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA==", - "requires": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@types/node": "18.15.13", - "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", - "ws": "8.5.0" - }, - "dependencies": { - "@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" - }, - "aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "requires": {} - } - } - }, "ethjs-util": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", diff --git a/package.json b/package.json index 1f0ccfcb..4d2f75d4 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "cypress": "cypress run", "fmt:check": "prettier -c --ignore-path .gitignore --ignore-path .prettierignore .", "fmt:fix": "prettier -w --ignore-path .gitignore --ignore-path .prettierignore .", - "e2e:headless": "start-server-and-test dev http://localhost:5177 cypress", + "e2e:headless": "start-server-and-test dev http://localhost:5173 cypress", "test": "vitest run", "storybook": "storybook dev", "build-storybook": "build-storybook", @@ -47,7 +47,6 @@ "date-fns": "^2.29.3", "dexie": "^3.2.4", "emojibase": "^6.1.0", - "ethers": "^6.10.0", "i18next": "^22.4.13", "i18next-browser-languagedetector": "^7.0.1", "i18next-http-backend": "^2.2.0", From a338e397c6949062ecc90d31224dca3c20587a65 Mon Sep 17 00:00:00 2001 From: daria-github Date: Tue, 23 Jan 2024 08:29:06 -0800 Subject: [PATCH 4/5] comment out code for sent messages --- .../ConversationListController.tsx | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/controllers/ConversationListController.tsx b/src/controllers/ConversationListController.tsx index 52e78459..6a709791 100644 --- a/src/controllers/ConversationListController.tsx +++ b/src/controllers/ConversationListController.tsx @@ -1,6 +1,6 @@ -import { useEffect, useMemo, useState } from "react"; -import { useClient, useConsent, useDb } from "@xmtp/react-sdk"; -import type { CachedConversation, CachedMessage } from "@xmtp/react-sdk"; +import { useEffect, useMemo } from "react"; +import { useClient, useConsent } from "@xmtp/react-sdk"; +import type { CachedConversation } from "@xmtp/react-sdk"; import type { ActiveTab } from "../store/xmtp"; import { useXmtpStore } from "../store/xmtp"; import useListConversations from "../hooks/useListConversations"; @@ -26,9 +26,9 @@ export const ConversationListController = ({ const { isLoaded, isLoading, conversations } = useListConversations(); const { isAllowed, isDenied } = useConsent(); - const { db } = useDb(); - const [messages, setMessages] = useState([]); - const messagesDb = db.table("messages"); + // const { db } = useDb(); + // const [messages, setMessages] = useState([]); + // const messagesDb = db.table("messages"); useStreamAllMessages(); const { client: walletAddress } = useClient(); @@ -48,22 +48,23 @@ export const ConversationListController = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [isLoaded, activeTab, changedConsentCount]); - useEffect(() => { - // This may make more sense to come from the React SDK, but we're pulling from here for now - const fetchMessages = async () => - messagesDb - .where("senderAddress") - .equals(walletAddress?.address as string) - .toArray() - .then((dbMessages: CachedMessage[]) => { - setMessages(dbMessages); - }) - .catch((error: Error) => { - console.error("Error querying messages:", error); - }); + // To-do: remove if not needed after consent goes out + // useEffect(() => { + // // This may make more sense to come from the React SDK, but we're pulling from here for now + // const fetchMessages = async () => + // messagesDb + // .where("senderAddress") + // .equals(walletAddress?.address as string) + // .toArray() + // .then((dbMessages: CachedMessage[]) => { + // setMessages(dbMessages); + // }) + // .catch((error: Error) => { + // console.error("Error querying messages:", error); + // }); - void fetchMessages(); - }, [conversations.length, messagesDb, walletAddress?.address]); + // void fetchMessages(); + // }, [conversations.length, messagesDb, walletAddress?.address]); const messagesToPass = useMemo(() => { const conversationsWithTab = conversations.map( @@ -84,21 +85,21 @@ export const ConversationListController = ({ ); const sortedConvos = conversationsWithTab.filter( (item: NodeWithConsent) => { - const hasSentMessages = messages.find( - (message) => message?.conversationTopic === item.props.convo.topic, - ); + // To-do: remove commented out code in this block if not needed after consent goes out + // const hasSentMessages = messages.find( + // (message) => message?.conversationTopic === item.props.convo.topic, + // ); const isAddressBlocked = isDenied(item.props.convo.peerAddress); const isAddressAllowed = isAllowed(item.props.convo.peerAddress); if (activeTab === "messages") { - // Still want to keep blocked in blocked, even if those still have messages - return isAddressAllowed || (!isAddressBlocked && hasSentMessages); + return isAddressAllowed; } if (activeTab === "blocked") { return isAddressBlocked; } if (activeTab === "requests") { - return !hasSentMessages && !isAddressBlocked && !isAddressAllowed; + return !isAddressBlocked && !isAddressAllowed; } return null; }, @@ -107,10 +108,10 @@ export const ConversationListController = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [ conversations, - messages, + // messages, isLoading, walletAddress, - db, + // db, changedConsentCount, isAllowed, isDenied, From 7f6d4245c066eca25796cbbefc23adb0f67ba784 Mon Sep 17 00:00:00 2001 From: daria-github Date: Tue, 23 Jan 2024 08:33:23 -0800 Subject: [PATCH 5/5] added db hook --- src/controllers/ConversationListController.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/ConversationListController.tsx b/src/controllers/ConversationListController.tsx index 6a709791..d5547fb2 100644 --- a/src/controllers/ConversationListController.tsx +++ b/src/controllers/ConversationListController.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo } from "react"; -import { useClient, useConsent } from "@xmtp/react-sdk"; +import { useClient, useConsent, useDb } from "@xmtp/react-sdk"; import type { CachedConversation } from "@xmtp/react-sdk"; import type { ActiveTab } from "../store/xmtp"; import { useXmtpStore } from "../store/xmtp"; @@ -26,7 +26,7 @@ export const ConversationListController = ({ const { isLoaded, isLoading, conversations } = useListConversations(); const { isAllowed, isDenied } = useConsent(); - // const { db } = useDb(); + const { db } = useDb(); // const [messages, setMessages] = useState([]); // const messagesDb = db.table("messages");