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