diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx
index a7a92d36..54099c66 100644
--- a/src/components/common/messaging/Message.tsx
+++ b/src/components/common/messaging/Message.tsx
@@ -9,7 +9,6 @@ import { QueuedMessage } from "../../../redux/reducers/queue";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import { AppContext } from "../../../context/revoltjs/RevoltClient";
-import { useUser } from "../../../context/revoltjs/hooks";
import { MessageObject } from "../../../context/revoltjs/util";
import Overline from "../../ui/Overline";
diff --git a/src/components/common/messaging/SystemMessage.tsx b/src/components/common/messaging/SystemMessage.tsx
index 59051baf..19c5325c 100644
--- a/src/components/common/messaging/SystemMessage.tsx
+++ b/src/components/common/messaging/SystemMessage.tsx
@@ -8,7 +8,6 @@ import { TextReact } from "../../../lib/i18n";
import { User } from "../../../mobx";
import { useData } from "../../../mobx/State";
-import { useForceUpdate, useUser } from "../../../context/revoltjs/hooks";
import { MessageObject } from "../../../context/revoltjs/util";
import UserShort from "../user/UserShort";
diff --git a/src/components/common/messaging/attachments/MessageReply.tsx b/src/components/common/messaging/attachments/MessageReply.tsx
index b849e3db..dcf35178 100644
--- a/src/components/common/messaging/attachments/MessageReply.tsx
+++ b/src/components/common/messaging/attachments/MessageReply.tsx
@@ -13,7 +13,7 @@ import { useRenderState } from "../../../../lib/renderer/Singleton";
import { useData } from "../../../../mobx/State";
-import { useForceUpdate, useUser } from "../../../../context/revoltjs/hooks";
+import { useClient } from "../../../../context/revoltjs/RevoltClient";
import { mapMessage, MessageObject } from "../../../../context/revoltjs/util";
import Markdown from "../../../markdown/Markdown";
@@ -124,7 +124,7 @@ export const ReplyBase = styled.div<{
`;
export const MessageReply = observer(({ index, channel, id }: Props) => {
- const ctx = useForceUpdate();
+ const client = useClient();
const view = useRenderState(channel);
if (view?.type !== "RENDER") return null;
@@ -138,7 +138,7 @@ export const MessageReply = observer(({ index, channel, id }: Props) => {
if (m) {
setMessage(m);
} else {
- ctx.client.channels
+ client.channels
.fetchMessage(channel, id)
.then((m) => setMessage(mapMessage(m)));
}
@@ -178,8 +178,7 @@ export const MessageReply = observer(({ index, channel, id }: Props) => {
{
- const obj =
- ctx.client.channels.get(channel);
+ const obj = client.channels.get(channel);
if (obj?.channel_type === "TextChannel") {
history.push(
`/server/${obj.server}/channel/${obj._id}/${message._id}`,
diff --git a/src/components/common/messaging/bars/ReplyBar.tsx b/src/components/common/messaging/bars/ReplyBar.tsx
index 5de69066..a6b282d0 100644
--- a/src/components/common/messaging/bars/ReplyBar.tsx
+++ b/src/components/common/messaging/bars/ReplyBar.tsx
@@ -17,8 +17,6 @@ import { useRenderState } from "../../../../lib/renderer/Singleton";
import { useData } from "../../../../mobx/State";
import { Reply } from "../../../../redux/reducers/queue";
-import { useUsers } from "../../../../context/revoltjs/hooks";
-
import IconButton from "../../../ui/IconButton";
import Markdown from "../../../markdown/Markdown";
diff --git a/src/components/common/messaging/bars/TypingIndicator.tsx b/src/components/common/messaging/bars/TypingIndicator.tsx
index 8c2fe0be..816b7fc5 100644
--- a/src/components/common/messaging/bars/TypingIndicator.tsx
+++ b/src/components/common/messaging/bars/TypingIndicator.tsx
@@ -15,7 +15,6 @@ import {
AppContext,
useClient,
} from "../../../../context/revoltjs/RevoltClient";
-import { useUsers } from "../../../../context/revoltjs/hooks";
import { Username } from "../../user/UserShort";
diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx
index b1203138..e22d35bf 100644
--- a/src/components/navigation/left/HomeSidebar.tsx
+++ b/src/components/navigation/left/HomeSidebar.tsx
@@ -23,11 +23,7 @@ import { Unreads } from "../../../redux/reducers/unreads";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import { AppContext } from "../../../context/revoltjs/RevoltClient";
-import {
- useDMs,
- useForceUpdate,
- useUsers,
-} from "../../../context/revoltjs/hooks";
+import { useDMs, useForceUpdate } from "../../../context/revoltjs/hooks";
import Category from "../../ui/Category";
import placeholderSVG from "../items/placeholder.svg";
diff --git a/src/components/navigation/right/MemberSidebar.tsx b/src/components/navigation/right/MemberSidebar.tsx
index 8beac5b8..23d65554 100644
--- a/src/components/navigation/right/MemberSidebar.tsx
+++ b/src/components/navigation/right/MemberSidebar.tsx
@@ -21,7 +21,6 @@ import {
HookContext,
useChannel,
useForceUpdate,
- useUsers,
} from "../../../context/revoltjs/hooks";
import CollapsibleSection from "../../common/CollapsibleSection";
diff --git a/src/context/intermediate/popovers/UserProfile.tsx b/src/context/intermediate/popovers/UserProfile.tsx
index c321b9f4..0e0105d9 100644
--- a/src/context/intermediate/popovers/UserProfile.tsx
+++ b/src/context/intermediate/popovers/UserProfile.tsx
@@ -31,7 +31,6 @@ import {
useChannels,
useForceUpdate,
useUserPermission,
- useUsers,
} from "../../revoltjs/hooks";
import { useIntermediate } from "../Intermediate";
diff --git a/src/context/revoltjs/hooks.ts b/src/context/revoltjs/hooks.ts
index e693ccf7..e5ea6876 100644
--- a/src/context/revoltjs/hooks.ts
+++ b/src/context/revoltjs/hooks.ts
@@ -77,18 +77,6 @@ function useObject(
: map.toArray();
}
-export function useUser(id?: string, context?: HookContext) {
- if (typeof id === "undefined") return;
- return useObject("users", id, context) as Readonly
| undefined;
-}
-
-export function useUsers(ids?: string[], context?: HookContext) {
- return useObject("users", ids, context) as (
- | Readonly
- | undefined
- )[];
-}
-
export function useChannel(id?: string, context?: HookContext) {
if (typeof id === "undefined") return;
return useObject("channels", id, context) as
diff --git a/src/mobx/index.ts b/src/mobx/index.ts
index d878cd1f..fdc1ae4c 100644
--- a/src/mobx/index.ts
+++ b/src/mobx/index.ts
@@ -9,8 +9,8 @@ import {
action,
extendObservable,
} from "mobx";
-import { Attachment, Users } from "revolt.js/dist/api/objects";
-import { RemoveUserField } from "revolt.js/dist/api/routes";
+import { Attachment, Channels, Users } from "revolt.js/dist/api/objects";
+import { RemoveChannelField, RemoveUserField } from "revolt.js/dist/api/routes";
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
type Nullable = T | null;
@@ -42,7 +42,7 @@ export class User {
}
@action update(data: Partial, clear?: RemoveUserField) {
- const apply = (key: keyof Users.User) => {
+ const apply = (key: string) => {
// This code has been tested.
// @ts-expect-error
if (data[key] && !isEqual(this[key], data[key])) {
@@ -62,6 +62,7 @@ export class User {
}
}
+ apply("username");
apply("avatar");
apply("badges");
apply("status");
@@ -70,8 +71,110 @@ export class User {
}
}
+export class Channel {
+ _id: string;
+ type: Channels.Channel["channel_type"];
+
+ // Direct Message
+ active: Nullable = null;
+
+ // Group
+ owner: Nullable = null;
+
+ // Server
+ server: Nullable = null;
+
+ // Permissions
+ permissions: Nullable = null;
+ default_permissions: Nullable = null;
+ role_permissions: Nullable<{ [key: string]: number }> = null;
+
+ // Common
+ name: Nullable = null;
+ icon: Nullable = null;
+ description: Nullable = null;
+ recipients: Nullable = null;
+ last_message: Nullable = null;
+
+ constructor(data: Channels.Channel) {
+ this._id = data._id;
+ this.type = data.channel_type;
+
+ switch (data.channel_type) {
+ case "DirectMessage": {
+ this.active = toNullable(data.active);
+ this.recipients = toNullable(data.recipients);
+ this.last_message = toNullable(data.last_message);
+ break;
+ }
+ case "Group": {
+ this.recipients = toNullable(data.recipients);
+ this.name = toNullable(data.name);
+ this.owner = toNullable(data.owner);
+ this.description = toNullable(data.description);
+ this.last_message = toNullable(data.last_message);
+ this.icon = toNullable(data.icon);
+ this.permissions = toNullable(data.permissions);
+ break;
+ }
+ case "TextChannel":
+ case "VoiceChannel": {
+ this.server = toNullable(data.server);
+ this.name = toNullable(data.name);
+ this.description = toNullable(data.description);
+ this.icon = toNullable(data.icon);
+ this.default_permissions = toNullable(data.default_permissions);
+ this.role_permissions = toNullable(data.role_permissions);
+
+ if (data.channel_type === "TextChannel") {
+ this.last_message = toNullable(data.last_message);
+ }
+
+ break;
+ }
+ }
+
+ makeAutoObservable(this);
+ }
+
+ @action update(
+ data: Partial,
+ clear?: RemoveChannelField,
+ ) {
+ const apply = (key: string) => {
+ // This code has been tested.
+ // @ts-expect-error
+ if (data[key] && !isEqual(this[key], data[key])) {
+ // @ts-expect-error
+ this[key] = data[key];
+ }
+ };
+
+ switch (clear) {
+ case "Description":
+ this.description = null;
+ break;
+ case "Icon":
+ this.icon = null;
+ break;
+ }
+
+ apply("active");
+ apply("owner");
+ apply("permissions");
+ apply("default_permissions");
+ apply("role_permissions");
+ apply("name");
+ apply("icon");
+ apply("description");
+ apply("recipients");
+ apply("last_message");
+ }
+}
+
export class DataStore {
@observable users = new Map();
+ @observable channels = new Map();
constructor() {
makeAutoObservable(this);
@@ -84,6 +187,11 @@ export class DataStore {
for (let user of packet.users) {
this.users.set(user._id, new User(user));
}
+
+ for (let channel of packet.channels) {
+ this.channels.set(channel._id, new Channel(channel));
+ }
+
break;
}
case "UserUpdate": {
diff --git a/src/pages/Open.tsx b/src/pages/Open.tsx
index 6a36e246..ddeb98b6 100644
--- a/src/pages/Open.tsx
+++ b/src/pages/Open.tsx
@@ -9,11 +9,6 @@ import {
ClientStatus,
StatusContext,
} from "../context/revoltjs/RevoltClient";
-import {
- useChannels,
- useForceUpdate,
- useUser,
-} from "../context/revoltjs/hooks";
import Header from "../components/ui/Header";
@@ -32,13 +27,9 @@ export default function Open() {
);
}
- const ctx = useForceUpdate();
- const channels = useChannels(undefined, ctx);
- const user = useUser(id, ctx);
-
useEffect(() => {
if (id === "saved") {
- for (const channel of channels) {
+ for (const channel of client.channels.toArray()) {
if (channel?.channel_type === "SavedMessages") {
history.push(`/channel/${channel._id}`);
return;
@@ -53,12 +44,15 @@ export default function Open() {
return;
}
+ let user = client.users.get(id);
if (user) {
- const channel: string | undefined = channels.find(
- (channel) =>
- channel?.channel_type === "DirectMessage" &&
- channel.recipients.includes(id),
- )?._id;
+ const channel: string | undefined = client.channels
+ .toArray()
+ .find(
+ (channel) =>
+ channel?.channel_type === "DirectMessage" &&
+ channel.recipients.includes(id),
+ )?._id;
if (channel) {
history.push(`/channel/${channel}`);
diff --git a/src/pages/settings/server/Invites.tsx b/src/pages/settings/server/Invites.tsx
index e77bf3b5..1708d851 100644
--- a/src/pages/settings/server/Invites.tsx
+++ b/src/pages/settings/server/Invites.tsx
@@ -9,11 +9,7 @@ import { useEffect, useState } from "preact/hooks";
import { useData } from "../../../mobx/State";
import { useClient } from "../../../context/revoltjs/RevoltClient";
-import {
- useChannels,
- useForceUpdate,
- useUsers,
-} from "../../../context/revoltjs/hooks";
+import { useChannels, useForceUpdate } from "../../../context/revoltjs/hooks";
import { getChannelName } from "../../../context/revoltjs/util";
import UserIcon from "../../../components/common/user/UserIcon";
@@ -34,7 +30,6 @@ export const Invites = observer(({ server }: Props) => {
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));
useEffect(() => {
diff --git a/src/pages/settings/server/Members.tsx b/src/pages/settings/server/Members.tsx
index 24528cba..69f3aa97 100644
--- a/src/pages/settings/server/Members.tsx
+++ b/src/pages/settings/server/Members.tsx
@@ -10,7 +10,6 @@ import { useEffect, useState } from "preact/hooks";
import { useData } from "../../../mobx/State";
import { useClient } from "../../../context/revoltjs/RevoltClient";
-import { useForceUpdate, useUsers } from "../../../context/revoltjs/hooks";
import UserIcon from "../../../components/common/user/UserIcon";
import Button from "../../../components/ui/Button";