From 29cc221a34c4cd5805d098f38d442d3a128484e5 Mon Sep 17 00:00:00 2001
From: Paul <paulmakles@gmail.com>
Date: Sat, 31 Jul 2021 12:09:18 +0100
Subject: [PATCH] Fix elements not observing permissions.

---
 package.json                                  |   2 +-
 .../common/messaging/MessageBox.tsx           |   5 +-
 .../intermediate/popovers/UserProfile.tsx     | 550 +++++++++---------
 src/pages/settings/ChannelSettings.tsx        |   2 +-
 src/pages/settings/server/Members.tsx         |   8 +-
 yarn.lock                                     |   8 +-
 6 files changed, 297 insertions(+), 278 deletions(-)

diff --git a/package.json b/package.json
index 0abe86c..400a600 100644
--- a/package.json
+++ b/package.json
@@ -97,7 +97,7 @@
     "react-router-dom": "^5.2.0",
     "react-scroll": "^1.8.2",
     "redux": "^4.1.0",
-    "revolt.js": "5.0.0-alpha.12",
+    "revolt.js": "5.0.0-alpha.14",
     "rimraf": "^3.0.2",
     "sass": "^1.35.1",
     "shade-blend-color": "^1.0.0",
diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx
index 78a1b1a..bd35492 100644
--- a/src/components/common/messaging/MessageBox.tsx
+++ b/src/components/common/messaging/MessageBox.tsx
@@ -1,5 +1,6 @@
 import { Send, ShieldX } from "@styled-icons/boxicons-solid";
 import Axios, { CancelTokenSource } from "axios";
+import { observer } from "mobx-react-lite";
 import { ChannelPermission } from "revolt.js/dist/api/permissions";
 import { Channel } from "revolt.js/dist/maps/Channels";
 import styled from "styled-components";
