From 615ce96d58b40b9ad681a5b530388160fcd2be4a Mon Sep 17 00:00:00 2001 From: Badi Ifaoui Date: Thu, 25 Jan 2024 08:32:00 +0100 Subject: [PATCH 1/3] feat: trusted bots badge & fix verified account checker --- src/atoms.ts | 1 + src/components/views/dialogs/InviteDialog.tsx | 2 ++ .../views/elements/BotVerifiedBadge.tsx | 31 +++++++++++++++++++ src/components/views/elements/RoomName.tsx | 28 +++++++++-------- src/components/views/right_panel/UserInfo.tsx | 2 ++ src/context/SuperheroProvider.tsx | 20 +++++++++++- src/hooks/useVerifiedBot.ts | 19 ++++++++++++ 7 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 src/components/views/elements/BotVerifiedBadge.tsx create mode 100644 src/hooks/useVerifiedBot.ts diff --git a/src/atoms.ts b/src/atoms.ts index 4a933a575d..84da6cb591 100644 --- a/src/atoms.ts +++ b/src/atoms.ts @@ -11,6 +11,7 @@ export type BareUser = { }; export const verifiedAccountsAtom = atomWithStorage>("VERIFIED_ACCOUNTS", {}); +export const verifiedBotsAtom = atomWithStorage>("VERIFIED_BOTS", {}); export const minimumTokenThresholdAtom = atomWithStorage>("TOKEN_THRESHOLD", {}); export const communityBotAtom = atomWithStorage("COMMUNITY_BOT", { userId: "", diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 9ed31af258..8b94ad9a36 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -81,6 +81,7 @@ import { SdkContextClass } from "matrix-react-sdk/src/contexts/SDKContext"; import { UserProfilesStore } from "matrix-react-sdk/src/stores/UserProfilesStore"; import { UserVerifiedBadge } from "../elements/UserVerifiedBadge"; +import { BotVerifiedBadge } from "../elements/BotVerifiedBadge"; // we have a number of types defined from the Matrix spec which can't reasonably be altered here. /* eslint-disable camelcase */ @@ -288,6 +289,7 @@ class DMRoomTile extends React.PureComponent {
{this.highlightName(this.props.member.name)} +
{caption}
diff --git a/src/components/views/elements/BotVerifiedBadge.tsx b/src/components/views/elements/BotVerifiedBadge.tsx new file mode 100644 index 0000000000..67948a6497 --- /dev/null +++ b/src/components/views/elements/BotVerifiedBadge.tsx @@ -0,0 +1,31 @@ +import React from "react"; + +import { useVerifiedBot } from "../../../hooks/useVerifiedBot"; + +export interface UserVerifiedBadgeProps { + userId: string; +} + +export const BotVerifiedBadge = ({ userId }: UserVerifiedBadgeProps): JSX.Element => { + const isVerifiedBot = useVerifiedBot(userId); + + return ( + <> + {isVerifiedBot && ( +
+ Trusted Bot +
+ )} + + ); +}; diff --git a/src/components/views/elements/RoomName.tsx b/src/components/views/elements/RoomName.tsx index f4ae920842..66139b6e64 100644 --- a/src/components/views/elements/RoomName.tsx +++ b/src/components/views/elements/RoomName.tsx @@ -22,6 +22,7 @@ import { Icon as CommunityRoomIcon } from "../../../../res/themes/superhero/img/ import { useRoomName } from "../../../hooks/useRoomName"; import { useVerifiedRoom } from "../../../hooks/useVerifiedRoom"; import { UserVerifiedBadge } from "./UserVerifiedBadge"; +import { BotVerifiedBadge } from "./BotVerifiedBadge"; interface IProps { room?: Room | IPublicRoomsChunkRoom; @@ -33,16 +34,18 @@ export const RoomName = ({ room, children, maxLength }: IProps): JSX.Element => const roomName = useRoomName(room); const { isTokenGatedRoom, isCommunityRoom } = useVerifiedRoom(room); - const roomUsers: string[] = useMemo(() => { - if ((room as Room).getJoinedMemberCount?.() > 2 || (room as IPublicRoomsChunkRoom).num_joined_members > 2) { - return []; + const roomUser: string | undefined = useMemo(() => { + // check if this is a DM room and if so, return the other user's ID + const dmUserId = (room as Room)?.guessDMUserId?.(); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + // need to access the private summaryHeroes property, to know if it's a DM room + if (!(room as Room)?.summaryHeroes) { + return undefined; } - return ( - (room as Room) - ?.getMembers?.() - .map((m: { userId: string }) => m.userId) - .filter((userId: string) => !!userId && userId !== (room as Room)?.myUserId) || [] - ); + + return dmUserId && dmUserId !== (room as Room).myUserId ? dmUserId : undefined; }, [room]); const truncatedRoomName = useMemo(() => { @@ -63,12 +66,11 @@ export const RoomName = ({ room, children, maxLength }: IProps): JSX.Element => )} {isTokenGatedRoom && } {truncatedRoomName} - {roomUsers?.length && !isTokenGatedRoom && !isCommunityRoom ? ( - - ) : null} + {roomUser && !isTokenGatedRoom && !isCommunityRoom ? : null} + {roomUser && !isTokenGatedRoom && !isCommunityRoom ? : null} ), - [truncatedRoomName, isCommunityRoom, isTokenGatedRoom, roomUsers], + [truncatedRoomName, isCommunityRoom, isTokenGatedRoom, roomUser], ); if (children) return children(renderRoomName()); diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 4a8e269c79..fdfa87a5b8 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -84,6 +84,7 @@ import UIStore from "matrix-react-sdk/src/stores/UIStore"; import { UserVerifiedBadge } from "../elements/UserVerifiedBadge"; import { MessageButton } from "../elements/MessageButton"; +import { BotVerifiedBadge } from "../elements/BotVerifiedBadge"; export interface IDevice extends Device { ambiguous?: boolean; @@ -1617,6 +1618,7 @@ export const UserInfoHeader: React.FC<{

+ {displayName} diff --git a/src/context/SuperheroProvider.tsx b/src/context/SuperheroProvider.tsx index 0653efc08b..6a2c596168 100644 --- a/src/context/SuperheroProvider.tsx +++ b/src/context/SuperheroProvider.tsx @@ -1,7 +1,7 @@ import { useAtom } from "jotai"; import React, { useCallback, useEffect } from "react"; -import { communityBotAtom, minimumTokenThresholdAtom, verifiedAccountsAtom } from "../atoms"; +import { communityBotAtom, minimumTokenThresholdAtom, verifiedAccountsAtom, verifiedBotsAtom } from "../atoms"; const useMinimumTokenThreshold = (config: any): void => { const [, setMinimumTokenThreshold] = useAtom(minimumTokenThresholdAtom); @@ -43,6 +43,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(() => { @@ -65,7 +66,24 @@ export const SuperheroProvider = ({ children, config }: any): any => { } } + function loadVerifiedBots(): void { + if (config.bots_backend_url) { + fetch(`${config.bots_backend_url}/ui/get-verified-bots`, { + method: "POST", + }) + .then((res) => res.json()) + .then(setVerifiedBots) + .catch(() => { + setVerifiedBots({ + "@walletbot:superhero.chat": "true", + "@communitybot:superhero.chat": "true", + }); + }); + } + } + useEffect(() => { + loadVerifiedBots(); if (!verifiedAccounts?.length) { loadVerifiedAccounts(); } diff --git a/src/hooks/useVerifiedBot.ts b/src/hooks/useVerifiedBot.ts new file mode 100644 index 0000000000..ed49d35a02 --- /dev/null +++ b/src/hooks/useVerifiedBot.ts @@ -0,0 +1,19 @@ +import { useMemo } from "react"; +import { useAtom } from "jotai"; + +import { verifiedBotsAtom } 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 isVerifiedBot: boolean = useMemo(() => { + return !!(botId && !!verifiedBots[botId]); + }, [botId, verifiedBots]); + + return isVerifiedBot; +} From e1a398597b8528db20792ea556429cfb47b8ba3e Mon Sep 17 00:00:00 2001 From: Badi Ifaoui Date: Fri, 26 Jan 2024 07:57:58 +0100 Subject: [PATCH 2/3] fix: pill style --- src/components/views/elements/Pill.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/Pill.tsx b/src/components/views/elements/Pill.tsx index d020d67328..8ddcde2e19 100644 --- a/src/components/views/elements/Pill.tsx +++ b/src/components/views/elements/Pill.tsx @@ -156,12 +156,12 @@ export const Pill: React.FC = ({ type: propType, url, inMessage, room <> {isCommunityRoom ? ( <> - + $ ) : null} {isTokenGatedRoom ? ( - + ) : null} {getSafeRoomName(pillText || "")} From c571af4f05de623edbf0e26b3bdc6808a2edd8f2 Mon Sep 17 00:00:00 2001 From: Badi Ifaoui Date: Fri, 26 Jan 2024 08:52:03 +0100 Subject: [PATCH 3/3] fix: configs & home style --- config.sample.json | 12 +++-- res/css/superhero/custom.css | 21 ++++++-- .../superhero/img/arts/chat-screenshot.svg | 53 +++++++------------ src/components/structures/HomePage.tsx | 8 +-- src/context/SuperheroProvider.tsx | 17 ++---- 5 files changed, 50 insertions(+), 61 deletions(-) diff --git a/config.sample.json b/config.sample.json index 7974608974..cbb8ccb8fa 100644 --- a/config.sample.json +++ b/config.sample.json @@ -1,19 +1,20 @@ { "default_server_config": { "m.homeserver": { - "base_url": "https://matrix-client.matrix.org", - "server_name": "matrix.org" + "base_url": "https://matrix.superhero.com", + "server_name": "superhero.com" }, "m.identity_server": { "base_url": "https://vector.im" } }, - "bots_backend_url": "https://http://matrix.superhero.com/wallet", + "bots_backend_url": "https://matrix.superhero.com/walletbot", + "permalink_prefix": "https://chat.superhero.com", "disable_custom_urls": false, "disable_guests": false, "disable_login_language_selector": false, "disable_3pid_login": false, - "brand": "Element", + "brand": "Superhero", "integrations_ui_url": "https://scalar.vector.im/", "integrations_rest_url": "https://scalar.vector.im/api", "integrations_widgets_urls": [ @@ -47,5 +48,6 @@ "brand": "Element Call" }, "map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx", - "community_bot_user_id": "@communitybot:superhero.com" + "community_bot_user_id": "@communitybot:superhero.com", + "wallet_bot_user_id": "@walletbot:superhero.com" } diff --git a/res/css/superhero/custom.css b/res/css/superhero/custom.css index e27a4ca430..d2e71db399 100644 --- a/res/css/superhero/custom.css +++ b/res/css/superhero/custom.css @@ -105,7 +105,7 @@ h2 .sh_VerifiedIcon { .mx_AccessibleButton.mx_LegacyRoomHeader_button.mx_AccessibleButton_disabled { display: none; - } +} .cpd-theme-dark .mx_SpacePanel .mx_AccessibleButton.mx_SpacePanel_toggleCollapse { background-color: white !important; @@ -221,7 +221,7 @@ h2 .sh_VerifiedIcon { --cpd-color-alpha-gray-500: hsla(214, 41%, 97%, 0.15); --cpd-color-pink-1200: #c81fb7 !important; --cpd-color-pink-300: #544352 !important; - --cpd-color-fuchsia-1200: #D538EE !important; + --cpd-color-fuchsia-1200: #d538ee !important; --cpd-color-fuchsia-300: #52424f !important; --cpd-color-purple-1200: #9a30fd !important; --cpd-color-purple-300: #443f4c !important; @@ -269,22 +269,35 @@ h2 .sh_VerifiedIcon { } .mx_HomePage_title svg { - heigh: 44px; + height: 44px; width: 173.99px; margin-right: 8px; } +.mx_HomePage_default_wrapper .chat_screen_shot { + max-width: 70%; +} + .mx_HomePage_default_buttons_title { font-size: 30px; } + .cpd-theme-dark .mx_HomePage_default_buttons_title { - opacity: 0.7; + color: rgba(255, 255, 255, 0.7); +} + +.cpd-theme-dark .mx_HomePage_default_buttons_title span { + color: rgba(255, 255, 255, 1); } .mx_HomePage_default .mx_HomePage_default_buttons { margin: 10px auto 0 !important; } +.cpd-theme-dark .mx_HomePage_default .mx_HomePage_default_buttons.browsers .mx_HomePage_button_custom { + background-color: rgba(255, 255, 255, 0.1) !important; +} + .mx_HomePage_default .mx_HomePage_default_buttons .mx_AccessibleButton.mx_HomePage_button_custom { width: auto !important; min-height: auto !important; diff --git a/res/themes/superhero/img/arts/chat-screenshot.svg b/res/themes/superhero/img/arts/chat-screenshot.svg index 3d3312078e..5638ab7ede 100644 --- a/res/themes/superhero/img/arts/chat-screenshot.svg +++ b/res/themes/superhero/img/arts/chat-screenshot.svg @@ -1,43 +1,26 @@ - - - + + + + - - + + - - - - - - + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/src/components/structures/HomePage.tsx b/src/components/structures/HomePage.tsx index 6a6bb9f4dd..55ee4996b0 100644 --- a/src/components/structures/HomePage.tsx +++ b/src/components/structures/HomePage.tsx @@ -34,7 +34,7 @@ interface IProps { const HomePage: React.FC = () => { const cli = useMatrixClientContext(); - const config = SdkConfig.get(); + const config: any = SdkConfig.get(); const pageUrl = getHomePageUrl(config, cli); if (pageUrl) { @@ -44,7 +44,7 @@ const HomePage: React.FC = () => { return (
- +
is so much better with our Wallet
@@ -52,7 +52,7 @@ const HomePage: React.FC = () => {
1. Download extension for your browser
-
+
{ window.open("https://addons.mozilla.org/en-US/firefox/addon/superhero-wallet/", "_blank"); @@ -81,7 +81,7 @@ const HomePage: React.FC = () => {
{ - startDmOnFirstMessage(cli, [new DirectoryMember({ user_id: "@walletbot:superhero.com" })]); + startDmOnFirstMessage(cli, [new DirectoryMember({ user_id: config.wallet_bot_user_id })]); }} className="mx_HomePage_button_custom" > diff --git a/src/context/SuperheroProvider.tsx b/src/context/SuperheroProvider.tsx index 6a2c596168..d1332fbc23 100644 --- a/src/context/SuperheroProvider.tsx +++ b/src/context/SuperheroProvider.tsx @@ -67,19 +67,10 @@ export const SuperheroProvider = ({ children, config }: any): any => { } function loadVerifiedBots(): void { - if (config.bots_backend_url) { - fetch(`${config.bots_backend_url}/ui/get-verified-bots`, { - method: "POST", - }) - .then((res) => res.json()) - .then(setVerifiedBots) - .catch(() => { - setVerifiedBots({ - "@walletbot:superhero.chat": "true", - "@communitybot:superhero.chat": "true", - }); - }); - } + setVerifiedBots({ + [config.community_bot_user_id]: "true", + [config.wallet_bot_user_id]: "true", + }); } useEffect(() => {