Skip to content

Commit

Permalink
feat: user handle links to dm (#54)
Browse files Browse the repository at this point in the history
* feat: adds linkify matrix replacement with slight mods

* feat: adds fetching the bot accounts from the backend

* feat: atoms for verified bots

* fix(wallet): updates link storage to correct orders

* refactor(dm): extracts openDmForUser

* chore: removes community bot atom

* chore: removes last wallet bot usage

* chore: removes trailing comma
  • Loading branch information
kenodressel authored Feb 16, 2024
1 parent 069e3c8 commit fc6280a
Show file tree
Hide file tree
Showing 9 changed files with 386 additions and 46 deletions.
1 change: 1 addition & 0 deletions components.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"src/components/structures/HomePage.tsx": "src/components/structures/HomePage.tsx",
"src/components/views/dialogs/spotlight/SpotlightDialog.tsx": "src/components/views/dialogs/spotlight/SpotlightDialog.tsx",
"src/components/views/elements/Pill.tsx": "src/components/views/elements/Pill.tsx",
"src/linkify-matrix.ts": "src/linkify-matrix.ts",
"src/components/structures/LeftPanel.tsx": "src/components/structures/LeftPanel.tsx",
"src/components/views/rooms/RoomList.tsx": "src/components/views/rooms/RoomList.tsx",
"src/components/views/rooms/RoomSublist.tsx": "src/components/views/rooms/RoomSublist.tsx"
Expand Down
4 changes: 1 addition & 3 deletions config.sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,5 @@
"participant_limit": 8,
"brand": "Element Call"
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx",
"community_bot_user_id": "@communitybot:superhero.com",
"wallet_bot_user_id": "@walletbot:superhero.com"
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
}
18 changes: 13 additions & 5 deletions src/atoms.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { atomWithStorage } from "jotai/utils";
import { getDefaultStore } from "jotai/index";

