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";