diff --git a/package-lock.json b/package-lock.json
index ee28d0a1..ccca33b5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15016,6 +15016,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",
@@ -20643,53 +20690,6 @@
"rlp": "^2.2.3"
}
},
- "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/ethjs-util": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz",
@@ -44494,6 +44494,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": {
@@ -48873,43 +48912,6 @@
}
}
},
- "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"
- }
- },
"ethjs-util": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz",
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 30643741..d5547fb2 100644
--- a/src/controllers/ConversationListController.tsx
+++ b/src/controllers/ConversationListController.tsx
@@ -1,5 +1,6 @@
import { useEffect, useMemo } from "react";
-import { useConsent, useDb } 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";
import useListConversations from "../hooks/useListConversations";
@@ -14,6 +15,7 @@ type ConversationListControllerProps = {
type ConsentProps = {
tab: ActiveTab;
+ convo: CachedConversation;
};
type NodeWithConsent = React.ReactElement;
@@ -25,8 +27,14 @@ 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 changedConsentCount = useXmtpStore((s) => s.changedConsentCount);
+
const activeTab = useXmtpStore((s) => s.activeTab);
// when the conversations are loaded, update their identities
@@ -38,38 +46,76 @@ export const ConversationListController = ({
};
void runUpdate();
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [isLoaded, activeTab]);
+ }, [isLoaded, activeTab, changedConsentCount]);
- const filteredConversations = useMemo(() => {
- const convos = conversations.map((conversation) => (
-
- ));
- return convos;
- }, [conversations, isAllowed, isDenied]);
+ // 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]);
- const messagesToPass = useMemo(
- () =>
- filteredConversations.filter((item: NodeWithConsent) => {
- if (!isLoading && activeTab === "messages") {
- return item.props.tab === "messages";
+ const messagesToPass = useMemo(() => {
+ const conversationsWithTab = conversations.map(
+ (conversation: CachedConversation) => {
+ const tab = isAllowed(conversation.peerAddress)
+ ? "messages"
+ : isDenied(conversation.peerAddress)
+ ? "blocked"
+ : "requests";
+ return (
+
+ );
+ },
+ );
+ const sortedConvos = conversationsWithTab.filter(
+ (item: NodeWithConsent) => {
+ // 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") {
+ return isAddressAllowed;
}
- if (!isLoading && activeTab === "blocked") {
- return item.props.tab === "blocked";
+ if (activeTab === "blocked") {
+ return isAddressBlocked;
}
- return item.props.tab === "requests";
- }),
- [filteredConversations, isLoading, activeTab],
- );
+ if (activeTab === "requests") {
+ return !isAddressBlocked && !isAddressAllowed;
+ }
+ return null;
+ },
+ );
+ return sortedConvos;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [
+ conversations,
+ // messages,
+ isLoading,
+ walletAddress,
+ // db,
+ changedConsentCount,
+ isAllowed,
+ isDenied,
+ ]);
return (
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 })),
}));