From 411fac2527fcbce63439df16bf49294cdf5fd13b Mon Sep 17 00:00:00 2001
From: Paul
Date: Thu, 29 Jul 2021 18:41:01 +0100
Subject: [PATCH] Remove useChannel
---
src/components/common/AgeGate.tsx | 7 +-
src/components/common/AutoComplete.tsx | 12 +--
src/components/common/ChannelIcon.tsx | 96 ++++++++++---------
.../common/messaging/MessageBox.tsx | 4 +-
.../navigation/items/ButtonItem.tsx | 20 ++--
.../navigation/left/HomeSidebar.tsx | 41 ++++----
.../navigation/left/ServerListSidebar.tsx | 13 ++-
.../navigation/left/ServerSidebar.tsx | 19 ++--
src/components/navigation/left/common.ts | 13 ++-
.../navigation/right/MemberSidebar.tsx | 37 +++----
src/context/intermediate/Intermediate.tsx | 12 +--
src/context/intermediate/modals/Prompt.tsx | 10 +-
.../intermediate/popovers/ChannelInfo.tsx | 21 ++--
.../intermediate/popovers/UserProfile.tsx | 19 ++--
src/context/revoltjs/hooks.ts | 7 --
src/context/revoltjs/util.tsx | 4 +-
src/lib/ContextMenus.tsx | 38 ++++----
src/mobx/index.ts | 4 +-
src/pages/channels/Channel.tsx | 21 ++--
src/pages/channels/ChannelHeader.tsx | 5 +-
src/pages/channels/actions/HeaderActions.tsx | 2 +-
.../channels/messaging/ConversationStart.tsx | 16 ++--
src/pages/settings/ChannelSettings.tsx | 12 ++-
src/pages/settings/channel/Overview.tsx | 16 ++--
src/pages/settings/channel/Permissions.tsx | 14 +--
src/pages/settings/server/Categories.tsx | 16 ++--
src/pages/settings/server/Invites.tsx | 16 ++--
src/pages/settings/server/Overview.tsx | 21 ++--
28 files changed, 259 insertions(+), 257 deletions(-)
diff --git a/src/components/common/AgeGate.tsx b/src/components/common/AgeGate.tsx
index 324005bb..adfb365d 100644
--- a/src/components/common/AgeGate.tsx
+++ b/src/components/common/AgeGate.tsx
@@ -1,10 +1,11 @@
+import { observer } from "mobx-react-lite";
import { useHistory } from "react-router-dom";
-import { Channel } from "revolt.js";
import styled from "styled-components";
import { Text } from "preact-i18n";
import { useState } from "preact/hooks";
+import { Channel } from "../../mobx";
import { dispatch, getState } from "../../redux";
import Button from "../ui/Button";
@@ -46,7 +47,7 @@ type Props = {
channel: Channel;
};
-export default function AgeGate(props: Props) {
+export default observer((props: Props) => {
const history = useHistory();
const [consent, setConsent] = useState(
getState().sectionToggle["nsfw"] ?? false,
@@ -105,4 +106,4 @@ export default function AgeGate(props: Props) {
);
-}
+});
diff --git a/src/components/common/AutoComplete.tsx b/src/components/common/AutoComplete.tsx
index faca2ffb..e457cbf8 100644
--- a/src/components/common/AutoComplete.tsx
+++ b/src/components/common/AutoComplete.tsx
@@ -5,7 +5,7 @@ import styled, { css } from "styled-components";
import { StateUpdater, useState } from "preact/hooks";
-import { User } from "../../mobx";
+import { Channel, User } from "../../mobx";
import { useData } from "../../mobx/State";
import { useClient } from "../../context/revoltjs/RevoltClient";
@@ -28,7 +28,7 @@ export type AutoCompleteState =
}
| {
type: "channel";
- matches: Channels.TextChannel[];
+ matches: Channel[];
}
));
@@ -197,15 +197,13 @@ export function useAutoComplete(
if (type === "channel" && searchClues?.channels) {
const channels = client.servers
.get(searchClues.channels.server)
- ?.channels.map((x) => client.channels.get(x))
- .filter(
- (x) => typeof x !== "undefined",
- ) as Channels.TextChannel[];
+ ?.channels.map((x) => store.channels.get(x))
+ .filter((x) => typeof x !== "undefined") as Channel[];
const matches = (
search.length > 0
? channels.filter((channel) =>
- channel.name.toLowerCase().match(regex),
+ channel.name!.toLowerCase().match(regex),
)
: channels
)
diff --git a/src/components/common/ChannelIcon.tsx b/src/components/common/ChannelIcon.tsx
index fb605c7a..301b009a 100644
--- a/src/components/common/ChannelIcon.tsx
+++ b/src/components/common/ChannelIcon.tsx
@@ -1,65 +1,67 @@
import { Hash, VolumeFull } from "@styled-icons/boxicons-regular";
+import { observer } from "mobx-react-lite";
import { Channels } from "revolt.js/dist/api/objects";
import { useContext } from "preact/hooks";
+import { Channel } from "../../mobx";
+
import { AppContext } from "../../context/revoltjs/RevoltClient";
import { ImageIconBase, IconBaseProps } from "./IconBase";
import fallback from "./assets/group.png";
-interface Props
- extends IconBaseProps<
- Channels.GroupChannel | Channels.TextChannel | Channels.VoiceChannel
- > {
+interface Props extends IconBaseProps {
isServerChannel?: boolean;
}
-export default function ChannelIcon(
- props: Props & Omit, keyof Props>,
-) {
- const client = useContext(AppContext);
+export default observer(
+ (
+ props: Props & Omit, keyof Props>,
+ ) => {
+ const client = useContext(AppContext);
- const {
- size,
- target,
- attachment,
- isServerChannel: server,
- animate,
- children,
- as,
- ...imgProps
- } = props;
- const iconURL = client.generateFileURL(
- target?.icon ?? attachment,
- { max_side: 256 },
- animate,
- );
- const isServerChannel =
- server ||
- (target &&
- (target.channel_type === "TextChannel" ||
- target.channel_type === "VoiceChannel"));
+ const {
+ size,
+ target,
+ attachment,
+ isServerChannel: server,
+ animate,
+ children,
+ as,
+ ...imgProps
+ } = props;
+ const iconURL = client.generateFileURL(
+ target?.icon ?? attachment,
+ { max_side: 256 },
+ animate,
+ );
+ const isServerChannel =
+ server ||
+ (target &&
+ (target.channel_type === "TextChannel" ||
+ target.channel_type === "VoiceChannel"));
- if (typeof iconURL === "undefined") {
- if (isServerChannel) {
- if (target?.channel_type === "VoiceChannel") {
- return ;
+ if (typeof iconURL === "undefined") {
+ if (isServerChannel) {
+ if (target?.channel_type === "VoiceChannel") {
+ return ;
+ }
+ return ;
}
- return ;
}
- }
- return (
- // ! fixme: replace fallback with +
-
- );
-}
+ return (
+ // ! fixme: replace fallback with +
+
+ );
+ },
+);
diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx
index 0ebb500e..2983295e 100644
--- a/src/components/common/messaging/MessageBox.tsx
+++ b/src/components/common/messaging/MessageBox.tsx
@@ -1,7 +1,6 @@
import { Send, HappyAlt, ShieldX } from "@styled-icons/boxicons-solid";
import { Styleshare } from "@styled-icons/simple-icons";
import Axios, { CancelTokenSource } from "axios";
-import { Channel } from "revolt.js";
import { ChannelPermission } from "revolt.js/dist/api/permissions";
import styled from "styled-components";
import { ulid } from "ulid";
@@ -20,6 +19,7 @@ import {
SMOOTH_SCROLL_ON_RECEIVE,
} from "../../../lib/renderer/Singleton";
+import { Channel } from "../../../mobx";
import { dispatch, getState } from "../../../redux";
import { Reply } from "../../../redux/reducers/queue";
@@ -360,7 +360,7 @@ export default function MessageBox({ channel }: Props) {
users: { type: "channel", id: channel._id },
channels:
channel.channel_type === "TextChannel"
- ? { server: channel.server }
+ ? { server: channel.server! }
: undefined,
});
diff --git a/src/components/navigation/items/ButtonItem.tsx b/src/components/navigation/items/ButtonItem.tsx
index d19290d3..734b5226 100644
--- a/src/components/navigation/items/ButtonItem.tsx
+++ b/src/components/navigation/items/ButtonItem.tsx
@@ -10,7 +10,7 @@ import { Localizer, Text } from "preact-i18n";
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
import { stopPropagation } from "../../../lib/stopPropagation";
-import { User } from "../../../mobx";
+import { Channel, User } from "../../../mobx";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
@@ -34,8 +34,8 @@ type CommonProps = Omit<
type UserProps = CommonProps & {
user: User;
- context?: Channels.Channel;
- channel?: Channels.DirectMessageChannel;
+ context?: Channel;
+ channel?: Channel;
};
export const UserButton = observer((props: UserProps) => {
@@ -73,7 +73,7 @@ export const UserButton = observer((props: UserProps) => {
{
{channel?.last_message && alert ? (
- channel.last_message.short
+ (channel.last_message as { short: string }).short
) : (
)}
@@ -115,12 +115,12 @@ export const UserButton = observer((props: UserProps) => {
});
type ChannelProps = CommonProps & {
- channel: Channels.Channel & { unread?: string };
+ channel: Channel & { unread?: string };
user?: User;
compact?: boolean;
};
-export function ChannelButton(props: ChannelProps) {
+export const ChannelButton = observer((props: ChannelProps) => {
const { active, alert, alertCount, channel, user, compact, ...divProps } =
props;
@@ -153,12 +153,12 @@ export function ChannelButton(props: ChannelProps) {
{channel.channel_type === "Group" && (
{channel.last_message && alert ? (
- channel.last_message.short
+ (channel.last_message as { short: string }).short
) : (
)}
@@ -186,7 +186,7 @@ export function ChannelButton(props: ChannelProps) {
);
-}
+});
type ButtonProps = CommonProps & {
onClick?: () => void;
diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx
index e22d35bf..d9cea635 100644
--- a/src/components/navigation/left/HomeSidebar.tsx
+++ b/src/components/navigation/left/HomeSidebar.tsx
@@ -43,10 +43,16 @@ const HomeSidebar = observer((props: Props) => {
const { channel } = useParams<{ channel: string }>();
const { openScreen } = useIntermediate();
- const ctx = useForceUpdate();
- const channels = useDMs(ctx);
+ const store = useData();
+ const channels = [...store.channels.values()]
+ .filter(
+ (x) =>
+ x.channel_type === "DirectMessage" ||
+ x.channel_type === "Group",
+ )
+ .map((x) => mapChannelWithUnread(x, props.unreads));
- const obj = channels.find((x) => x?._id === channel);
+ const obj = store.channels.get(channel);
if (channel && !obj) return ;
if (obj) useUnreads({ ...props, channel: obj });
@@ -60,12 +66,7 @@ const HomeSidebar = observer((props: Props) => {
});
}, [channel]);
- const channelsArr = channels
- .filter((x) => x.channel_type !== "SavedMessages")
- .map((x) => mapChannelWithUnread(x, props.unreads));
-
- const store = useData();
- channelsArr.sort((b, a) => a.timestamp.localeCompare(b.timestamp));
+ channels.sort((b, a) => a.timestamp.localeCompare(b.timestamp));
return (
@@ -132,20 +133,22 @@ const HomeSidebar = observer((props: Props) => {
})
}
/>
- {channelsArr.length === 0 && (
+ {channels.length === 0 && (
)}
- {channelsArr.map((x) => {
+ {channels.map((x) => {
let user;
- if (x.channel_type === "DirectMessage") {
- if (!x.active) return null;
+ if (x.channel.channel_type === "DirectMessage") {
+ if (!x.channel.active) return null;
- const recipient = client.channels.getRecipient(x._id);
+ const recipient = client.channels.getRecipient(
+ x.channel._id,
+ );
user = store.users.get(recipient);
if (!user) {
console.warn(
- `Skipped DM ${x._id} because user was missing.`,
+ `Skipped DM ${x.channel._id} because user was missing.`,
);
return null;
}
@@ -153,14 +156,14 @@ const HomeSidebar = observer((props: Props) => {
return (
+ active={x.channel._id === channel}
+ to={`/channel/${x.channel._id}`}>
);
diff --git a/src/components/navigation/left/ServerListSidebar.tsx b/src/components/navigation/left/ServerListSidebar.tsx
index 14f24322..bf8253f7 100644
--- a/src/components/navigation/left/ServerListSidebar.tsx
+++ b/src/components/navigation/left/ServerListSidebar.tsx
@@ -186,16 +186,18 @@ export const ServerListSidebar = observer(({ unreads, lastOpened }: Props) => {
const ctx = useForceUpdate();
const activeServers = useServers(undefined, ctx) as Servers.Server[];
- const channels = (useChannels(undefined, ctx) as Channel[]).map((x) =>
+ const channels = [...store.channels.values()].map((x) =>
mapChannelWithUnread(x, unreads),
);
- const unreadChannels = channels.filter((x) => x.unread).map((x) => x._id);
+ const unreadChannels = channels
+ .filter((x) => x.unread)
+ .map((x) => x.channel?._id);
const servers = activeServers.map((server) => {
let alertCount = 0;
for (const id of server.channels) {
- const channel = channels.find((x) => x._id === id);
+ const channel = channels.find((x) => x.channel?._id === id);
if (channel?.alertCount) {
alertCount += channel.alertCount;
}
@@ -224,8 +226,9 @@ export const ServerListSidebar = observer(({ unreads, lastOpened }: Props) => {
let alertCount = 0;
for (const x of channels) {
if (
- ((x.channel_type === "DirectMessage" && x.active) ||
- x.channel_type === "Group") &&
+ (x.channel?.channel_type === "DirectMessage"
+ ? x.channel?.active
+ : true) &&
x.unread
) {
homeUnread = "unread";
diff --git a/src/components/navigation/left/ServerSidebar.tsx b/src/components/navigation/left/ServerSidebar.tsx
index f4d53406..e21b33b7 100644
--- a/src/components/navigation/left/ServerSidebar.tsx
+++ b/src/components/navigation/left/ServerSidebar.tsx
@@ -1,3 +1,4 @@
+import { observer } from "mobx-react-lite";
import { Redirect, useParams } from "react-router";
import { Channels } from "revolt.js/dist/api/objects";
import styled from "styled-components";
@@ -8,6 +9,7 @@ import { useEffect } from "preact/hooks";
import ConditionalLink from "../../../lib/ConditionalLink";
import PaintCounter from "../../../lib/PaintCounter";
+import { useData } from "../../../mobx/State";
import { dispatch } from "../../../redux";
import { connectState } from "../../../redux/connector";
import { Unreads } from "../../../redux/reducers/unreads";
@@ -53,7 +55,7 @@ const ServerList = styled.div`
}
`;
-function ServerSidebar(props: Props) {
+const ServerSidebar = observer((props: Props) => {
const { server: server_id, channel: channel_id } =
useParams<{ server?: string; channel?: string }>();
const ctx = useForceUpdate();
@@ -61,13 +63,9 @@ function ServerSidebar(props: Props) {
const server = useServer(server_id, ctx);
if (!server) return ;
- const channels = (
- useChannels(server.channels, ctx).filter(
- (entry) => typeof entry !== "undefined",
- ) as Readonly[]
- ).map((x) => mapChannelWithUnread(x, props.unreads));
+ const store = useData();
- const channel = channels.find((x) => x?._id === channel_id);
+ const channel = channel_id ? store.channels.get(channel_id) : undefined;
if (channel_id && !channel) return ;
if (channel) useUnreads({ ...props, channel }, ctx);
@@ -85,7 +83,7 @@ function ServerSidebar(props: Props) {
const elements = [];
function addChannel(id: string) {
- const entry = channels.find((x) => x._id === id);
+ const entry = store.channels.get(id);
if (!entry) return;
const active = channel?._id === entry._id;
@@ -98,7 +96,8 @@ function ServerSidebar(props: Props) {
@@ -141,7 +140,7 @@ function ServerSidebar(props: Props) {
);
-}
+});
export default connectState(ServerSidebar, (state) => {
return {
diff --git a/src/components/navigation/left/common.ts b/src/components/navigation/left/common.ts
index f8539c21..6f60ba63 100644
--- a/src/components/navigation/left/common.ts
+++ b/src/components/navigation/left/common.ts
@@ -1,7 +1,6 @@
-import { Channel } from "revolt.js";
-
import { useLayoutEffect } from "preact/hooks";
+import { Channel } from "../../../mobx";
import { dispatch } from "../../../redux";
import { Unreads } from "../../../redux/reducers/unreads";
@@ -63,12 +62,12 @@ export function mapChannelWithUnread(channel: Channel, unreads: Unreads) {
channel.channel_type === "DirectMessage" ||
channel.channel_type === "Group"
) {
- last_message_id = channel.last_message?._id;
+ last_message_id = (channel.last_message as { _id: string })?._id;
} else if (channel.channel_type === "TextChannel") {
- last_message_id = channel.last_message;
+ last_message_id = channel.last_message as string;
} else {
return {
- ...channel,
+ channel,
unread: undefined,
alertCount: undefined,
timestamp: channel._id,
@@ -85,7 +84,7 @@ export function mapChannelWithUnread(channel: Channel, unreads: Unreads) {
unread = "mention";
} else if (
u.last_id &&
- last_message_id.localeCompare(u.last_id) > 0
+ (last_message_id as string).localeCompare(u.last_id) > 0
) {
unread = "unread";
}
@@ -95,7 +94,7 @@ export function mapChannelWithUnread(channel: Channel, unreads: Unreads) {
}
return {
- ...channel,
+ channel,
timestamp: last_message_id ?? channel._id,
unread,
alertCount,
diff --git a/src/components/navigation/right/MemberSidebar.tsx b/src/components/navigation/right/MemberSidebar.tsx
index 23d65554..8c2b8138 100644
--- a/src/components/navigation/right/MemberSidebar.tsx
+++ b/src/components/navigation/right/MemberSidebar.tsx
@@ -8,6 +8,7 @@ import { ClientboundNotification } from "revolt.js/dist/websocket/notifications"
import { Text } from "preact-i18n";
import { useContext, useEffect, useState } from "preact/hooks";
+import { Channel } from "../../../mobx";
import { useData } from "../../../mobx/State";
import { getState } from "../../../redux";
@@ -17,11 +18,7 @@ import {
ClientStatus,
StatusContext,
} from "../../../context/revoltjs/RevoltClient";
-import {
- HookContext,
- useChannel,
- useForceUpdate,
-} from "../../../context/revoltjs/hooks";
+import { HookContext } from "../../../context/revoltjs/hooks";
import CollapsibleSection from "../../common/CollapsibleSection";
import Button from "../../ui/Button";
@@ -34,27 +31,19 @@ import { GenericSidebarBase, GenericSidebarList } from "../SidebarBase";
import { UserButton } from "../items/ButtonItem";
import { ChannelDebugInfo } from "./ChannelDebugInfo";
-interface Props {
- ctx: HookContext;
-}
-
-export default function MemberSidebar(props: { channel?: Channels.Channel }) {
- const ctx = useForceUpdate();
- const { channel: cid } = useParams<{ channel: string }>();
- const channel = props.channel ?? useChannel(cid, ctx);
-
+export default function MemberSidebar({ channel }: { channel?: Channel }) {
switch (channel?.channel_type) {
case "Group":
- return ;
+ return ;
case "TextChannel":
- return ;
+ return ;
default:
return null;
}
}
export const GroupMemberSidebar = observer(
- ({ channel }: Props & { channel: Channels.GroupChannel }) => {
+ ({ channel }: { channel: Channel }) => {
const { openScreen } = useIntermediate();
const store = useData();
@@ -77,7 +66,7 @@ export const GroupMemberSidebar = observer(
voiceParticipants.sort((a, b) => a.username.localeCompare(b.username));
}*/
- members.sort((a, b) => {
+ members?.sort((a, b) => {
// ! FIXME: should probably rewrite all this code
const l =
+(
@@ -141,21 +130,21 @@ export const GroupMemberSidebar = observer(
text={
{" "}
- — {channel.recipients.length}
+ — {channel.recipients?.length ?? 0}
}
/>
}>
- {members.length === 0 && (
+ {members?.length === 0 && (
)}
- {members.map(
+ {members?.map(
(user) =>
user && (
openScreen({
id: "profile",
@@ -173,7 +162,7 @@ export const GroupMemberSidebar = observer(
);
export const ServerMemberSidebar = observer(
- ({ channel }: Props & { channel: Channels.TextChannel }) => {
+ ({ channel }: { channel: Channel }) => {
const [members, setMembers] = useState(
undefined,
);
@@ -193,7 +182,7 @@ export const ServerMemberSidebar = observer(
typeof members === "undefined"
) {
client.members
- .fetchMembers(channel.server)
+ .fetchMembers(channel.server!)
.then((members) => setMembers(members));
}
}, [status]);
diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx
index 03b41251..72e7fe2a 100644
--- a/src/context/intermediate/Intermediate.tsx
+++ b/src/context/intermediate/Intermediate.tsx
@@ -13,7 +13,7 @@ import { useContext, useEffect, useMemo, useState } from "preact/hooks";
import { internalSubscribe } from "../../lib/eventEmitter";
-import { User } from "../../mobx";
+import { Channel, User } from "../../mobx";
import { Action } from "../../components/ui/Modal";
@@ -34,15 +34,15 @@ export type Screen =
actions: Action[];
}
| ({ id: "special_prompt" } & (
- | { type: "leave_group"; target: Channels.GroupChannel }
- | { type: "close_dm"; target: Channels.DirectMessageChannel }
+ | { type: "leave_group"; target: Channel }
+ | { type: "close_dm"; target: Channel }
| { type: "leave_server"; target: Servers.Server }
| { type: "delete_server"; target: Servers.Server }
- | { type: "delete_channel"; target: Channels.TextChannel }
+ | { type: "delete_channel"; target: Channel }
| { type: "delete_message"; target: Channels.Message }
| {
type: "create_invite";
- target: Channels.TextChannel | Channels.GroupChannel;
+ target: Channel;
}
| { type: "kick_member"; target: Servers.Server; user: User }
| { type: "ban_member"; target: Servers.Server; user: User }
@@ -83,7 +83,7 @@ export type Screen =
| { id: "image_viewer"; attachment?: Attachment; embed?: EmbedImage }
| { id: "modify_account"; field: "username" | "email" | "password" }
| { id: "profile"; user_id: string }
- | { id: "channel_info"; channel_id: string }
+ | { id: "channel_info"; channel: Channel }
| { id: "pending_requests"; users: User[] }
| {
id: "user_picker";
diff --git a/src/context/intermediate/modals/Prompt.tsx b/src/context/intermediate/modals/Prompt.tsx
index 38096fc2..ea9b2764 100644
--- a/src/context/intermediate/modals/Prompt.tsx
+++ b/src/context/intermediate/modals/Prompt.tsx
@@ -9,7 +9,7 @@ import { useContext, useEffect, useState } from "preact/hooks";
import { TextReact } from "../../../lib/i18n";
-import { User } from "../../../mobx";
+import { Channel, User } from "../../../mobx";
import { useData } from "../../../mobx/State";
import Message from "../../../components/common/messaging/Message";
@@ -55,15 +55,15 @@ export function PromptModal({
}
type SpecialProps = { onClose: () => void } & (
- | { type: "leave_group"; target: Channels.GroupChannel }
- | { type: "close_dm"; target: Channels.DirectMessageChannel }
+ | { type: "leave_group"; target: Channel }
+ | { type: "close_dm"; target: Channel }
| { type: "leave_server"; target: Servers.Server }
| { type: "delete_server"; target: Servers.Server }
- | { type: "delete_channel"; target: Channels.TextChannel }
+ | { type: "delete_channel"; target: Channel }
| { type: "delete_message"; target: Channels.Message }
| {
type: "create_invite";
- target: Channels.TextChannel | Channels.GroupChannel;
+ target: Channel;
}
| { type: "kick_member"; target: Servers.Server; user: User }
| { type: "ban_member"; target: Servers.Server; user: User }
diff --git a/src/context/intermediate/popovers/ChannelInfo.tsx b/src/context/intermediate/popovers/ChannelInfo.tsx
index 18a492af..3b15cd7f 100644
--- a/src/context/intermediate/popovers/ChannelInfo.tsx
+++ b/src/context/intermediate/popovers/ChannelInfo.tsx
@@ -1,23 +1,23 @@
import { X } from "@styled-icons/boxicons-regular";
+import { observer } from "mobx-react-lite";
import styles from "./ChannelInfo.module.scss";
+import { Channel } from "../../../mobx";
+
import Modal from "../../../components/ui/Modal";
import Markdown from "../../../components/markdown/Markdown";
-import { useChannel, useForceUpdate } from "../../revoltjs/hooks";
+import { useClient } from "../../revoltjs/RevoltClient";
+import { useForceUpdate } from "../../revoltjs/hooks";
import { getChannelName } from "../../revoltjs/util";
interface Props {
- channel_id: string;
+ channel: Channel;
onClose: () => void;
}
-export function ChannelInfo({ channel_id, onClose }: Props) {
- const ctx = useForceUpdate();
- const channel = useChannel(channel_id, ctx);
- if (!channel) return null;
-
+export const ChannelInfo = observer(({ channel, onClose }: Props) => {
if (
channel.channel_type === "DirectMessage" ||
channel.channel_type === "SavedMessages"
@@ -26,19 +26,20 @@ export function ChannelInfo({ channel_id, onClose }: Props) {
return null;
}
+ const client = useClient();
return (
-
{getChannelName(ctx.client, channel, true)}
+
{getChannelName(client, channel, true)}
-
+
);
-}
+});
diff --git a/src/context/intermediate/popovers/UserProfile.tsx b/src/context/intermediate/popovers/UserProfile.tsx
index 0e0105d9..b8c4e2d1 100644
--- a/src/context/intermediate/popovers/UserProfile.tsx
+++ b/src/context/intermediate/popovers/UserProfile.tsx
@@ -27,11 +27,7 @@ import {
StatusContext,
useClient,
} from "../../revoltjs/RevoltClient";
-import {
- useChannels,
- useForceUpdate,
- useUserPermission,
-} from "../../revoltjs/hooks";
+import { useForceUpdate, useUserPermission } from "../../revoltjs/hooks";
import { useIntermediate } from "../Intermediate";
interface Props {
@@ -65,7 +61,6 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
const [tab, setTab] = useState("profile");
const ctx = useForceUpdate();
- const channels = useChannels(undefined, ctx);
const permissions = useUserPermission(client.user!._id, ctx);
const store = useData();
@@ -77,6 +72,12 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
const user = store.users.get(user_id)!;
const users = mutual?.users.map((id) => store.users.get(id));
+ const mutualGroups = [...store.channels.values()].filter(
+ (channel) =>
+ channel?.channel_type === "Group" &&
+ channel.recipients!.includes(user_id),
+ );
+
useLayoutEffect(() => {
if (!user_id) return;
if (typeof profile !== "undefined") setProfile(undefined);
@@ -111,12 +112,6 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
}
}, [profile, status]);
- const mutualGroups = channels.filter(
- (channel) =>
- channel?.channel_type === "Group" &&
- channel.recipients.includes(user_id),
- );
-
const backgroundURL =
profile &&
client.users.getBackgroundURL(profile, { width: 1000 }, true);
diff --git a/src/context/revoltjs/hooks.ts b/src/context/revoltjs/hooks.ts
index e5ea6876..99823c58 100644
--- a/src/context/revoltjs/hooks.ts
+++ b/src/context/revoltjs/hooks.ts
@@ -77,13 +77,6 @@ function useObject(
: map.toArray();
}
-export function useChannel(id?: string, context?: HookContext) {
- if (typeof id === "undefined") return;
- return useObject("channels", id, context) as
- | Readonly
- | undefined;
-}
-
export function useChannels(ids?: string[], context?: HookContext) {
return useObject("channels", ids, context) as (
| Readonly
diff --git a/src/context/revoltjs/util.tsx b/src/context/revoltjs/util.tsx
index 98489e88..439dbf62 100644
--- a/src/context/revoltjs/util.tsx
+++ b/src/context/revoltjs/util.tsx
@@ -1,8 +1,10 @@
import { Client } from "revolt.js";
-import { Channel, Message, User } from "revolt.js/dist/api/objects";
+import { Message } from "revolt.js/dist/api/objects";
import { Text } from "preact-i18n";
+import { Channel } from "../../mobx";
+
import { Children } from "../../types/Preact";
export function takeError(error: any): string {
diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx
index 9cca0a20..d1e3bbe1 100644
--- a/src/lib/ContextMenus.tsx
+++ b/src/lib/ContextMenus.tsx
@@ -34,7 +34,7 @@ import {
import { Text } from "preact-i18n";
import { useContext } from "preact/hooks";
-import { User } from "../mobx";
+import { Channel, User } from "../mobx";
import { useData } from "../mobx/State";
import { dispatch } from "../redux";
import { connectState } from "../redux/connector";
@@ -53,7 +53,6 @@ import {
useClient,
} from "../context/revoltjs/RevoltClient";
import {
- useChannel,
useChannelPermission,
useForceUpdate,
useServer,
@@ -86,7 +85,7 @@ type Action =
| { action: "copy_id"; id: string }
| { action: "copy_selection" }
| { action: "copy_text"; content: string }
- | { action: "mark_as_read"; channel: Channels.Channel }
+ | { action: "mark_as_read"; channel: Channel }
| { action: "retry_message"; message: QueuedMessage }
| { action: "cancel_message"; message: QueuedMessage }
| { action: "mention"; user: string }
@@ -115,20 +114,17 @@ type Action =
| { action: "create_channel"; target: Servers.Server }
| {
action: "create_invite";
- target:
- | Channels.GroupChannel
- | Channels.TextChannel
- | Channels.VoiceChannel;
+ target: Channel;
}
- | { action: "leave_group"; target: Channels.GroupChannel }
+ | { action: "leave_group"; target: Channel }
| {
action: "delete_channel";
- target: Channels.TextChannel | Channels.VoiceChannel;
+ target: Channel;
}
- | { action: "close_dm"; target: Channels.DirectMessageChannel }
+ | { action: "close_dm"; target: Channel }
| { action: "leave_server"; target: Servers.Server }
| { action: "delete_server"; target: Servers.Server }
- | { action: "open_notification_options"; channel: Channels.Channel }
+ | { action: "open_notification_options"; channel: Channel }
| { action: "open_settings" }
| { action: "open_channel_settings"; id: string }
| { action: "open_server_settings"; id: string }
@@ -172,9 +168,10 @@ function ContextMenus(props: Props) {
return;
const message =
- data.channel.channel_type === "TextChannel"
+ typeof data.channel.last_message === "string"
? data.channel.last_message
- : data.channel.last_message._id;
+ : data.channel.last_message!._id;
+
dispatch({
type: "UNREADS_MARK_READ",
channel: data.channel._id,
@@ -529,8 +526,10 @@ function ContextMenus(props: Props) {
pushDivider();
}
- const channel = useChannel(cid, forceUpdate);
- const contextualChannel = useChannel(cxid, forceUpdate);
+ const channel = cid ? store.channels.get(cid) : undefined;
+ const contextualChannel = cxid
+ ? store.channels.get(cxid)
+ : undefined;
const targetChannel = channel ?? contextualChannel;
const user = uid ? store.users.get(uid) : undefined;
@@ -541,7 +540,7 @@ function ContextMenus(props: Props) {
? targetChannel
: undefined;
const server = useServer(
- serverChannel ? serverChannel.server : sid,
+ serverChannel ? serverChannel.server! : sid,
forceUpdate,
);
@@ -551,7 +550,10 @@ function ContextMenus(props: Props) {
const serverPermissions = server
? useServerPermission(server._id, forceUpdate)
: serverChannel
- ? useServerPermission(serverChannel.server, forceUpdate)
+ ? useServerPermission(
+ serverChannel.server!,
+ forceUpdate,
+ )
: 0;
const userPermissions = user
? useUserPermission(user._id, forceUpdate)
@@ -819,7 +821,7 @@ function ContextMenus(props: Props) {
generateAction(
{
action: "open_server_channel_settings",
- server: channel.server,
+ server: channel.server!,
id: channel._id,
},
"open_channel_settings",
diff --git a/src/mobx/index.ts b/src/mobx/index.ts
index fdc1ae4c..700c5b2e 100644
--- a/src/mobx/index.ts
+++ b/src/mobx/index.ts
@@ -73,7 +73,7 @@ export class User {
export class Channel {
_id: string;
- type: Channels.Channel["channel_type"];
+ channel_type: Channels.Channel["channel_type"];
// Direct Message
active: Nullable = null;
@@ -98,7 +98,7 @@ export class Channel {
constructor(data: Channels.Channel) {
this._id = data._id;
- this.type = data.channel_type;
+ this.channel_type = data.channel_type;
switch (data.channel_type) {
case "DirectMessage": {
diff --git a/src/pages/channels/Channel.tsx b/src/pages/channels/Channel.tsx
index 3cd4b2bb..9f40f8ea 100644
--- a/src/pages/channels/Channel.tsx
+++ b/src/pages/channels/Channel.tsx
@@ -1,3 +1,4 @@
+import { observer } from "mobx-react-lite";
import { useParams, useHistory } from "react-router-dom";
import { Channels } from "revolt.js/dist/api/objects";
import styled from "styled-components";
@@ -6,10 +7,10 @@ import { useState } from "preact/hooks";
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
+import { Channel as MobXChannel } from "../../mobx";
+import { useData } from "../../mobx/State";
import { dispatch, getState } from "../../redux";
-import { useChannel, useForceUpdate } from "../../context/revoltjs/hooks";
-
import AgeGate from "../../components/common/AgeGate";
import MessageBox from "../../components/common/messaging/MessageBox";
import JumpToBottom from "../../components/common/messaging/bars/JumpToBottom";
@@ -36,19 +37,19 @@ const ChannelContent = styled.div`
`;
export function Channel({ id }: { id: string }) {
- const ctx = useForceUpdate();
- const channel = useChannel(id, ctx);
-
+ const store = useData();
+ const channel = store.channels.get(id);
if (!channel) return null;
if (channel.channel_type === "VoiceChannel") {
return ;
}
+
return ;
}
const MEMBERS_SIDEBAR_KEY = "sidebar_members";
-function TextChannel({ channel }: { channel: Channels.Channel }) {
+const TextChannel = observer(({ channel }: { channel: MobXChannel }) => {
const [showMembers, setMembers] = useState(
getState().sectionToggle[MEMBERS_SIDEBAR_KEY] ?? true,
);
@@ -61,7 +62,9 @@ function TextChannel({ channel }: { channel: Channels.Channel }) {
gated={
(channel.channel_type === "TextChannel" ||
channel.channel_type === "Group") &&
- channel.name.includes("nsfw")
+ channel.name?.includes("nsfw")
+ ? true
+ : false
}>
);
-}
+});
-function VoiceChannel({ channel }: { channel: Channels.Channel }) {
+function VoiceChannel({ channel }: { channel: MobXChannel }) {
return (
<>
diff --git a/src/pages/channels/ChannelHeader.tsx b/src/pages/channels/ChannelHeader.tsx
index 69e44e1c..f14ac512 100644
--- a/src/pages/channels/ChannelHeader.tsx
+++ b/src/pages/channels/ChannelHeader.tsx
@@ -2,14 +2,13 @@ import { At, Hash, Menu } from "@styled-icons/boxicons-regular";
import { Notepad, Group } from "@styled-icons/boxicons-solid";
import { observable } from "mobx";
import { observer } from "mobx-react-lite";
-import { Channel } from "revolt.js";
import styled from "styled-components";
import { useContext } from "preact/hooks";
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
-import { User } from "../../mobx";
+import { Channel, User } from "../../mobx";
import { useData } from "../../mobx/State";
import { useIntermediate } from "../../context/intermediate/Intermediate";
@@ -131,7 +130,7 @@ export default observer(({ channel, toggleSidebar }: ChannelHeaderProps) => {
onClick={() =>
openScreen({
id: "channel_info",
- channel_id: channel._id,
+ channel,
})
}>
openScreen({
id: "user_picker",
- omit: channel.recipients,
+ omit: channel.recipients!,
callback: async (users) => {
for (const user of users) {
await client.channels.addMember(
diff --git a/src/pages/channels/messaging/ConversationStart.tsx b/src/pages/channels/messaging/ConversationStart.tsx
index acaef3c7..447f24f0 100644
--- a/src/pages/channels/messaging/ConversationStart.tsx
+++ b/src/pages/channels/messaging/ConversationStart.tsx
@@ -1,8 +1,11 @@
+import { observer } from "mobx-react-lite";
import styled from "styled-components";
import { Text } from "preact-i18n";
-import { useChannel, useForceUpdate } from "../../../context/revoltjs/hooks";
+import { useData } from "../../../mobx/State";
+
+import { useClient } from "../../../context/revoltjs/RevoltClient";
import { getChannelName } from "../../../context/revoltjs/util";
const StartBase = styled.div`
@@ -24,17 +27,18 @@ interface Props {
id: string;
}
-export default function ConversationStart({ id }: Props) {
- const ctx = useForceUpdate();
- const channel = useChannel(id, ctx);
+export default observer(({ id }: Props) => {
+ const store = useData();
+ const client = useClient();
+ const channel = store.channels.get(id);
if (!channel) return null;
return (
- {getChannelName(ctx.client, channel, true)}
+ {getChannelName(client, channel, true)}
);
-}
+});
diff --git a/src/pages/settings/ChannelSettings.tsx b/src/pages/settings/ChannelSettings.tsx
index 4e12183d..79015adb 100644
--- a/src/pages/settings/ChannelSettings.tsx
+++ b/src/pages/settings/ChannelSettings.tsx
@@ -3,7 +3,9 @@ import { Route, useHistory, useParams } from "react-router-dom";
import { Text } from "preact-i18n";
-import { useChannel, useForceUpdate } from "../../context/revoltjs/hooks";
+import { useData } from "../../mobx/State";
+
+import { useClient } from "../../context/revoltjs/RevoltClient";
import { getChannelName } from "../../context/revoltjs/util";
import Category from "../../components/ui/Category";
@@ -14,8 +16,10 @@ import Permissions from "./channel/Permissions";
export default function ChannelSettings() {
const { channel: cid } = useParams<{ channel: string }>();
- const ctx = useForceUpdate();
- const channel = useChannel(cid, ctx);
+
+ const store = useData();
+ const client = useClient();
+ const channel = store.channels.get(cid);
if (!channel) return null;
if (
channel.channel_type === "SavedMessages" ||
@@ -49,7 +53,7 @@ export default function ChannelSettings() {
category: (
),
id: "overview",
diff --git a/src/pages/settings/channel/Overview.tsx b/src/pages/settings/channel/Overview.tsx
index b4a895e9..cf1da074 100644
--- a/src/pages/settings/channel/Overview.tsx
+++ b/src/pages/settings/channel/Overview.tsx
@@ -1,3 +1,4 @@
+import { observer } from "mobx-react-lite";
import { Channels } from "revolt.js/dist/api/objects";
import styled, { css } from "styled-components";
@@ -6,6 +7,8 @@ import { useContext, useEffect, useState } from "preact/hooks";
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
+import { Channel } from "../../../mobx";
+
import { FileUploader } from "../../../context/revoltjs/FileUploads";
import { AppContext } from "../../../context/revoltjs/RevoltClient";
@@ -13,10 +16,7 @@ import Button from "../../../components/ui/Button";
import InputBox from "../../../components/ui/InputBox";
interface Props {
- channel:
- | Channels.GroupChannel
- | Channels.TextChannel
- | Channels.VoiceChannel;
+ channel: Channel;
}
const Row = styled.div`
@@ -32,13 +32,13 @@ const Row = styled.div`
}
`;
-export default function Overview({ channel }: Props) {
+export default observer(({ channel }: Props) => {
const client = useContext(AppContext);
- const [name, setName] = useState(channel.name);
+ const [name, setName] = useState(channel.name ?? undefined);
const [description, setDescription] = useState(channel.description ?? "");
- useEffect(() => setName(channel.name), [channel.name]);
+ useEffect(() => setName(channel.name ?? undefined), [channel.name]);
useEffect(
() => setDescription(channel.description ?? ""),
[channel.description],
@@ -127,4 +127,4 @@ export default function Overview({ channel }: Props) {
);
-}
+});
diff --git a/src/pages/settings/channel/Permissions.tsx b/src/pages/settings/channel/Permissions.tsx
index 963694ae..c7fc2352 100644
--- a/src/pages/settings/channel/Permissions.tsx
+++ b/src/pages/settings/channel/Permissions.tsx
@@ -1,8 +1,11 @@
+import { observer } from "mobx-react-lite";
import { Channels } from "revolt.js/dist/api/objects";
import { ChannelPermission } from "revolt.js/dist/api/permissions";
import { useContext, useEffect, useState } from "preact/hooks";
+import { Channel } from "../../../mobx";
+
import { AppContext } from "../../../context/revoltjs/RevoltClient";
import { useServer } from "../../../context/revoltjs/hooks";
@@ -21,21 +24,18 @@ const DEFAULT_PERMISSION_DM =
ChannelPermission.UploadFiles;
interface Props {
- channel:
- | Channels.GroupChannel
- | Channels.TextChannel
- | Channels.VoiceChannel;
+ channel: Channel;
}
// ! FIXME: bad code :)
-export default function Permissions({ channel }: Props) {
+export default observer(({ channel }: Props) => {
const [selected, setSelected] = useState("default");
const client = useContext(AppContext);
type R = { name: string; permissions: number };
const roles: { [key: string]: R } = {};
if (channel.channel_type !== "Group") {
- const server = useServer(channel.server);
+ const server = useServer(channel.server!);
const a = server?.roles ?? {};
for (const b of Object.keys(a)) {
roles[b] = {
@@ -110,4 +110,4 @@ export default function Permissions({ channel }: Props) {
);
-}
+});
diff --git a/src/pages/settings/server/Categories.tsx b/src/pages/settings/server/Categories.tsx
index 8f35bcf1..6e75222c 100644
--- a/src/pages/settings/server/Categories.tsx
+++ b/src/pages/settings/server/Categories.tsx
@@ -1,5 +1,6 @@
import { XCircle } from "@styled-icons/boxicons-regular";
import isEqual from "lodash.isequal";
+import { observer } from "mobx-react-lite";
import { Channels, Servers, Users } from "revolt.js/dist/api/objects";
import { Route } from "revolt.js/dist/api/routes";
import { ulid } from "ulid";
@@ -8,8 +9,9 @@ import styles from "./Panes.module.scss";
import { Text } from "preact-i18n";
import { useContext, useEffect, useState } from "preact/hooks";
+import { useData } from "../../../mobx/State";
+
import { AppContext } from "../../../context/revoltjs/RevoltClient";
-import { useChannels } from "../../../context/revoltjs/hooks";
import ChannelIcon from "../../../components/common/ChannelIcon";
import UserIcon from "../../../components/common/user/UserIcon";
@@ -25,12 +27,12 @@ interface Props {
}
// ! FIXME: really bad code
-export function Categories({ server }: Props) {
+export const Categories = observer(({ server }: Props) => {
const client = useContext(AppContext);
- const channels = useChannels(server.channels) as (
- | Channels.TextChannel
- | Channels.VoiceChannel
- )[];
+ const store = useData();
+ const channels = server.channels
+ .map((id) => store.channels.get(id)!)
+ .filter((x) => typeof x !== "undefined");
const [cats, setCats] = useState(
server.categories ?? [],
@@ -150,4 +152,4 @@ export function Categories({ server }: Props) {
})}
);
-}
+});
diff --git a/src/pages/settings/server/Invites.tsx b/src/pages/settings/server/Invites.tsx
index 1708d851..6e072447 100644
--- a/src/pages/settings/server/Invites.tsx
+++ b/src/pages/settings/server/Invites.tsx
@@ -9,7 +9,6 @@ import { useEffect, useState } from "preact/hooks";
import { useData } from "../../../mobx/State";
import { useClient } from "../../../context/revoltjs/RevoltClient";
-import { useChannels, useForceUpdate } from "../../../context/revoltjs/hooks";
import { getChannelName } from "../../../context/revoltjs/util";
import UserIcon from "../../../components/common/user/UserIcon";
@@ -26,14 +25,15 @@ export const Invites = observer(({ server }: Props) => {
InvitesNS.ServerInvite[] | undefined
>(undefined);
- const ctx = useForceUpdate();
- const channels = useChannels(invites?.map((x) => x.channel) ?? [], ctx);
-
const store = useData();
+ const client = useClient();
const users = invites?.map((invite) => store.users.get(invite.creator));
+ const channels = invites?.map((invite) =>
+ store.channels.get(invite.channel),
+ );
useEffect(() => {
- ctx.client.servers
+ client.servers
.fetchInvites(server._id)
.then((invites) => setInvites(invites));
}, []);
@@ -57,7 +57,7 @@ export const Invites = observer(({ server }: Props) => {
{typeof invites === "undefined" && }
{invites?.map((invite, index) => {
const creator = users![index];
- const channel = channels.find((x) => x?._id === invite.channel);
+ const channel = channels![index];
return (
{
{channel && creator
- ? getChannelName(ctx.client, channel, true)
+ ? getChannelName(client, channel, true)
: "#??"}
{
setDelete([...deleting, invite._id]);
- await ctx.client.deleteInvite(invite._id);
+ await client.deleteInvite(invite._id);
setInvites(
invites?.filter(
diff --git a/src/pages/settings/server/Overview.tsx b/src/pages/settings/server/Overview.tsx
index e92e952d..ba25104c 100644
--- a/src/pages/settings/server/Overview.tsx
+++ b/src/pages/settings/server/Overview.tsx
@@ -1,4 +1,5 @@
import isEqual from "lodash.isequal";
+import { observer } from "mobx-react-lite";
import { Servers, Server } from "revolt.js/dist/api/objects";
import styles from "./Panes.module.scss";
@@ -7,6 +8,8 @@ import { useContext, useEffect, useState } from "preact/hooks";
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
+import { useData } from "../../../mobx/State";
+
import { FileUploader } from "../../../context/revoltjs/FileUploads";
import { AppContext } from "../../../context/revoltjs/RevoltClient";
import { getChannelName } from "../../../context/revoltjs/util";
@@ -19,8 +22,9 @@ interface Props {
server: Servers.Server;
}
-export function Overview({ server }: Props) {
+export const Overview = observer(({ server }: Props) => {
const client = useContext(AppContext);
+ const store = useData();
const [name, setName] = useState(server.name);
const [description, setDescription] = useState(server.description ?? "");
@@ -170,15 +174,14 @@ export function Overview({ server }: Props) {
- {server.channels.map((id) => {
- const channel = client.channels.get(id);
- if (!channel) return null;
- return (
-
- );
- })}
+ ))}
))}
@@ -190,4 +193,4 @@ export function Overview({ server }: Props) {
);
-}
+});