@@ -108,7 +109,7 @@ const Action = styled.div`
 // ! FIXME: add to app config and load from app config
 export const CAN_UPLOAD_AT_ONCE = 4;
 
-export default function MessageBox({ channel }: Props) {
+export default observer(({ channel }: Props) => {
     const [draft, setDraft] = useState(getState().drafts[channel._id] ?? "");
 
     const [uploadState, setUploadState] = useState<UploadState>({
@@ -506,4 +507,4 @@ export default function MessageBox({ channel }: Props) {
             </Base>
         </>
     );
-}
+});
diff --git a/src/context/intermediate/popovers/UserProfile.tsx b/src/context/intermediate/popovers/UserProfile.tsx
index c0d4bb4..8c7ffc1 100644
--- a/src/context/intermediate/popovers/UserProfile.tsx
+++ b/src/context/intermediate/popovers/UserProfile.tsx
@@ -1,5 +1,6 @@
 import { Money } from "@styled-icons/boxicons-regular";
 import { Envelope, Edit, UserPlus, Shield } from "@styled-icons/boxicons-solid";
+import { observer } from "mobx-react-lite";
 import { Link, useHistory } from "react-router-dom";
 import { Profile, RelationshipStatus } from "revolt-api/types/Users";
 import { UserPermission } from "revolt.js/dist/api/permissions";
@@ -41,297 +42,314 @@ enum Badges {
     EarlyAdopter = 256,
 }
 
-export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
-    const { openScreen, writeClipboard } = useIntermediate();
+export const UserProfile = observer(
+    ({ user_id, onClose, dummy, dummyProfile }: Props) => {
+        const { openScreen, writeClipboard } = useIntermediate();
 
-    const [profile, setProfile] = useState<undefined | null | Profile>(
-        undefined,
-    );
-    const [mutual, setMutual] = useState<
-        undefined | null | Route<"GET", "/users/id/mutual">["response"]
-    >(undefined);
+        const [profile, setProfile] = useState<undefined | null | Profile>(
+            undefined,
+        );
+        const [mutual, setMutual] = useState<
+            undefined | null | Route<"GET", "/users/id/mutual">["response"]
+        >(undefined);
 
-    const history = useHistory();
-    const client = useClient();
-    const status = useContext(StatusContext);
-    const [tab, setTab] = useState("profile");
+        const history = useHistory();
+        const client = useClient();
+        const status = useContext(StatusContext);
+        const [tab, setTab] = useState("profile");
 
-    const user = client.users.get(user_id);
-    if (!user) {
-        useEffect(onClose, []);
-        return null;
-    }
-
-    const users = mutual?.users.map((id) => client.users.get(id));
+        const user = client.users.get(user_id);
+        if (!user) {
+            useEffect(onClose, []);
+            return null;
+        }
 
-    const mutualGroups = [...client.channels.values()].filter(
-        (channel) =>
-            channel?.channel_type === "Group" &&
-            channel.recipient_ids!.includes(user_id),
-    );
+        const users = mutual?.users.map((id) => client.users.get(id));
 
-    useLayoutEffect(() => {
-        if (!user_id) return;
-        if (typeof profile !== "undefined") setProfile(undefined);
-        if (typeof mutual !== "undefined") setMutual(undefined);
-    }, [user_id]);
+        const mutualGroups = [...client.channels.values()].filter(
+            (channel) =>
+                channel?.channel_type === "Group" &&
+                channel.recipient_ids!.includes(user_id),
+        );
 
-    if (dummy) {
         useLayoutEffect(() => {
-            setProfile(dummyProfile);
-        }, [dummyProfile]);
-    }
+            if (!user_id) return;
+            if (typeof profile !== "undefined") setProfile(undefined);
+            if (typeof mutual !== "undefined") setMutual(undefined);
+        }, [user_id]);
 
-    useEffect(() => {
-        if (dummy) return;
-        if (status === ClientStatus.ONLINE && typeof mutual === "undefined") {
-            setMutual(null);
-            user.fetchMutual().then(setMutual);
+        if (dummy) {
+            useLayoutEffect(() => {
+                setProfile(dummyProfile);
+            }, [dummyProfile]);
         }
-    }, [mutual, status]);
 
-    useEffect(() => {
-        if (dummy) return;
-        if (status === ClientStatus.ONLINE && typeof profile === "undefined") {
-            setProfile(null);
+        useEffect(() => {
+            if (dummy) return;
+            if (
+                status === ClientStatus.ONLINE &&
+                typeof mutual === "undefined"
+            ) {
+                setMutual(null);
+                user.fetchMutual().then(setMutual);
+            }
+        }, [mutual, status]);
+
+        useEffect(() => {
+            if (dummy) return;
+            if (
+                status === ClientStatus.ONLINE &&
+                typeof profile === "undefined"
+            ) {
+                setProfile(null);
 
-            if (user.permission & UserPermission.ViewProfile) {
-                user.fetchProfile()
-                    .then(setProfile)
-                    .catch(() => {});
+                if (user.permission & UserPermission.ViewProfile) {
+                    user.fetchProfile()
+                        .then(setProfile)
+                        .catch(() => {});
+                }
             }
-        }
-    }, [profile, status]);
+        }, [profile, status]);
 
-    const backgroundURL =
-        profile &&
-        client.generateFileURL(profile.background, { width: 1000 }, true);
-    const badges = user.badges ?? 0;
+        const backgroundURL =
+            profile &&
+            client.generateFileURL(profile.background, { width: 1000 }, true);
+        const badges = user.badges ?? 0;
 
-    return (
-        <Modal
-            visible
-            border={dummy}
-            padding={false}
-            onClose={onClose}
-            dontModal={dummy}>
-            <div
-                className={styles.header}
-                data-force={profile?.background ? "light" : undefined}
-                style={{
-                    backgroundImage:
-                        backgroundURL &&
-                        `linear-gradient( rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7) ), url('${backgroundURL}')`,
-                }}>
-                <div className={styles.profile}>
-                    <UserIcon size={80} target={user} status animate />
-                    <div className={styles.details}>
-                        <Localizer>
-                            <span
-                                className={styles.username}
-                                onClick={() => writeClipboard(user.username)}>
-                                @{user.username}
-                            </span>
-                        </Localizer>
-                        {user.status?.text && (
-                            <span className={styles.status}>
-                                <UserStatus user={user} tooltip />
-                            </span>
-                        )}
-                    </div>
-                    {user.relationship === RelationshipStatus.Friend && (
-                        <Localizer>
-                            <Tooltip
-                                content={
-                                    <Text id="app.context_menu.message_user" />
-                                }>
-                                <IconButton
-                                    onClick={() => {
-                                        onClose();
-                                        history.push(`/open/${user_id}`);
-                                    }}>
-                                    <Envelope size={30} />
-                                </IconButton>
-                            </Tooltip>
-                        </Localizer>
-                    )}
-                    {user.relationship === RelationshipStatus.User && (
-                        <IconButton
-                            onClick={() => {
-                                onClose();
-                                if (dummy) return;
-                                history.push(`/settings/profile`);
-                            }}>
-                            <Edit size={28} />
-                        </IconButton>
-                    )}
-                    {(user.relationship === RelationshipStatus.Incoming ||
-                        user.relationship === RelationshipStatus.None) && (
-                        <IconButton onClick={() => user.addFriend()}>
-                            <UserPlus size={28} />
-                        </IconButton>
-                    )}
-                </div>
-                <div className={styles.tabs}>
-                    <div
-                        data-active={tab === "profile"}
-                        onClick={() => setTab("profile")}>
-                        <Text id="app.special.popovers.user_profile.profile" />
-                    </div>
-                    {user.relationship !== RelationshipStatus.User && (
-                        <>
-                            <div
-                                data-active={tab === "friends"}
-                                onClick={() => setTab("friends")}>
-                                <Text id="app.special.popovers.user_profile.mutual_friends" />
-                            </div>
-                            <div
-                                data-active={tab === "groups"}
-                                onClick={() => setTab("groups")}>
-                                <Text id="app.special.popovers.user_profile.mutual_groups" />
-                            </div>
-                        </>
-                    )}
-                </div>
-            </div>
-            <div className={styles.content}>
-                {tab === "profile" && (
-                    <div>
-                        {!(profile?.content || badges > 0) && (
-                            <div className={styles.empty}>
-                                <Text id="app.special.popovers.user_profile.empty" />
-                            </div>
+        return (
+            <Modal
+                visible
+                border={dummy}
+                padding={false}
+                onClose={onClose}
+                dontModal={dummy}>
+                <div
+                    className={styles.header}
+                    data-force={profile?.background ? "light" : undefined}
+                    style={{
+                        backgroundImage:
+                            backgroundURL &&
+                            `linear-gradient( rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7) ), url('${backgroundURL}')`,
+                    }}>
+                    <div className={styles.profile}>
+                        <UserIcon size={80} target={user} status animate />
+                        <div className={styles.details}>
+                            <Localizer>
+                                <span
+                                    className={styles.username}
+                                    onClick={() =>
+                                        writeClipboard(user.username)
+                                    }>
+                                    @{user.username}
+                                </span>
+                            </Localizer>
+                            {user.status?.text && (
+                                <span className={styles.status}>
+                                    <UserStatus user={user} tooltip />
+                                </span>
+                            )}
+                        </div>
+                        {user.relationship === RelationshipStatus.Friend && (
+                            <Localizer>
+                                <Tooltip
+                                    content={
+                                        <Text id="app.context_menu.message_user" />
+                                    }>
+                                    <IconButton
+                                        onClick={() => {
+                                            onClose();
+                                            history.push(`/open/${user_id}`);
+                                        }}>
+                                        <Envelope size={30} />
+                                    </IconButton>
+                                </Tooltip>
+                            </Localizer>
                         )}
-                        {badges > 0 && (
-                            <div className={styles.category}>
-                                <Text id="app.special.popovers.user_profile.sub.badges" />
-                            </div>
+                        {user.relationship === RelationshipStatus.User && (
+                            <IconButton
+                                onClick={() => {
+                                    onClose();
+                                    if (dummy) return;
+                                    history.push(`/settings/profile`);
+                                }}>
+                                <Edit size={28} />
+                            </IconButton>
                         )}
-                        {badges > 0 && (
-                            <div className={styles.badges}>
-                                <Localizer>
-                                    {badges & Badges.Developer ? (
-                                        <Tooltip
-                                            content={
-                                                <Text id="app.navigation.tabs.dev" />
-                                            }>
-                                            <img src="/assets/badges/developer.svg" />
-                                        </Tooltip>
-                                    ) : (
-                                        <></>
-                                    )}
-                                    {badges & Badges.Translator ? (
-                                        <Tooltip
-                                            content={
-                                                <Text id="app.special.popovers.user_profile.badges.translator" />
-                                            }>
-                                            <img src="/assets/badges/translator.svg" />
-                                        </Tooltip>
-                                    ) : (
-                                        <></>
-                                    )}
-                                    {badges & Badges.EarlyAdopter ? (
-                                        <Tooltip
-                                            content={
-                                                <Text id="app.special.popovers.user_profile.badges.early_adopter" />
-                                            }>
-                                            <img src="/assets/badges/early_adopter.svg" />
-                                        </Tooltip>
-                                    ) : (
-                                        <></>
-                                    )}
-                                    {badges & Badges.Supporter ? (
-                                        <Tooltip
-                                            content={
-                                                <Text id="app.special.popovers.user_profile.badges.supporter" />
-                                            }>
-                                            <Money size={32} color="#efab44" />
-                                        </Tooltip>
-                                    ) : (
-                                        <></>
-                                    )}
-                                    {badges & Badges.ResponsibleDisclosure ? (
-                                        <Tooltip
-                                            content={
-                                                <Text id="app.special.popovers.user_profile.badges.responsible_disclosure" />
-                                            }>
-                                            <Shield size={32} color="gray" />
-                                        </Tooltip>
-                                    ) : (
-                                        <></>
-                                    )}
-                                </Localizer>
-                            </div>
+                        {(user.relationship === RelationshipStatus.Incoming ||
+                            user.relationship === RelationshipStatus.None) && (
+                            <IconButton onClick={() => user.addFriend()}>
+                                <UserPlus size={28} />
+                            </IconButton>
                         )}
-                        {profile?.content && (
-                            <div className={styles.category}>
-                                <Text id="app.special.popovers.user_profile.sub.information" />
-                            </div>
+                    </div>
+                    <div className={styles.tabs}>
+                        <div
+                            data-active={tab === "profile"}
+                            onClick={() => setTab("profile")}>
+                            <Text id="app.special.popovers.user_profile.profile" />
+                        </div>
+                        {user.relationship !== RelationshipStatus.User && (
+                            <>
+                                <div
+                                    data-active={tab === "friends"}
+                                    onClick={() => setTab("friends")}>
+                                    <Text id="app.special.popovers.user_profile.mutual_friends" />
+                                </div>
+                                <div
+                                    data-active={tab === "groups"}
+                                    onClick={() => setTab("groups")}>
+                                    <Text id="app.special.popovers.user_profile.mutual_groups" />
+                                </div>
+                            </>
                         )}
-                        <Markdown content={profile?.content} />
-                        {/*<div className={styles.category}><Text id="app.special.popovers.user_profile.sub.connections" /></div>*/}
                     </div>
-                )}
-                {tab === "friends" &&
-                    (users ? (
+                </div>
+                <div className={styles.content}>
+                    {tab === "profile" && (
+                        <div>
+                            {!(profile?.content || badges > 0) && (
+                                <div className={styles.empty}>
+                                    <Text id="app.special.popovers.user_profile.empty" />
+                                </div>
+                            )}
+                            {badges > 0 && (
+                                <div className={styles.category}>
+                                    <Text id="app.special.popovers.user_profile.sub.badges" />
+                                </div>
+                            )}
+                            {badges > 0 && (
+                                <div className={styles.badges}>
+                                    <Localizer>
+                                        {badges & Badges.Developer ? (
+                                            <Tooltip
+                                                content={
+                                                    <Text id="app.navigation.tabs.dev" />
+                                                }>
+                                                <img src="/assets/badges/developer.svg" />
+                                            </Tooltip>
+                                        ) : (
+                                            <></>
+                                        )}
+                                        {badges & Badges.Translator ? (
+                                            <Tooltip
+                                                content={
+                                                    <Text id="app.special.popovers.user_profile.badges.translator" />
+                                                }>
+                                                <img src="/assets/badges/translator.svg" />
+                                            </Tooltip>
+                                        ) : (
+                                            <></>
+                                        )}
+                                        {badges & Badges.EarlyAdopter ? (
+                                            <Tooltip
+                                                content={
+                                                    <Text id="app.special.popovers.user_profile.badges.early_adopter" />
+                                                }>
+                                                <img src="/assets/badges/early_adopter.svg" />
+                                            </Tooltip>
+                                        ) : (
+                                            <></>
+                                        )}
+                                        {badges & Badges.Supporter ? (
+                                            <Tooltip
+                                                content={
+                                                    <Text id="app.special.popovers.user_profile.badges.supporter" />
+                                                }>
+                                                <Money
+                                                    size={32}
+                                                    color="#efab44"
+                                                />
+                                            </Tooltip>
+                                        ) : (
+                                            <></>
+                                        )}
+                                        {badges &
+                                        Badges.ResponsibleDisclosure ? (
+                                            <Tooltip
+                                                content={
+                                                    <Text id="app.special.popovers.user_profile.badges.responsible_disclosure" />
+                                                }>
+                                                <Shield
+                                                    size={32}
+                                                    color="gray"
+                                                />
+                                            </Tooltip>
+                                        ) : (
+                                            <></>
+                                        )}
+                                    </Localizer>
+                                </div>
+                            )}
+                            {profile?.content && (
+                                <div className={styles.category}>
+                                    <Text id="app.special.popovers.user_profile.sub.information" />
+                                </div>
+                            )}
+                            <Markdown content={profile?.content} />
+                            {/*<div className={styles.category}><Text id="app.special.popovers.user_profile.sub.connections" /></div>*/}
+                        </div>
+                    )}
+                    {tab === "friends" &&
+                        (users ? (
+                            <div className={styles.entries}>
+                                {users.length === 0 ? (
+                                    <div className={styles.empty}>
+                                        <Text id="app.special.popovers.user_profile.no_users" />
+                                    </div>
+                                ) : (
+                                    users.map(
+                                        (x) =>
+                                            x && (
+                                                <div
+                                                    onClick={() =>
+                                                        openScreen({
+                                                            id: "profile",
+                                                            user_id: x._id,
+                                                        })
+                                                    }
+                                                    className={styles.entry}
+                                                    key={x._id}>
+                                                    <UserIcon
+                                                        size={32}
+                                                        target={x}
+                                                    />
+                                                    <span>{x.username}</span>
+                                                </div>
+                                            ),
+                                    )
+                                )}
+                            </div>
+                        ) : (
+                            <Preloader type="ring" />
+                        ))}
+                    {tab === "groups" && (
                         <div className={styles.entries}>
-                            {users.length === 0 ? (
+                            {mutualGroups.length === 0 ? (
                                 <div className={styles.empty}>
-                                    <Text id="app.special.popovers.user_profile.no_users" />
+                                    <Text id="app.special.popovers.user_profile.no_groups" />
                                 </div>
                             ) : (
-                                users.map(
+                                mutualGroups.map(
                                     (x) =>
-                                        x && (
-                                            <div
-                                                onClick={() =>
-                                                    openScreen({
-                                                        id: "profile",
-                                                        user_id: x._id,
-                                                    })
-                                                }
-                                                className={styles.entry}
-                                                key={x._id}>
-                                                <UserIcon
-                                                    size={32}
-                                                    target={x}
-                                                />
-                                                <span>{x.username}</span>
-                                            </div>
+                                        x?.channel_type === "Group" && (
+                                            <Link to={`/channel/${x._id}`}>
+                                                <div
+                                                    className={styles.entry}
+                                                    key={x._id}>
+                                                    <ChannelIcon
+                                                        target={x}
+                                                        size={32}
+                                                    />
+                                                    <span>{x.name}</span>
+                                                </div>
+                                            </Link>
                                         ),
                                 )
                             )}
                         </div>
-                    ) : (
-                        <Preloader type="ring" />
-                    ))}
-                {tab === "groups" && (
-                    <div className={styles.entries}>
-                        {mutualGroups.length === 0 ? (
-                            <div className={styles.empty}>
-                                <Text id="app.special.popovers.user_profile.no_groups" />
-                            </div>
-                        ) : (
-                            mutualGroups.map(
-                                (x) =>
-                                    x?.channel_type === "Group" && (
-                                        <Link to={`/channel/${x._id}`}>
-                                            <div
-                                                className={styles.entry}
-                                                key={x._id}>
-                                                <ChannelIcon
-                                                    target={x}
-                                                    size={32}
-                                                />
-                                                <span>{x.name}</span>
-                                            </div>
-                                        </Link>
-                                    ),
-                            )
-                        )}
-                    </div>
-                )}
-            </div>
-        </Modal>
-    );
-}
+                    )}
+                </div>
+            </Modal>
+        );
+    },
+);
diff --git a/src/pages/settings/ChannelSettings.tsx b/src/pages/settings/ChannelSettings.tsx
index 1cd7fec..8076565 100644
--- a/src/pages/settings/ChannelSettings.tsx
+++ b/src/pages/settings/ChannelSettings.tsx
@@ -30,7 +30,7 @@ export default function ChannelSettings() {
         switch (channel?.channel_type) {
             case "TextChannel":
             case "VoiceChannel":
-                base_url = `/server/${channel.server}/channel/${cid}/settings`;
+                base_url = `/server/${channel.server_id}/channel/${cid}/settings`;
                 break;
             default:
                 base_url = `/channel/${cid}/settings`;
diff --git a/src/pages/settings/server/Members.tsx b/src/pages/settings/server/Members.tsx
index c7b0c79..bdae55a 100644
--- a/src/pages/settings/server/Members.tsx
+++ b/src/pages/settings/server/Members.tsx
@@ -27,8 +27,6 @@ export const Members = observer(({ server }: Props) => {
         { members: Member[]; users: User[] } | undefined
     >(undefined);
 
-    const client = useClient();
-
     useEffect(() => {
         server.fetchMembers().then(setData);
     }, []);
@@ -50,10 +48,12 @@ export const Members = observer(({ server }: Props) => {
             {data &&
                 data.members.length > 0 &&
                 data.members
-                    .map((member, index) => {
+                    .map((member) => {
                         return {
                             member,
-                            user: data.users[index],
+                            user: data.users.find(
+                                (x) => x._id === member._id.user,
+                            ),
                         };
                     })
                     .map(({ member, user }) => (
diff --git a/yarn.lock b/yarn.lock
index f95d6a0..b3d7704 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3570,10 +3570,10 @@ revolt-api@0.5.1-alpha.10-patch.0:
   resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.1-alpha.10-patch.0.tgz#97d31bec7dfa4573567097443acb059c4feaac20"
   integrity sha512-UyM890HkGlYNQOxpHuEpUsJHLt8Ujnjg9/zPEDGpbvS4iy0jmHX23Hh8tOCfb/ewxbNrtT3G1HpSWKOneW/vYg==
 
-revolt.js@5.0.0-alpha.12:
-  version "5.0.0-alpha.12"
-  resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-5.0.0-alpha.12.tgz#06777f74f6a79161b18e02938a8d60d465395066"
-  integrity sha512-QqgawsSjrFTKhMA5JBKii6MgOJ4VO2u1GBmjTiKzPR2krnoWHdPSbD7VvD2scMGMPXIaIxU3zA++tyN8mfzIFg==
+revolt.js@5.0.0-alpha.14:
+  version "5.0.0-alpha.14"
+  resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-5.0.0-alpha.14.tgz#13b1d350a89467eb2ad6905a290ee1fada4150c1"
+  integrity sha512-kZBIx9PX8Y8Esu51Y6OgeFwlpajtaRv/ap3YKlWEELlAcDAEDoSZj+iL4ilkxIxvh4RDJMlVlAforwSvXvy9DQ==
   dependencies:
     axios "^0.19.2"
     eventemitter3 "^4.0.7"
-- 
GitLab