type TokenThreshold = {
threshold: string;
Expand All @@ -10,10 +11,17 @@ export type BareUser = {
rawDisplayName: string;
};

type BotAccounts = {
communityBot: string;
superheroBot: string;
blockchainBot: string;
};

export const verifiedAccountsAtom = atomWithStorage<Record<string, string>>("VERIFIED_ACCOUNTS", {});
export const verifiedBotsAtom = atomWithStorage<Record<string, string>>("VERIFIED_BOTS", {});
export const botAccountsAtom = atomWithStorage<BotAccounts | null>("BOT_ACCOUNTS", null);
export const minimumTokenThresholdAtom = atomWithStorage<Record<string, TokenThreshold>>("TOKEN_THRESHOLD", {});
export const communityBotAtom = atomWithStorage<BareUser>("COMMUNITY_BOT", {
userId: "",
rawDisplayName: "",
});

export function getBotAccountData(): BotAccounts | null {
const defaultStore = getDefaultStore();
return defaultStore.get(botAccountsAtom) as BotAccounts | null;
}
9 changes: 8 additions & 1 deletion src/components/structures/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ import { useMatrixClientContext } from "matrix-react-sdk/src/contexts/MatrixClie
import { DirectoryMember, startDmOnFirstMessage } from "matrix-react-sdk/src/utils/direct-messages";
import { getHomePageUrl } from "matrix-react-sdk/src/utils/pages";
import * as React from "react";
import { useAtom } from "jotai";

import { Icon as ChatScreenShot } from "../../../res/themes/superhero/img/arts/chat-screenshot.svg";
import { Icon as ChromeIcon } from "../../../res/themes/superhero/img/icons/chrome.svg";
import { Icon as FirefoxIcon } from "../../../res/themes/superhero/img/icons/firefox.svg";
import { Icon as SuperheroLogo } from "../../../res/themes/superhero/img/logos/superhero-logo.svg";
import { botAccountsAtom } from "../../atoms";

interface IProps {
justRegistered?: boolean;
Expand All @@ -36,6 +38,7 @@ const HomePage: React.FC<IProps> = () => {
const cli = useMatrixClientContext();
const config: any = SdkConfig.get();
const pageUrl = getHomePageUrl(config, cli);
const [botAccounts] = useAtom(botAccountsAtom);

if (pageUrl) {
return <EmbeddedPage className="mx_HomePage" url={pageUrl} scrollbar={true} />;
Expand Down Expand Up @@ -81,7 +84,11 @@ const HomePage: React.FC<IProps> = () => {
<div className="mx_HomePage_default_buttons">
<AccessibleButton
onClick={(): void => {
startDmOnFirstMessage(cli, [new DirectoryMember({ user_id: config.wallet_bot_user_id })]);
startDmOnFirstMessage(cli, [
new DirectoryMember({
user_id: botAccounts?.superheroBot || "",
}),
]);
}}
className="mx_HomePage_button_custom"
>
Expand Down
23 changes: 9 additions & 14 deletions src/components/views/elements/MessageButton.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import React, { useContext, useState } from "react";
import MatrixClientContext from "matrix-react-sdk/src/contexts/MatrixClientContext";
import AccessibleButton from "matrix-react-sdk/src/components/views/elements/AccessibleButton";
import { MatrixClient, RoomMember, User } from "matrix-js-sdk/src/matrix";
import { DirectoryMember, startDmOnFirstMessage } from "matrix-react-sdk/src/utils/direct-messages";
import { useAtom } from "jotai";

import { Member } from "../right_panel/UserInfo";
import { Icon as SendMessage } from "../../../../res/themes/superhero/img/icons/send.svg";
import { BareUser, communityBotAtom } from "../../../atoms";
import { BareUser, botAccountsAtom } from "../../../atoms";
import { openDmForUser } from "../../../utils";

/**
* Converts the member to a DirectoryMember and starts a DM with them.
*/
async function openDmForUser(matrixClient: MatrixClient, user: Member | BareUser): Promise<void> {
const avatarUrl = user instanceof User ? user.avatarUrl : user instanceof RoomMember ? user.getMxcAvatarUrl() : "";
const startDmUser = new DirectoryMember({
user_id: user.userId,
display_name: user.rawDisplayName,
avatar_url: avatarUrl,
});
await startDmOnFirstMessage(matrixClient, [startDmUser]);
}

export const MessageButton = ({
member,
Expand Down Expand Up @@ -51,7 +41,12 @@ export const MessageButton = ({
};

export const MessageCommunityBotButton = ({ text = "Send Message" }: { text?: string }): JSX.Element => {
const [communityBot] = useAtom(communityBotAtom);
const [botAccounts] = useAtom(botAccountsAtom);

return <MessageButton member={communityBot} text={text} />;
const botUser = {
userId: botAccounts?.communityBot || "",
rawDisplayName: "Community Bot",
} as Member;

return <MessageButton member={botUser} text={text} />;
};
50 changes: 33 additions & 17 deletions src/context/SuperheroProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { useAtom } from "jotai";
import React, { useCallback, useEffect } from "react";

import { communityBotAtom, minimumTokenThresholdAtom, verifiedAccountsAtom, verifiedBotsAtom } from "../atoms";
import { minimumTokenThresholdAtom, verifiedAccountsAtom, botAccountsAtom } from "../atoms";

type BotAccounts = {
domain: string;
communityBot: {
userId: string;
};
superheroBot: {
userId: string;
};
blockchainBot: {
userId: string;
};
};

const useMinimumTokenThreshold = (config: any): void => {
const [, setMinimumTokenThreshold] = useAtom(minimumTokenThresholdAtom);
Expand Down Expand Up @@ -38,15 +51,7 @@ const useMinimumTokenThreshold = (config: any): void => {
*/
export const SuperheroProvider = ({ children, config }: any): any => {
const [verifiedAccounts, setVerifiedAccounts] = useAtom(verifiedAccountsAtom);
const [, setVerifiedBots] = useAtom(verifiedBotsAtom);
const [, setCommunityBot] = useAtom(communityBotAtom);

useEffect(() => {
setCommunityBot({
userId: config.community_bot_user_id,
rawDisplayName: "Community DAO Room Bot",
});
}, [setCommunityBot, config.community_bot_user_id]);
const [, setBotAccounts] = useAtom(botAccountsAtom);

function loadVerifiedAccounts(): void {
if (config.bots_backend_url) {
Expand All @@ -61,15 +66,26 @@ export const SuperheroProvider = ({ children, config }: any): any => {
}
}

function loadVerifiedBots(): void {
setVerifiedBots({
[config.community_bot_user_id]: "true",
[config.wallet_bot_user_id]: "true",
});
}
useEffect(() => {
if (config.bots_backend_url) {
fetch(`${config.bots_backend_url}/ui/bot-accounts`, {
method: "GET",
})
.then((res) => res.json())
.then((data: BotAccounts) => {
setBotAccounts({
communityBot: "@" + data.communityBot.userId + ":" + data.domain,
superheroBot: "@" + data.superheroBot.userId + ":" + data.domain,
blockchainBot: "@" + data.blockchainBot.userId + ":" + data.domain,
});
})
.catch(() => {
//
});
}
}, [config.bots_backend_url, setBotAccounts]);

useEffect(() => {
loadVerifiedBots();
if (!verifiedAccounts?.length) {
loadVerifiedAccounts();
}
Expand Down
26 changes: 20 additions & 6 deletions src/hooks/useVerifiedBot.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
import { useMemo } from "react";
import { useAtom } from "jotai";

import { verifiedBotsAtom } from "../atoms";
import { botAccountsAtom, getBotAccountData } from "../atoms";

/**
* Custom hook to check if a bot is verified.
* @param botId - The ID of the bot to check.
* @returns A boolean indicating whether the bot is verified or not.
*/
export function useVerifiedBot(botId?: string): boolean {
const [verifiedBots] = useAtom(verifiedBotsAtom);
const [botAccounts] = useAtom(botAccountsAtom);

const isVerifiedBot: boolean = useMemo(() => {
return !!(botId && !!verifiedBots[botId]);
}, [botId, verifiedBots]);
return useMemo(() => {
return !!(
botId &&
(botId === botAccounts?.communityBot ||
botId === botAccounts?.superheroBot ||
botId === botAccounts?.blockchainBot)
);
}, [botId, botAccounts]);
}

export function isVerifiedBot(botId?: string): boolean {
const botAccounts = getBotAccountData();

return isVerifiedBot;
return !!(
botId &&
(botId === botAccounts?.communityBot ||
botId === botAccounts?.superheroBot ||
botId === botAccounts?.blockchainBot)
);
}
Loading

0 comments on commit fc6280a

Please sign in to comment.