mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-22 07:00:58 -05:00
Start migration to revolt.js@5.0.0.
200 error milestone
This commit is contained in:
parent
564c1d8494
commit
3184269ba4
32 changed files with 215 additions and 834 deletions
|
@ -22,7 +22,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"preact": "^10.5.13"
|
"preact": "^10.5.13",
|
||||||
|
"revolt-api": "0.5.1-alpha.10-patch.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fontsource/atkinson-hyperlegible": "^4.4.5",
|
"@fontsource/atkinson-hyperlegible": "^4.4.5",
|
||||||
|
@ -96,7 +97,7 @@
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scroll": "^1.8.2",
|
"react-scroll": "^1.8.2",
|
||||||
"redux": "^4.1.0",
|
"redux": "^4.1.0",
|
||||||
"revolt.js": "4.4.0-alpha.0",
|
"revolt.js": "5.0.0-alpha.5",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sass": "^1.35.1",
|
"sass": "^1.35.1",
|
||||||
"shade-blend-color": "^1.0.0",
|
"shade-blend-color": "^1.0.0",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom";
|
||||||
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
|
|
||||||
import { Channel } from "../../mobx";
|
|
||||||
import { dispatch, getState } from "../../redux";
|
import { dispatch, getState } from "../../redux";
|
||||||
|
|
||||||
import Button from "../ui/Button";
|
import Button from "../ui/Button";
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import { useStore } from "react-redux";
|
import { useStore } from "react-redux";
|
||||||
import { SYSTEM_USER_ID } from "revolt.js";
|
import { SYSTEM_USER_ID } from "revolt.js";
|
||||||
import { Channels } from "revolt.js/dist/api/objects";
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
import { User } from "revolt.js/dist/maps/Users";
|
||||||
import styled, { css } from "styled-components";
|
import styled, { css } from "styled-components";
|
||||||
|
|
||||||
import { StateUpdater, useState } from "preact/hooks";
|
import { StateUpdater, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { Channel, User } from "../../mobx";
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
|
|
||||||
import { useClient } from "../../context/revoltjs/RevoltClient";
|
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
import { emojiDictionary } from "../../assets/emojis";
|
import { emojiDictionary } from "../../assets/emojis";
|
||||||
|
@ -57,7 +55,6 @@ export function useAutoComplete(
|
||||||
const [state, setState] = useState<AutoCompleteState>({ type: "none" });
|
const [state, setState] = useState<AutoCompleteState>({ type: "none" });
|
||||||
const [focused, setFocused] = useState(false);
|
const [focused, setFocused] = useState(false);
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const store = useData();
|
|
||||||
|
|
||||||
function findSearchString(
|
function findSearchString(
|
||||||
el: HTMLTextAreaElement,
|
el: HTMLTextAreaElement,
|
||||||
|
@ -132,7 +129,7 @@ export function useAutoComplete(
|
||||||
let users: User[] = [];
|
let users: User[] = [];
|
||||||
switch (searchClues.users.type) {
|
switch (searchClues.users.type) {
|
||||||
case "all":
|
case "all":
|
||||||
users = [...store.users.values()];
|
users = [...client.users.values()];
|
||||||
break;
|
break;
|
||||||
case "channel": {
|
case "channel": {
|
||||||
const channel = client.channels.get(
|
const channel = client.channels.get(
|
||||||
|
@ -141,22 +138,15 @@ export function useAutoComplete(
|
||||||
switch (channel?.channel_type) {
|
switch (channel?.channel_type) {
|
||||||
case "Group":
|
case "Group":
|
||||||
case "DirectMessage":
|
case "DirectMessage":
|
||||||
users = channel.recipients
|
users = channel.recipients!.filter(
|
||||||
.map((x) => store.users.get(x))
|
(x) => typeof x !== "undefined",
|
||||||
.filter(
|
) as User[];
|
||||||
(x) => typeof x !== "undefined",
|
|
||||||
) as User[];
|
|
||||||
break;
|
break;
|
||||||
case "TextChannel":
|
case "TextChannel":
|
||||||
const server = channel.server;
|
const server = channel.server_id;
|
||||||
users = client.members
|
users = [...client.members.keys()]
|
||||||
.toArray()
|
.filter((x) => x.server === server)
|
||||||
.filter(
|
.map((x) => client.users.get(x.user))
|
||||||
(x) => x._id.substr(0, 26) === server,
|
|
||||||
)
|
|
||||||
.map((x) =>
|
|
||||||
store.users.get(x._id.substr(26)),
|
|
||||||
)
|
|
||||||
.filter(
|
.filter(
|
||||||
(x) => typeof x !== "undefined",
|
(x) => typeof x !== "undefined",
|
||||||
) as User[];
|
) as User[];
|
||||||
|
@ -197,7 +187,7 @@ export function useAutoComplete(
|
||||||
if (type === "channel" && searchClues?.channels) {
|
if (type === "channel" && searchClues?.channels) {
|
||||||
const channels = client.servers
|
const channels = client.servers
|
||||||
.get(searchClues.channels.server)
|
.get(searchClues.channels.server)
|
||||||
?.channels.map((x) => store.channels.get(x))
|
?.channels.map((x) => client.channels.get(x))
|
||||||
.filter((x) => typeof x !== "undefined") as Channel[];
|
.filter((x) => typeof x !== "undefined") as Channel[];
|
||||||
|
|
||||||
const matches = (
|
const matches = (
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { Message as MessageObject } from "revolt.js/dist/maps/Messages";
|
||||||
|
|
||||||
import { attachContextMenu } from "preact-context-menu";
|
import { attachContextMenu } from "preact-context-menu";
|
||||||
import { memo } from "preact/compat";
|
import { memo } from "preact/compat";
|
||||||
import { useContext, useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
|
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
import { QueuedMessage } from "../../../redux/reducers/queue";
|
import { QueuedMessage } from "../../../redux/reducers/queue";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
import { useClient } from "../../../context/revoltjs/RevoltClient";
|
||||||
import { MessageObject } from "../../../context/revoltjs/util";
|
|
||||||
|
|
||||||
import Overline from "../../ui/Overline";
|
import Overline from "../../ui/Overline";
|
||||||
|
|
||||||
|
@ -46,15 +45,14 @@ const Message = observer(
|
||||||
head: preferHead,
|
head: preferHead,
|
||||||
queued,
|
queued,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const store = useData();
|
const client = useClient();
|
||||||
const user = store.users.get(message.author);
|
const user = message.author;
|
||||||
|
|
||||||
const client = useContext(AppContext);
|
|
||||||
const { openScreen } = useIntermediate();
|
const { openScreen } = useIntermediate();
|
||||||
|
|
||||||
const content = message.content as string;
|
const content = message.content as string;
|
||||||
const head =
|
const head =
|
||||||
preferHead || (message.replies && message.replies.length > 0);
|
preferHead || (message.reply_ids && message.reply_ids.length > 0);
|
||||||
|
|
||||||
// ! FIXME: tell fatal to make this type generic
|
// ! FIXME: tell fatal to make this type generic
|
||||||
// bree: Fatal please...
|
// bree: Fatal please...
|
||||||
|
@ -66,28 +64,33 @@ const Message = observer(
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const openProfile = () =>
|
const openProfile = () =>
|
||||||
openScreen({ id: "profile", user_id: message.author });
|
openScreen({ id: "profile", user_id: message.author_id });
|
||||||
|
|
||||||
// ! FIXME: animate on hover
|
// ! FIXME: animate on hover
|
||||||
const [animate, setAnimate] = useState(false);
|
const [animate, setAnimate] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id={message._id}>
|
<div id={message._id}>
|
||||||
{message.replies?.map((message_id, index) => (
|
{message.reply_ids?.map((message_id, index) => (
|
||||||
<MessageReply
|
<MessageReply
|
||||||
index={index}
|
index={index}
|
||||||
id={message_id}
|
id={message_id}
|
||||||
channel={message.channel}
|
channel={message.channel!}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<MessageBase
|
<MessageBase
|
||||||
highlight={highlight}
|
highlight={highlight}
|
||||||
head={
|
head={
|
||||||
head && !(message.replies && message.replies.length > 0)
|
(head &&
|
||||||
|
!(
|
||||||
|
message.reply_ids &&
|
||||||
|
message.reply_ids.length > 0
|
||||||
|
)) ??
|
||||||
|
false
|
||||||
}
|
}
|
||||||
contrast={contrast}
|
contrast={contrast}
|
||||||
sending={typeof queued !== "undefined"}
|
sending={typeof queued !== "undefined"}
|
||||||
mention={message.mentions?.includes(client.user!._id)}
|
mention={message.mention_ids?.includes(client.user!._id)}
|
||||||
failed={typeof queued?.error !== "undefined"}
|
failed={typeof queued?.error !== "undefined"}
|
||||||
onContextMenu={
|
onContextMenu={
|
||||||
attachContext
|
attachContext
|
||||||
|
|
|
@ -2,8 +2,10 @@ import { Reply } from "@styled-icons/boxicons-regular";
|
||||||
import { File } from "@styled-icons/boxicons-solid";
|
import { File } from "@styled-icons/boxicons-solid";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom";
|
||||||
|
import { RelationshipStatus } from "revolt-api/types/Users";
|
||||||
import { SYSTEM_USER_ID } from "revolt.js";
|
import { SYSTEM_USER_ID } from "revolt.js";
|
||||||
import { Users } from "revolt.js/dist/api/objects";
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
import styled, { css } from "styled-components";
|
import styled, { css } from "styled-components";
|
||||||
|
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
|
@ -11,17 +13,14 @@ import { useLayoutEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { useRenderState } from "../../../../lib/renderer/Singleton";
|
import { useRenderState } from "../../../../lib/renderer/Singleton";
|
||||||
|
|
||||||
import { useData } from "../../../../mobx/State";
|
|
||||||
|
|
||||||
import { useClient } from "../../../../context/revoltjs/RevoltClient";
|
import { useClient } from "../../../../context/revoltjs/RevoltClient";
|
||||||
import { mapMessage, MessageObject } from "../../../../context/revoltjs/util";
|
|
||||||
|
|
||||||
import Markdown from "../../../markdown/Markdown";
|
import Markdown from "../../../markdown/Markdown";
|
||||||
import UserShort from "../../user/UserShort";
|
import UserShort from "../../user/UserShort";
|
||||||
import { SystemMessage } from "../SystemMessage";
|
import { SystemMessage } from "../SystemMessage";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
channel: string;
|
channel: Channel;
|
||||||
index: number;
|
index: number;
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
@ -124,13 +123,11 @@ export const ReplyBase = styled.div<{
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const MessageReply = observer(({ index, channel, id }: Props) => {
|
export const MessageReply = observer(({ index, channel, id }: Props) => {
|
||||||
const client = useClient();
|
const view = useRenderState(channel._id);
|
||||||
const view = useRenderState(channel);
|
|
||||||
if (view?.type !== "RENDER") return null;
|
if (view?.type !== "RENDER") return null;
|
||||||
|
|
||||||
const [message, setMessage] = useState<MessageObject | undefined>(
|
const [message, setMessage] = useState<Message | undefined>(undefined);
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
// ! FIXME: We should do this through the message renderer, so it can fetch it from cache if applicable.
|
// ! FIXME: We should do this through the message renderer, so it can fetch it from cache if applicable.
|
||||||
const m = view.messages.find((x) => x._id === id);
|
const m = view.messages.find((x) => x._id === id);
|
||||||
|
@ -138,9 +135,7 @@ export const MessageReply = observer(({ index, channel, id }: Props) => {
|
||||||
if (m) {
|
if (m) {
|
||||||
setMessage(m);
|
setMessage(m);
|
||||||
} else {
|
} else {
|
||||||
client.channels
|
channel.fetchMessage(id).then(setMessage);
|
||||||
.fetchMessage(channel, id)
|
|
||||||
.then((m) => setMessage(mapMessage(m)));
|
|
||||||
}
|
}
|
||||||
}, [view.messages]);
|
}, [view.messages]);
|
||||||
|
|
||||||
|
@ -155,33 +150,32 @@ export const MessageReply = observer(({ index, channel, id }: Props) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = useData();
|
|
||||||
const user = store.users.get(message.author);
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReplyBase head={index === 0}>
|
<ReplyBase head={index === 0}>
|
||||||
<Reply size={16} />
|
<Reply size={16} />
|
||||||
{user?.relationship === Users.Relationship.Blocked ? (
|
{message.author?.relationship === RelationshipStatus.Blocked ? (
|
||||||
<>
|
<>
|
||||||
<Text id="app.main.channel.misc.blocked_user" />
|
<Text id="app.main.channel.misc.blocked_user" />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{message.author === SYSTEM_USER_ID ? (
|
{message.author_id === SYSTEM_USER_ID ? (
|
||||||
<SystemMessage message={message} hideInfo />
|
<SystemMessage message={message} hideInfo />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="user">
|
<div className="user">
|
||||||
<UserShort user={user} size={16} />
|
<UserShort user={message.author} size={16} />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="content"
|
className="content"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const obj = client.channels.get(channel);
|
if (
|
||||||
if (obj?.channel_type === "TextChannel") {
|
channel.channel_type === "TextChannel"
|
||||||
|
) {
|
||||||
history.push(
|
history.push(
|
||||||
`/server/${obj.server}/channel/${obj._id}/${message._id}`,
|
`/server/${channel.server}/channel/${channel._id}/${message._id}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
history.push(
|
history.push(
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
import { Prompt } from "react-router";
|
import { Prompt } from "react-router";
|
||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom";
|
||||||
import {
|
import type { Attachment } from "revolt-api/types/Autumn";
|
||||||
Attachment,
|
import type { EmbedImage } from "revolt-api/types/January";
|
||||||
Channels,
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
EmbedImage,
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
Servers,
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
Users,
|
import { User } from "revolt.js/dist/maps/Users";
|
||||||
} from "revolt.js/dist/api/objects";
|
|
||||||
|
|
||||||
import { createContext } from "preact";
|
import { createContext } from "preact";
|
||||||
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { internalSubscribe } from "../../lib/eventEmitter";
|
import { internalSubscribe } from "../../lib/eventEmitter";
|
||||||
|
|
||||||
import { Channel, Server, User } from "../../mobx";
|
|
||||||
|
|
||||||
import { Action } from "../../components/ui/Modal";
|
import { Action } from "../../components/ui/Modal";
|
||||||
|
|
||||||
import { Children } from "../../types/Preact";
|
import { Children } from "../../types/Preact";
|
||||||
|
@ -39,7 +36,7 @@ export type Screen =
|
||||||
| { type: "leave_server"; target: Server }
|
| { type: "leave_server"; target: Server }
|
||||||
| { type: "delete_server"; target: Server }
|
| { type: "delete_server"; target: Server }
|
||||||
| { type: "delete_channel"; target: Channel }
|
| { type: "delete_channel"; target: Channel }
|
||||||
| { type: "delete_message"; target: Channels.Message }
|
| { type: "delete_message"; target: Message }
|
||||||
| {
|
| {
|
||||||
type: "create_invite";
|
type: "create_invite";
|
||||||
target: Channel;
|
target: Channel;
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { Client } from "revolt.js";
|
import { Client } from "revolt.js";
|
||||||
import { Message } from "revolt.js/dist/api/objects";
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
|
|
||||||
import { Channel } from "../../mobx";
|
|
||||||
|
|
||||||
import { Children } from "../../types/Preact";
|
import { Children } from "../../types/Preact";
|
||||||
|
|
||||||
export function takeError(error: any): string {
|
export function takeError(error: any): string {
|
||||||
|
@ -25,7 +23,6 @@ export function takeError(error: any): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getChannelName(
|
export function getChannelName(
|
||||||
client: Client,
|
|
||||||
channel: Channel,
|
channel: Channel,
|
||||||
prefixType?: boolean,
|
prefixType?: boolean,
|
||||||
): Children {
|
): Children {
|
||||||
|
@ -33,11 +30,10 @@ export function getChannelName(
|
||||||
return <Text id="app.navigation.tabs.saved" />;
|
return <Text id="app.navigation.tabs.saved" />;
|
||||||
|
|
||||||
if (channel.channel_type === "DirectMessage") {
|
if (channel.channel_type === "DirectMessage") {
|
||||||
const uid = client.channels.getRecipient(channel._id);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{prefixType && "@"}
|
{prefixType && "@"}
|
||||||
{client.users.get(uid)?.username}
|
{channel.recipient!.username}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -48,12 +44,3 @@ export function getChannelName(
|
||||||
|
|
||||||
return <>{channel.name}</>;
|
return <>{channel.name}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MessageObject = Omit<Message, "edited"> & { edited?: string };
|
|
||||||
export function mapMessage(message: Partial<Message>) {
|
|
||||||
const { edited, ...msg } = message;
|
|
||||||
return {
|
|
||||||
...msg,
|
|
||||||
edited: edited?.$date,
|
|
||||||
} as MessageObject;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
|
||||||
|
|
||||||
import { createContext } from "preact";
|
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
|
||||||
|
|
||||||
import { useClient } from "../context/revoltjs/RevoltClient";
|
|
||||||
|
|
||||||
import { DataStore } from ".";
|
|
||||||
import { Children } from "../types/Preact";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
children: Children;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DataContext = createContext<DataStore>(null!);
|
|
||||||
|
|
||||||
// ! later we can do seamless account switching, by hooking this into Redux
|
|
||||||
// ! and monitoring changes to active account and hence swapping stores.
|
|
||||||
// although this may need more work since we need a Client per account too.
|
|
||||||
|
|
||||||
export default function StateLoader(props: Props) {
|
|
||||||
const client = useClient();
|
|
||||||
const [store] = useState(new DataStore(client));
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const packet = (packet: ClientboundNotification) =>
|
|
||||||
store.packet(packet);
|
|
||||||
client.addListener("packet", packet);
|
|
||||||
return () => client.removeListener("packet", packet);
|
|
||||||
}, [client]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DataContext.Provider value={store}>
|
|
||||||
{props.children}
|
|
||||||
</DataContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useData = () => useContext(DataContext);
|
|
|
@ -1,443 +0,0 @@
|
||||||
import isEqual from "lodash.isequal";
|
|
||||||
import {
|
|
||||||
makeAutoObservable,
|
|
||||||
observable,
|
|
||||||
autorun,
|
|
||||||
runInAction,
|
|
||||||
reaction,
|
|
||||||
makeObservable,
|
|
||||||
action,
|
|
||||||
extendObservable,
|
|
||||||
} from "mobx";
|
|
||||||
import { Client } from "revolt.js";
|
|
||||||
import {
|
|
||||||
Attachment,
|
|
||||||
Channels,
|
|
||||||
Servers,
|
|
||||||
Users,
|
|
||||||
} from "revolt.js/dist/api/objects";
|
|
||||||
import {
|
|
||||||
RemoveChannelField,
|
|
||||||
RemoveMemberField,
|
|
||||||
RemoveServerField,
|
|
||||||
RemoveUserField,
|
|
||||||
} from "revolt.js/dist/api/routes";
|
|
||||||
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
|
||||||
|
|
||||||
type Nullable<T> = T | null;
|
|
||||||
function toNullable<T>(data?: T) {
|
|
||||||
return typeof data === "undefined" ? null : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class User {
|
|
||||||
_id: string;
|
|
||||||
username: string;
|
|
||||||
|
|
||||||
avatar: Nullable<Attachment>;
|
|
||||||
badges: Nullable<number>;
|
|
||||||
status: Nullable<Users.Status>;
|
|
||||||
relationship: Nullable<Users.Relationship>;
|
|
||||||
online: Nullable<boolean>;
|
|
||||||
|
|
||||||
constructor(data: Users.User) {
|
|
||||||
this._id = data._id;
|
|
||||||
this.username = data.username;
|
|
||||||
|
|
||||||
this.avatar = toNullable(data.avatar);
|
|
||||||
this.badges = toNullable(data.badges);
|
|
||||||
this.status = toNullable(data.status);
|
|
||||||
this.relationship = toNullable(data.relationship);
|
|
||||||
this.online = toNullable(data.online);
|
|
||||||
|
|
||||||
makeAutoObservable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action update(data: Partial<Users.User>, clear?: RemoveUserField) {
|
|
||||||
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 "Avatar":
|
|
||||||
this.avatar = null;
|
|
||||||
break;
|
|
||||||
case "StatusText": {
|
|
||||||
if (this.status) {
|
|
||||||
this.status.text = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply("username");
|
|
||||||
apply("avatar");
|
|
||||||
apply("badges");
|
|
||||||
apply("status");
|
|
||||||
apply("relationship");
|
|
||||||
apply("online");
|
|
||||||
}
|
|
||||||
|
|
||||||
@action setRelationship(relationship: Users.Relationship) {
|
|
||||||
this.relationship = relationship;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Channel {
|
|
||||||
_id: string;
|
|
||||||
channel_type: Channels.Channel["channel_type"];
|
|
||||||
|
|
||||||
// Direct Message
|
|
||||||
active: Nullable<boolean> = null;
|
|
||||||
|
|
||||||
// Group
|
|
||||||
owner: Nullable<string> = null;
|
|
||||||
|
|
||||||
// Server
|
|
||||||
server: Nullable<string> = null;
|
|
||||||
|
|
||||||
// Permissions
|
|
||||||
permissions: Nullable<number> = null;
|
|
||||||
default_permissions: Nullable<number> = null;
|
|
||||||
role_permissions: Nullable<{ [key: string]: number }> = null;
|
|
||||||
|
|
||||||
// Common
|
|
||||||
name: Nullable<string> = null;
|
|
||||||
icon: Nullable<Attachment> = null;
|
|
||||||
description: Nullable<string> = null;
|
|
||||||
recipients: Nullable<string[]> = null;
|
|
||||||
last_message: Nullable<string | Channels.LastMessage> = null;
|
|
||||||
|
|
||||||
constructor(data: Channels.Channel) {
|
|
||||||
this._id = data._id;
|
|
||||||
this.channel_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<Channels.Channel>,
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
@action groupJoin(user: string) {
|
|
||||||
this.recipients?.push(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action groupLeave(user: string) {
|
|
||||||
this.recipients = toNullable(
|
|
||||||
this.recipients?.filter((x) => x !== user),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Server {
|
|
||||||
_id: string;
|
|
||||||
owner: string;
|
|
||||||
name: string;
|
|
||||||
description: Nullable<string> = null;
|
|
||||||
|
|
||||||
channels: string[] = [];
|
|
||||||
categories: Nullable<Servers.Category[]> = null;
|
|
||||||
system_messages: Nullable<Servers.SystemMessageChannels> = null;
|
|
||||||
|
|
||||||
roles: Nullable<{ [key: string]: Servers.Role }> = null;
|
|
||||||
default_permissions: Servers.PermissionTuple;
|
|
||||||
|
|
||||||
icon: Nullable<Attachment> = null;
|
|
||||||
banner: Nullable<Attachment> = null;
|
|
||||||
|
|
||||||
constructor(data: Servers.Server) {
|
|
||||||
this._id = data._id;
|
|
||||||
this.owner = data.owner;
|
|
||||||
this.name = data.name;
|
|
||||||
this.description = toNullable(data.description);
|
|
||||||
|
|
||||||
this.channels = data.channels;
|
|
||||||
this.categories = toNullable(data.categories);
|
|
||||||
this.system_messages = toNullable(data.system_messages);
|
|
||||||
|
|
||||||
this.roles = toNullable(data.roles);
|
|
||||||
this.default_permissions = data.default_permissions;
|
|
||||||
|
|
||||||
this.icon = toNullable(data.icon);
|
|
||||||
this.banner = toNullable(data.banner);
|
|
||||||
|
|
||||||
makeAutoObservable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action update(data: Partial<Servers.Server>, clear?: RemoveServerField) {
|
|
||||||
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 "Banner":
|
|
||||||
this.banner = null;
|
|
||||||
break;
|
|
||||||
case "Description":
|
|
||||||
this.description = null;
|
|
||||||
break;
|
|
||||||
case "Icon":
|
|
||||||
this.icon = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply("owner");
|
|
||||||
apply("name");
|
|
||||||
apply("description");
|
|
||||||
apply("channels");
|
|
||||||
apply("categories");
|
|
||||||
apply("system_messages");
|
|
||||||
apply("roles");
|
|
||||||
apply("default_permissions");
|
|
||||||
apply("icon");
|
|
||||||
apply("banner");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Member {
|
|
||||||
_id: Servers.MemberCompositeKey;
|
|
||||||
nickname: Nullable<string> = null;
|
|
||||||
avatar: Nullable<Attachment> = null;
|
|
||||||
roles: Nullable<string[]> = null;
|
|
||||||
|
|
||||||
constructor(data: Servers.Member) {
|
|
||||||
this._id = data._id;
|
|
||||||
this.nickname = toNullable(data.nickname);
|
|
||||||
this.avatar = toNullable(data.avatar);
|
|
||||||
this.roles = toNullable(data.roles);
|
|
||||||
|
|
||||||
makeAutoObservable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action update(data: Partial<Servers.Member>, clear?: RemoveMemberField) {
|
|
||||||
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 "Nickname":
|
|
||||||
this.nickname = null;
|
|
||||||
break;
|
|
||||||
case "Avatar":
|
|
||||||
this.avatar = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply("nickname");
|
|
||||||
apply("avatar");
|
|
||||||
apply("roles");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DataStore {
|
|
||||||
client: Client;
|
|
||||||
|
|
||||||
@observable users = new Map<string, User>();
|
|
||||||
@observable channels = new Map<string, Channel>();
|
|
||||||
@observable servers = new Map<string, Server>();
|
|
||||||
@observable members = new Map<Servers.MemberCompositeKey, Member>();
|
|
||||||
|
|
||||||
constructor(client: Client) {
|
|
||||||
makeAutoObservable(this, undefined, { proxy: false });
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
async packet(packet: ClientboundNotification) {
|
|
||||||
switch (packet.type) {
|
|
||||||
case "Ready": {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let server of packet.servers) {
|
|
||||||
this.servers.set(server._id, new Server(server));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ChannelCreate": {
|
|
||||||
this.channels.set(packet._id, new Channel(packet));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ChannelUpdate": {
|
|
||||||
this.channels.get(packet.id)?.update(packet.data, packet.clear);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ChannelDelete": {
|
|
||||||
this.channels.delete(packet.id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ChannelGroupJoin": {
|
|
||||||
this.channels.get(packet.id)?.groupJoin(packet.user);
|
|
||||||
|
|
||||||
if (!this.users.has(packet.user)) {
|
|
||||||
let user = await this.client.users.fetch(packet.user);
|
|
||||||
this.users.set(packet.user, new User(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ChannelGroupLeave": {
|
|
||||||
this.channels.get(packet.id)?.groupJoin(packet.user);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "UserUpdate": {
|
|
||||||
this.users.get(packet.id)?.update(packet.data, packet.clear);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "UserRelationship": {
|
|
||||||
if (!this.users.has(packet.user._id)) {
|
|
||||||
this.users.set(packet.user._id, new User(packet.user));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.users.get(packet.user._id)?.setRelationship(packet.status);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ServerUpdate": {
|
|
||||||
this.servers.get(packet.id)?.update(packet.data, packet.clear);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ServerDelete": {
|
|
||||||
let server = this.servers.get(packet.id);
|
|
||||||
if (server) {
|
|
||||||
for (let channel of server.channels) {
|
|
||||||
this.channels.delete(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.servers.delete(packet.id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ServerMemberUpdate": {
|
|
||||||
this.members.get(packet.id)?.update(packet.data, packet.clear);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ServerMemberJoin": {
|
|
||||||
const _id = { server: packet.id, user: packet.user };
|
|
||||||
this.members.set(_id, new Member({ _id }));
|
|
||||||
|
|
||||||
if (!this.servers.has(packet.id)) {
|
|
||||||
let server = await this.client.servers.fetch(packet.id);
|
|
||||||
this.servers.set(packet.id, new Server(server));
|
|
||||||
|
|
||||||
for (let id of server.channels) {
|
|
||||||
let channel = this.client.channels.get(id);
|
|
||||||
if (channel) {
|
|
||||||
this.channels.set(id, new Channel(channel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.users.has(packet.user)) {
|
|
||||||
let user = await this.client.users.fetch(packet.user);
|
|
||||||
this.users.set(packet.user, new User(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ServerMemberLeave": {
|
|
||||||
this.members.delete({ server: packet.id, user: packet.user });
|
|
||||||
if (packet.user === this.client.user!._id) {
|
|
||||||
await this.packet({ type: "ServerDelete", id: packet.id });
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchMembers(server: string) {
|
|
||||||
let res = await this.client.members.fetchMembers(server);
|
|
||||||
|
|
||||||
for (let user of res.users) {
|
|
||||||
if (!this.users.has(user._id)) {
|
|
||||||
this.users.set(user._id, new User(user));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.members;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { X, Plus } from "@styled-icons/boxicons-regular";
|
import { X, Plus } from "@styled-icons/boxicons-regular";
|
||||||
import { PhoneCall, Envelope, UserX } from "@styled-icons/boxicons-solid";
|
import { PhoneCall, Envelope, UserX } from "@styled-icons/boxicons-solid";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Users } from "revolt.js/dist/api/objects";
|
import { RelationshipStatus } from "revolt-api/types/Users";
|
||||||
|
import { User } from "revolt.js/dist/maps/Users";
|
||||||
|
|
||||||
import styles from "./Friend.module.scss";
|
import styles from "./Friend.module.scss";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
@ -11,8 +12,6 @@ import { useContext } from "preact/hooks";
|
||||||
|
|
||||||
import { stopPropagation } from "../../lib/stopPropagation";
|
import { stopPropagation } from "../../lib/stopPropagation";
|
||||||
|
|
||||||
import { User } from "../../mobx";
|
|
||||||
|
|
||||||
import { VoiceOperationsContext } from "../../context/Voice";
|
import { VoiceOperationsContext } from "../../context/Voice";
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||||
import {
|
import {
|
||||||
|
@ -39,7 +38,7 @@ export const Friend = observer(({ user }: Props) => {
|
||||||
const actions: Children[] = [];
|
const actions: Children[] = [];
|
||||||
let subtext: Children = null;
|
let subtext: Children = null;
|
||||||
|
|
||||||
if (user.relationship === Users.Relationship.Friend) {
|
if (user.relationship === RelationshipStatus.Friend) {
|
||||||
subtext = <UserStatus user={user} />;
|
subtext = <UserStatus user={user} />;
|
||||||
actions.push(
|
actions.push(
|
||||||
<>
|
<>
|
||||||
|
@ -61,14 +60,12 @@ export const Friend = observer(({ user }: Props) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.relationship === Users.Relationship.Incoming) {
|
if (user.relationship === RelationshipStatus.Incoming) {
|
||||||
actions.push(
|
actions.push(
|
||||||
<IconButton
|
<IconButton
|
||||||
type="circle"
|
type="circle"
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
onClick={(ev) =>
|
onClick={(ev) => stopPropagation(ev, user.addFriend())}>
|
||||||
stopPropagation(ev, client.users.addFriend(user.username))
|
|
||||||
}>
|
|
||||||
<Plus size={24} />
|
<Plus size={24} />
|
||||||
</IconButton>,
|
</IconButton>,
|
||||||
);
|
);
|
||||||
|
@ -76,14 +73,14 @@ export const Friend = observer(({ user }: Props) => {
|
||||||
subtext = <Text id="app.special.friends.incoming" />;
|
subtext = <Text id="app.special.friends.incoming" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.relationship === Users.Relationship.Outgoing) {
|
if (user.relationship === RelationshipStatus.Outgoing) {
|
||||||
subtext = <Text id="app.special.friends.outgoing" />;
|
subtext = <Text id="app.special.friends.outgoing" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
user.relationship === Users.Relationship.Friend ||
|
user.relationship === RelationshipStatus.Friend ||
|
||||||
user.relationship === Users.Relationship.Outgoing ||
|
user.relationship === RelationshipStatus.Outgoing ||
|
||||||
user.relationship === Users.Relationship.Incoming
|
user.relationship === RelationshipStatus.Incoming
|
||||||
) {
|
) {
|
||||||
actions.push(
|
actions.push(
|
||||||
<IconButton
|
<IconButton
|
||||||
|
@ -96,13 +93,13 @@ export const Friend = observer(({ user }: Props) => {
|
||||||
onClick={(ev) =>
|
onClick={(ev) =>
|
||||||
stopPropagation(
|
stopPropagation(
|
||||||
ev,
|
ev,
|
||||||
user.relationship === Users.Relationship.Friend
|
user.relationship === RelationshipStatus.Friend
|
||||||
? openScreen({
|
? openScreen({
|
||||||
id: "special_prompt",
|
id: "special_prompt",
|
||||||
type: "unfriend_user",
|
type: "unfriend_user",
|
||||||
target: user,
|
target: user,
|
||||||
})
|
})
|
||||||
: client.users.removeFriend(user._id),
|
: user.removeFriend(),
|
||||||
)
|
)
|
||||||
}>
|
}>
|
||||||
<X size={24} />
|
<X size={24} />
|
||||||
|
@ -110,14 +107,12 @@ export const Friend = observer(({ user }: Props) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.relationship === Users.Relationship.Blocked) {
|
if (user.relationship === RelationshipStatus.Blocked) {
|
||||||
actions.push(
|
actions.push(
|
||||||
<IconButton
|
<IconButton
|
||||||
type="circle"
|
type="circle"
|
||||||
className={classNames(styles.button, styles.error)}
|
className={classNames(styles.button, styles.error)}
|
||||||
onClick={(ev) =>
|
onClick={(ev) => stopPropagation(ev, user.unblockUser())}>
|
||||||
stopPropagation(ev, client.users.unblockUser(user._id))
|
|
||||||
}>
|
|
||||||
<UserX size={24} />
|
<UserX size={24} />
|
||||||
</IconButton>,
|
</IconButton>,
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,8 @@ import {
|
||||||
} from "@styled-icons/boxicons-regular";
|
} from "@styled-icons/boxicons-regular";
|
||||||
import { UserDetail, MessageAdd, UserPlus } from "@styled-icons/boxicons-solid";
|
import { UserDetail, MessageAdd, UserPlus } from "@styled-icons/boxicons-solid";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Users } from "revolt.js/dist/api/objects";
|
import { RelationshipStatus, Presence } from "revolt-api/types/Users";
|
||||||
|
import { User } from "revolt.js/dist/maps/Users";
|
||||||
|
|
||||||
import styles from "./Friend.module.scss";
|
import styles from "./Friend.module.scss";
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
|
@ -13,10 +14,8 @@ import { Text } from "preact-i18n";
|
||||||
import { TextReact } from "../../lib/i18n";
|
import { TextReact } from "../../lib/i18n";
|
||||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import { User } from "../../mobx";
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
|
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||||
|
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
import CollapsibleSection from "../../components/common/CollapsibleSection";
|
import CollapsibleSection from "../../components/common/CollapsibleSection";
|
||||||
import Tooltip from "../../components/common/Tooltip";
|
import Tooltip from "../../components/common/Tooltip";
|
||||||
|
@ -30,43 +29,40 @@ import { Friend } from "./Friend";
|
||||||
export default observer(() => {
|
export default observer(() => {
|
||||||
const { openScreen } = useIntermediate();
|
const { openScreen } = useIntermediate();
|
||||||
|
|
||||||
const store = useData();
|
const client = useClient();
|
||||||
const users = [...store.users.values()];
|
const users = [...client.users.values()];
|
||||||
users.sort((a, b) => a.username.localeCompare(b.username));
|
users.sort((a, b) => a.username.localeCompare(b.username));
|
||||||
|
|
||||||
const friends = users.filter(
|
const friends = users.filter(
|
||||||
(x) => x.relationship === Users.Relationship.Friend,
|
(x) => x.relationship === RelationshipStatus.Friend,
|
||||||
);
|
);
|
||||||
const lists = [
|
const lists = [
|
||||||
[
|
[
|
||||||
"",
|
"",
|
||||||
users.filter((x) => x.relationship === Users.Relationship.Incoming),
|
users.filter((x) => x.relationship === RelationshipStatus.Incoming),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"app.special.friends.sent",
|
"app.special.friends.sent",
|
||||||
users.filter((x) => x.relationship === Users.Relationship.Outgoing),
|
users.filter((x) => x.relationship === RelationshipStatus.Outgoing),
|
||||||
"outgoing",
|
"outgoing",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"app.status.online",
|
"app.status.online",
|
||||||
friends.filter(
|
friends.filter(
|
||||||
(x) =>
|
(x) => x.online && x.status?.presence !== Presence.Invisible,
|
||||||
x.online && x.status?.presence !== Users.Presence.Invisible,
|
|
||||||
),
|
),
|
||||||
"online",
|
"online",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"app.status.offline",
|
"app.status.offline",
|
||||||
friends.filter(
|
friends.filter(
|
||||||
(x) =>
|
(x) => !x.online || x.status?.presence === Presence.Invisible,
|
||||||
!x.online ||
|
|
||||||
x.status?.presence === Users.Presence.Invisible,
|
|
||||||
),
|
),
|
||||||
"offline",
|
"offline",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"app.special.friends.blocked",
|
"app.special.friends.blocked",
|
||||||
users.filter((x) => x.relationship === Users.Relationship.Blocked),
|
users.filter((x) => x.relationship === RelationshipStatus.Blocked),
|
||||||
"blocked",
|
"blocked",
|
||||||
],
|
],
|
||||||
] as [string, User[], string][];
|
] as [string, User[], string][];
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
import { ArrowBack } from "@styled-icons/boxicons-regular";
|
import { ArrowBack } from "@styled-icons/boxicons-regular";
|
||||||
import { autorun } from "mobx";
|
import { autorun } from "mobx";
|
||||||
import { useStore } from "react-redux";
|
|
||||||
import { useHistory, useParams } from "react-router-dom";
|
import { useHistory, useParams } from "react-router-dom";
|
||||||
import { Invites, Servers } from "revolt.js/dist/api/objects";
|
import { RetrievedInvite } from "revolt-api/types/Invites";
|
||||||
|
|
||||||
import styles from "./Invite.module.scss";
|
import styles from "./Invite.module.scss";
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { defer } from "../../lib/defer";
|
import { defer } from "../../lib/defer";
|
||||||
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
|
|
||||||
import RequiresOnline from "../../context/revoltjs/RequiresOnline";
|
import RequiresOnline from "../../context/revoltjs/RequiresOnline";
|
||||||
import {
|
import {
|
||||||
AppContext,
|
AppContext,
|
||||||
|
@ -26,14 +23,13 @@ import Overline from "../../components/ui/Overline";
|
||||||
import Preloader from "../../components/ui/Preloader";
|
import Preloader from "../../components/ui/Preloader";
|
||||||
|
|
||||||
export default function Invite() {
|
export default function Invite() {
|
||||||
const store = useData();
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const client = useContext(AppContext);
|
const client = useContext(AppContext);
|
||||||
const status = useContext(StatusContext);
|
const status = useContext(StatusContext);
|
||||||
const { code } = useParams<{ code: string }>();
|
const { code } = useParams<{ code: string }>();
|
||||||
const [processing, setProcessing] = useState(false);
|
const [processing, setProcessing] = useState(false);
|
||||||
const [error, setError] = useState<string | undefined>(undefined);
|
const [error, setError] = useState<string | undefined>(undefined);
|
||||||
const [invite, setInvite] = useState<Invites.RetrievedInvite | undefined>(
|
const [invite, setInvite] = useState<RetrievedInvite | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -122,7 +118,7 @@ export default function Invite() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const dispose = autorun(() => {
|
const dispose = autorun(() => {
|
||||||
let server = store.servers.get(
|
let server = client.servers.get(
|
||||||
invite.server_id,
|
invite.server_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { Route, useHistory, useParams } from "react-router-dom";
|
||||||
|
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
|
|
||||||
import { useClient } from "../../context/revoltjs/RevoltClient";
|
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||||
import { getChannelName } from "../../context/revoltjs/util";
|
import { getChannelName } from "../../context/revoltjs/util";
|
||||||
|
|
||||||
|
@ -17,9 +15,8 @@ import Permissions from "./channel/Permissions";
|
||||||
export default function ChannelSettings() {
|
export default function ChannelSettings() {
|
||||||
const { channel: cid } = useParams<{ channel: string }>();
|
const { channel: cid } = useParams<{ channel: string }>();
|
||||||
|
|
||||||
const store = useData();
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const channel = store.channels.get(cid);
|
const channel = client.channels.get(cid);
|
||||||
if (!channel) return null;
|
if (!channel) return null;
|
||||||
if (
|
if (
|
||||||
channel.channel_type === "SavedMessages" ||
|
channel.channel_type === "SavedMessages" ||
|
||||||
|
@ -53,7 +50,7 @@ export default function ChannelSettings() {
|
||||||
category: (
|
category: (
|
||||||
<Category
|
<Category
|
||||||
variant="uniform"
|
variant="uniform"
|
||||||
text={getChannelName(client, channel, true)}
|
text={getChannelName(channel, true)}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
id: "overview",
|
id: "overview",
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { ListUl, ListCheck, ListMinus } from "@styled-icons/boxicons-regular";
|
import { ListUl, ListCheck, ListMinus } from "@styled-icons/boxicons-regular";
|
||||||
import { XSquare, Share, Group } from "@styled-icons/boxicons-solid";
|
import { XSquare, Share, Group } from "@styled-icons/boxicons-solid";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
import { Route, useHistory, useParams } from "react-router-dom";
|
import { Route, useHistory, useParams } from "react-router-dom";
|
||||||
|
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
|
|
||||||
import RequiresOnline from "../../context/revoltjs/RequiresOnline";
|
import RequiresOnline from "../../context/revoltjs/RequiresOnline";
|
||||||
|
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
import Category from "../../components/ui/Category";
|
import Category from "../../components/ui/Category";
|
||||||
|
|
||||||
|
@ -15,12 +17,11 @@ import { Invites } from "./server/Invites";
|
||||||
import { Members } from "./server/Members";
|
import { Members } from "./server/Members";
|
||||||
import { Overview } from "./server/Overview";
|
import { Overview } from "./server/Overview";
|
||||||
import { Roles } from "./server/Roles";
|
import { Roles } from "./server/Roles";
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
|
|
||||||
export default function ServerSettings() {
|
export default observer(() => {
|
||||||
const { server: sid } = useParams<{ server: string }>();
|
const { server: sid } = useParams<{ server: string }>();
|
||||||
const store = useData();
|
const client = useClient();
|
||||||
const server = store.servers.get(sid);
|
const server = client.servers.get(sid);
|
||||||
if (!server) return null;
|
if (!server) return null;
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
@ -36,7 +37,7 @@ export default function ServerSettings() {
|
||||||
<GenericSettings
|
<GenericSettings
|
||||||
pages={[
|
pages={[
|
||||||
{
|
{
|
||||||
category: <Category variant="uniform" text={server.name} />, //TOFIX: Just add the server.name as a string, otherwise it makes a duplicate category
|
category: <Category variant="uniform" text={server.name} />,
|
||||||
id: "overview",
|
id: "overview",
|
||||||
icon: <ListUl size={20} />,
|
icon: <ListUl size={20} />,
|
||||||
title: (
|
title: (
|
||||||
|
@ -110,4 +111,4 @@ export default function ServerSettings() {
|
||||||
showExitButton
|
showExitButton
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Channels } from "revolt.js/dist/api/objects";
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
import styled, { css } from "styled-components";
|
import styled, { css } from "styled-components";
|
||||||
|
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
|
@ -7,8 +7,6 @@ import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
|
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
|
||||||
|
|
||||||
import { Channel } from "../../../mobx";
|
|
||||||
|
|
||||||
import { FileUploader } from "../../../context/revoltjs/FileUploads";
|
import { FileUploader } from "../../../context/revoltjs/FileUploads";
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
|
@ -51,7 +49,7 @@ export default observer(({ channel }: Props) => {
|
||||||
if (description !== channel.description)
|
if (description !== channel.description)
|
||||||
changes.description = description;
|
changes.description = description;
|
||||||
|
|
||||||
client.channels.edit(channel._id, changes);
|
channel.edit(changes);
|
||||||
setChanged(false);
|
setChanged(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,17 +63,12 @@ export default observer(({ channel }: Props) => {
|
||||||
fileType="icons"
|
fileType="icons"
|
||||||
behaviour="upload"
|
behaviour="upload"
|
||||||
maxFileSize={2_500_000}
|
maxFileSize={2_500_000}
|
||||||
onUpload={(icon) =>
|
onUpload={(icon) => channel.edit({ icon })}
|
||||||
client.channels.edit(channel._id, { icon })
|
previewURL={channel.generateIconURL(
|
||||||
}
|
|
||||||
previewURL={client.channels.getIconURL(
|
|
||||||
channel._id,
|
|
||||||
{ max_side: 256 },
|
{ max_side: 256 },
|
||||||
true,
|
true,
|
||||||
)}
|
)}
|
||||||
remove={() =>
|
remove={() => channel.edit({ remove: "Icon" })}
|
||||||
client.channels.edit(channel._id, { remove: "Icon" })
|
|
||||||
}
|
|
||||||
defaultPreview={
|
defaultPreview={
|
||||||
channel.channel_type === "Group"
|
channel.channel_type === "Group"
|
||||||
? "/assets/group.png"
|
? "/assets/group.png"
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Channels } from "revolt.js/dist/api/objects";
|
|
||||||
import { ChannelPermission } from "revolt.js/dist/api/permissions";
|
import { ChannelPermission } from "revolt.js/dist/api/permissions";
|
||||||
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { Channel } from "../../../mobx";
|
import { AppContext, useClient } from "../../../context/revoltjs/RevoltClient";
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
|
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
|
||||||
|
|
||||||
import Button from "../../../components/ui/Button";
|
import Button from "../../../components/ui/Button";
|
||||||
import Checkbox from "../../../components/ui/Checkbox";
|
import Checkbox from "../../../components/ui/Checkbox";
|
||||||
|
@ -30,13 +27,12 @@ interface Props {
|
||||||
// ! FIXME: bad code :)
|
// ! FIXME: bad code :)
|
||||||
export default observer(({ channel }: Props) => {
|
export default observer(({ channel }: Props) => {
|
||||||
const [selected, setSelected] = useState("default");
|
const [selected, setSelected] = useState("default");
|
||||||
const client = useContext(AppContext);
|
const client = useClient();
|
||||||
const store = useData();
|
|
||||||
|
|
||||||
type R = { name: string; permissions: number };
|
type R = { name: string; permissions: number };
|
||||||
const roles: { [key: string]: R } = {};
|
const roles: { [key: string]: R } = {};
|
||||||
if (channel.channel_type !== "Group") {
|
if (channel.channel_type !== "Group") {
|
||||||
const server = store.servers.get(channel.server!);
|
const server = channel.server;
|
||||||
const a = server?.roles ?? {};
|
const a = server?.roles ?? {};
|
||||||
for (const b of Object.keys(a)) {
|
for (const b of Object.keys(a)) {
|
||||||
roles[b] = {
|
roles[b] = {
|
||||||
|
@ -105,7 +101,7 @@ export default observer(({ channel }: Props) => {
|
||||||
<Button
|
<Button
|
||||||
contrast
|
contrast
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
client.channels.setPermissions(channel._id, selected, p);
|
channel.setPermissions(selected, p);
|
||||||
}}>
|
}}>
|
||||||
click here to save permissions for role
|
click here to save permissions for role
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -2,14 +2,12 @@ import { At } from "@styled-icons/boxicons-regular";
|
||||||
import { Envelope, Key, HelpCircle } from "@styled-icons/boxicons-solid";
|
import { Envelope, Key, HelpCircle } from "@styled-icons/boxicons-solid";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Link, useHistory } from "react-router-dom";
|
import { Link, useHistory } from "react-router-dom";
|
||||||
import { Users } from "revolt.js/dist/api/objects";
|
import { Profile } from "revolt-api/types/Users";
|
||||||
|
|
||||||
import styles from "./Panes.module.scss";
|
import styles from "./Panes.module.scss";
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||||
import {
|
import {
|
||||||
ClientStatus,
|
ClientStatus,
|
||||||
|
@ -28,14 +26,10 @@ export const Account = observer(() => {
|
||||||
const status = useContext(StatusContext);
|
const status = useContext(StatusContext);
|
||||||
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const store = useData();
|
|
||||||
const user = store.users.get(client.user!._id)!;
|
|
||||||
|
|
||||||
const [email, setEmail] = useState("...");
|
const [email, setEmail] = useState("...");
|
||||||
const [revealEmail, setRevealEmail] = useState(false);
|
const [revealEmail, setRevealEmail] = useState(false);
|
||||||
const [profile, setProfile] = useState<undefined | Users.Profile>(
|
const [profile, setProfile] = useState<undefined | Profile>(undefined);
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
function switchPage(to: string) {
|
function switchPage(to: string) {
|
||||||
|
@ -50,8 +44,8 @@ export const Account = observer(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile === undefined && status === ClientStatus.ONLINE) {
|
if (profile === undefined && status === ClientStatus.ONLINE) {
|
||||||
client.users
|
client
|
||||||
.fetchProfile(user._id)
|
.user!.fetchProfile()
|
||||||
.then((profile) => setProfile(profile ?? {}));
|
.then((profile) => setProfile(profile ?? {}));
|
||||||
}
|
}
|
||||||
}, [status]);
|
}, [status]);
|
||||||
|
@ -61,12 +55,14 @@ export const Account = observer(() => {
|
||||||
<div className={styles.banner}>
|
<div className={styles.banner}>
|
||||||
<UserIcon
|
<UserIcon
|
||||||
className={styles.avatar}
|
className={styles.avatar}
|
||||||
target={user}
|
target={client.user!}
|
||||||
size={72}
|
size={72}
|
||||||
onClick={() => switchPage("profile")}
|
onClick={() => switchPage("profile")}
|
||||||
/>
|
/>
|
||||||
<div className={styles.userDetail}>
|
<div className={styles.userDetail}>
|
||||||
<div className={styles.username}>@{user.username}</div>
|
<div className={styles.username}>
|
||||||
|
@{client.user!.username}
|
||||||
|
</div>
|
||||||
<div className={styles.userid}>
|
<div className={styles.userid}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
|
@ -75,8 +71,8 @@ export const Account = observer(() => {
|
||||||
<HelpCircle size={16} />
|
<HelpCircle size={16} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip content={<Text id="app.special.copy" />}>
|
<Tooltip content={<Text id="app.special.copy" />}>
|
||||||
<a onClick={() => writeClipboard(user._id)}>
|
<a onClick={() => writeClipboard(client.user!._id)}>
|
||||||
{user._id}
|
{client.user!._id}
|
||||||
</a>
|
</a>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -85,7 +81,7 @@ export const Account = observer(() => {
|
||||||
<div className={styles.details}>
|
<div className={styles.details}>
|
||||||
{(
|
{(
|
||||||
[
|
[
|
||||||
["username", user.username, <At size={24} />],
|
["username", client.user!.username, <At size={24} />],
|
||||||
["email", email, <Envelope size={24} />],
|
["email", email, <Envelope size={24} />],
|
||||||
["password", "***********", <Key size={24} />],
|
["password", "***********", <Key size={24} />],
|
||||||
] as const
|
] as const
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { Users } from "revolt.js/dist/api/objects";
|
|
||||||
|
|
||||||
import styles from "./Panes.module.scss";
|
import styles from "./Panes.module.scss";
|
||||||
import { IntlContext, Text, translate } from "preact-i18n";
|
import { IntlContext, Text, translate } from "preact-i18n";
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
@ -18,6 +16,7 @@ import AutoComplete, {
|
||||||
useAutoComplete,
|
useAutoComplete,
|
||||||
} from "../../../components/common/AutoComplete";
|
} from "../../../components/common/AutoComplete";
|
||||||
import Button from "../../../components/ui/Button";
|
import Button from "../../../components/ui/Button";
|
||||||
|
import { Profile } from "revolt-api/types/Users";
|
||||||
|
|
||||||
export function Profile() {
|
export function Profile() {
|
||||||
const { intl } = useContext(IntlContext);
|
const { intl } = useContext(IntlContext);
|
||||||
|
@ -25,15 +24,15 @@ export function Profile() {
|
||||||
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
|
|
||||||
const [profile, setProfile] = useState<undefined | Users.Profile>(
|
const [profile, setProfile] = useState<undefined | Profile>(
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ! FIXME: temporary solution
|
// ! FIXME: temporary solution
|
||||||
// ! we should just announce profile changes through WS
|
// ! we should just announce profile changes through WS
|
||||||
function refreshProfile() {
|
function refreshProfile() {
|
||||||
client.users
|
client
|
||||||
.fetchProfile(client.user!._id)
|
.user!.fetchProfile()
|
||||||
.then((profile) => setProfile(profile ?? {}));
|
.then((profile) => setProfile(profile ?? {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,20 +84,17 @@ export function Profile() {
|
||||||
fileType="avatars"
|
fileType="avatars"
|
||||||
behaviour="upload"
|
behaviour="upload"
|
||||||
maxFileSize={4_000_000}
|
maxFileSize={4_000_000}
|
||||||
onUpload={(avatar) => client.users.editUser({ avatar })}
|
onUpload={(avatar) => client.users.edit({ avatar })}
|
||||||
remove={() =>
|
remove={() =>
|
||||||
client.users.editUser({ remove: "Avatar" })
|
client.users.edit({ remove: "Avatar" })
|
||||||
}
|
}
|
||||||
defaultPreview={client.users.getAvatarURL(
|
defaultPreview={client.user!.generateAvatarURL(
|
||||||
client.user!._id,
|
|
||||||
{ max_side: 256 },
|
{ max_side: 256 },
|
||||||
true,
|
true,
|
||||||
)}
|
)}
|
||||||
previewURL={client.users.getAvatarURL(
|
previewURL={client.user!.generateAvatarURL(
|
||||||
client.user!._id,
|
|
||||||
{ max_side: 256 },
|
{ max_side: 256 },
|
||||||
true,
|
true,
|
||||||
true,
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -113,21 +109,21 @@ export function Profile() {
|
||||||
fileType="backgrounds"
|
fileType="backgrounds"
|
||||||
maxFileSize={6_000_000}
|
maxFileSize={6_000_000}
|
||||||
onUpload={async (background) => {
|
onUpload={async (background) => {
|
||||||
await client.users.editUser({
|
await client.users.edit({
|
||||||
profile: { background },
|
profile: { background },
|
||||||
});
|
});
|
||||||
refreshProfile();
|
refreshProfile();
|
||||||
}}
|
}}
|
||||||
remove={async () => {
|
remove={async () => {
|
||||||
await client.users.editUser({
|
await client.users.edit({
|
||||||
remove: "ProfileBackground",
|
remove: "ProfileBackground",
|
||||||
});
|
});
|
||||||
setProfile({ ...profile, background: undefined });
|
setProfile({ ...profile, background: undefined });
|
||||||
}}
|
}}
|
||||||
previewURL={
|
previewURL={
|
||||||
profile?.background
|
profile?.background
|
||||||
? client.users.getBackgroundURL(
|
? client.generateFileURL(
|
||||||
profile,
|
profile.background,
|
||||||
{ width: 1000 },
|
{ width: 1000 },
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
@ -169,7 +165,7 @@ export function Profile() {
|
||||||
contrast
|
contrast
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setChanged(false);
|
setChanged(false);
|
||||||
client.users.editUser({
|
client.users.edit({
|
||||||
profile: { content: profile?.content },
|
profile: { content: profile?.content },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import { XCircle } from "@styled-icons/boxicons-regular";
|
import { XCircle } from "@styled-icons/boxicons-regular";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Servers, Users } from "revolt.js/dist/api/objects";
|
|
||||||
import { Route } from "revolt.js/dist/api/routes";
|
import { Route } from "revolt.js/dist/api/routes";
|
||||||
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
|
|
||||||
import styles from "./Panes.module.scss";
|
import styles from "./Panes.module.scss";
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { Server } from "../../../mobx";
|
|
||||||
|
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
import UserIcon from "../../../components/common/user/UserIcon";
|
import UserIcon from "../../../components/common/user/UserIcon";
|
||||||
|
@ -27,7 +25,7 @@ export const Bans = observer(({ server }: Props) => {
|
||||||
>(undefined);
|
>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
client.servers.fetchBans(server._id).then(setData as any);
|
server.fetchBans().then(setData as any);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -64,10 +62,7 @@ export const Bans = observer(({ server }: Props) => {
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setDelete([...deleting, x._id.user]);
|
setDelete([...deleting, x._id.user]);
|
||||||
|
|
||||||
await client.servers.unbanUser(
|
await server.unbanUser(x._id.user);
|
||||||
server._id,
|
|
||||||
x._id.user,
|
|
||||||
);
|
|
||||||
|
|
||||||
setData({
|
setData({
|
||||||
...data,
|
...data,
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
import { XCircle } from "@styled-icons/boxicons-regular";
|
|
||||||
import isEqual from "lodash.isequal";
|
import isEqual from "lodash.isequal";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Channels, Servers, Users } from "revolt.js/dist/api/objects";
|
import { Category } from "revolt-api/types/Servers";
|
||||||
import { Route } from "revolt.js/dist/api/routes";
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
|
|
||||||
import styles from "./Panes.module.scss";
|
import { useContext, useState } from "preact/hooks";
|
||||||
import { Text } from "preact-i18n";
|
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
|
||||||
|
|
||||||
import { Server } from "../../../mobx";
|
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
|
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
|
@ -30,15 +24,9 @@ interface Props {
|
||||||
// ! FIXME: really bad code
|
// ! FIXME: really bad code
|
||||||
export const Categories = observer(({ server }: Props) => {
|
export const Categories = observer(({ server }: Props) => {
|
||||||
const client = useContext(AppContext);
|
const client = useContext(AppContext);
|
||||||
const store = useData();
|
const channels = server.channels.filter((x) => typeof x !== "undefined");
|
||||||
const channels = server.channels
|
|
||||||
.map((id) => store.channels.get(id)!)
|
|
||||||
.filter((x) => typeof x !== "undefined");
|
|
||||||
|
|
||||||
const [cats, setCats] = useState<Servers.Category[]>(
|
|
||||||
server.categories ?? [],
|
|
||||||
);
|
|
||||||
|
|
||||||
|
const [cats, setCats] = useState<Category[]>(server.categories ?? []);
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -48,9 +36,7 @@ export const Categories = observer(({ server }: Props) => {
|
||||||
<Button
|
<Button
|
||||||
contrast
|
contrast
|
||||||
disabled={isEqual(server.categories ?? [], cats)}
|
disabled={isEqual(server.categories ?? [], cats)}
|
||||||
onClick={() =>
|
onClick={() => server.edit({ categories: cats })}>
|
||||||
client.servers.edit(server._id, { categories: cats })
|
|
||||||
}>
|
|
||||||
save categories
|
save categories
|
||||||
</Button>
|
</Button>
|
||||||
</p>
|
</p>
|
||||||
|
@ -116,13 +102,13 @@ export const Categories = observer(({ server }: Props) => {
|
||||||
}}>
|
}}>
|
||||||
<div style={{ flexShrink: 0 }}>
|
<div style={{ flexShrink: 0 }}>
|
||||||
<ChannelIcon target={channel} size={24} />{" "}
|
<ChannelIcon target={channel} size={24} />{" "}
|
||||||
<span>{channel.name}</span>
|
<span>{channel!.name}</span>
|
||||||
</div>
|
</div>
|
||||||
<ComboBox
|
<ComboBox
|
||||||
style={{ flexGrow: 1 }}
|
style={{ flexGrow: 1 }}
|
||||||
value={
|
value={
|
||||||
cats.find((x) =>
|
cats.find((x) =>
|
||||||
x.channels.includes(channel._id),
|
x.channels.includes(channel!._id),
|
||||||
)?.id ?? "none"
|
)?.id ?? "none"
|
||||||
}
|
}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
@ -132,11 +118,11 @@ export const Categories = observer(({ server }: Props) => {
|
||||||
...x,
|
...x,
|
||||||
channels: [
|
channels: [
|
||||||
...x.channels.filter(
|
...x.channels.filter(
|
||||||
(y) => y !== channel._id,
|
(y) => y !== channel!._id,
|
||||||
),
|
),
|
||||||
...(e.currentTarget.value ===
|
...(e.currentTarget.value ===
|
||||||
x.id
|
x.id
|
||||||
? [channel._id]
|
? [channel!._id]
|
||||||
: []),
|
: []),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import { XCircle } from "@styled-icons/boxicons-regular";
|
import { XCircle } from "@styled-icons/boxicons-regular";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Invites as InvitesNS, Servers } from "revolt.js/dist/api/objects";
|
import { ServerInvite } from "revolt-api/types/Invites";
|
||||||
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
|
|
||||||
import styles from "./Panes.module.scss";
|
import styles from "./Panes.module.scss";
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { Server } from "../../../mobx";
|
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
|
|
||||||
import { useClient } from "../../../context/revoltjs/RevoltClient";
|
import { useClient } from "../../../context/revoltjs/RevoltClient";
|
||||||
import { getChannelName } from "../../../context/revoltjs/util";
|
import { getChannelName } from "../../../context/revoltjs/util";
|
||||||
|
|
||||||
|
@ -22,21 +20,18 @@ interface Props {
|
||||||
|
|
||||||
export const Invites = observer(({ server }: Props) => {
|
export const Invites = observer(({ server }: Props) => {
|
||||||
const [deleting, setDelete] = useState<string[]>([]);
|
const [deleting, setDelete] = useState<string[]>([]);
|
||||||
const [invites, setInvites] = useState<
|
const [invites, setInvites] = useState<ServerInvite[] | undefined>(
|
||||||
InvitesNS.ServerInvite[] | undefined
|
undefined,
|
||||||
>(undefined);
|
);
|
||||||
|
|
||||||
const store = useData();
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const users = invites?.map((invite) => store.users.get(invite.creator));
|
const users = invites?.map((invite) => client.users.get(invite.creator));
|
||||||
const channels = invites?.map((invite) =>
|
const channels = invites?.map((invite) =>
|
||||||
store.channels.get(invite.channel),
|
client.channels.get(invite.channel),
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
client.servers
|
server.fetchInvites().then(setInvites);
|
||||||
.fetchInvites(server._id)
|
|
||||||
.then((invites) => setInvites(invites));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -73,7 +68,7 @@ export const Invites = observer(({ server }: Props) => {
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
{channel && creator
|
{channel && creator
|
||||||
? getChannelName(client, channel, true)
|
? getChannelName(channel, true)
|
||||||
: "#??"}
|
: "#??"}
|
||||||
</span>
|
</span>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import { ChevronDown } from "@styled-icons/boxicons-regular";
|
import { ChevronDown } from "@styled-icons/boxicons-regular";
|
||||||
import { isEqual } from "lodash";
|
import { isEqual } from "lodash";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Servers } from "revolt.js/dist/api/objects";
|
import { Member } from "revolt.js/dist/maps/Members";
|
||||||
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
|
import { User } from "revolt.js/dist/maps/Users";
|
||||||
|
|
||||||
import styles from "./Panes.module.scss";
|
import styles from "./Panes.module.scss";
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { Server } from "../../../mobx";
|
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
|
|
||||||
import { useClient } from "../../../context/revoltjs/RevoltClient";
|
import { useClient } from "../../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
import UserIcon from "../../../components/common/user/UserIcon";
|
import UserIcon from "../../../components/common/user/UserIcon";
|
||||||
|
@ -24,25 +23,21 @@ interface Props {
|
||||||
|
|
||||||
export const Members = observer(({ server }: Props) => {
|
export const Members = observer(({ server }: Props) => {
|
||||||
const [selected, setSelected] = useState<undefined | string>();
|
const [selected, setSelected] = useState<undefined | string>();
|
||||||
const [members, setMembers] = useState<Servers.Member[] | undefined>(
|
const [data, setData] = useState<
|
||||||
undefined,
|
{ members: Member[]; users: User[] } | undefined
|
||||||
);
|
>(undefined);
|
||||||
|
|
||||||
const store = useData();
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const users = members?.map((member) => store.users.get(member._id.user));
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
client.members
|
server.fetchMembers().then(setData);
|
||||||
.fetchMembers(server._id)
|
|
||||||
.then((members) => setMembers(members));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const [roles, setRoles] = useState<string[]>([]);
|
const [roles, setRoles] = useState<string[]>([]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
setRoles(
|
setRoles(
|
||||||
members!.find((x) => x._id.user === selected)?.roles ?? [],
|
data!.members.find((x) => x._id.user === selected)?.roles ?? [],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [selected]);
|
}, [selected]);
|
||||||
|
@ -50,15 +45,15 @@ export const Members = observer(({ server }: Props) => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.userList}>
|
<div className={styles.userList}>
|
||||||
<div className={styles.subtitle}>
|
<div className={styles.subtitle}>
|
||||||
{members?.length ?? 0} Members
|
{data?.members.length ?? 0} Members
|
||||||
</div>
|
</div>
|
||||||
{members &&
|
{data &&
|
||||||
members.length > 0 &&
|
data.members.length > 0 &&
|
||||||
members
|
data.members
|
||||||
.map((member, index) => {
|
.map((member, index) => {
|
||||||
return {
|
return {
|
||||||
member,
|
member,
|
||||||
user: users![index],
|
user: data.users[index],
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.map(({ member, user }) => (
|
.map(({ member, user }) => (
|
||||||
|
@ -130,27 +125,11 @@ export const Members = observer(({ server }: Props) => {
|
||||||
member.roles ?? [],
|
member.roles ?? [],
|
||||||
roles,
|
roles,
|
||||||
)}
|
)}
|
||||||
onClick={async () => {
|
onClick={() =>
|
||||||
await client.members.editMember(
|
member.edit({
|
||||||
server._id,
|
roles,
|
||||||
member._id.user,
|
})
|
||||||
{
|
}>
|
||||||
roles,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
setMembers(
|
|
||||||
members.map((x) =>
|
|
||||||
x._id.user ===
|
|
||||||
member._id.user
|
|
||||||
? {
|
|
||||||
...x,
|
|
||||||
roles,
|
|
||||||
}
|
|
||||||
: x,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}}>
|
|
||||||
<Text id="app.special.modals.actions.save" />
|
<Text id="app.special.modals.actions.save" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import isEqual from "lodash.isequal";
|
import isEqual from "lodash.isequal";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Servers } from "revolt.js/dist/api/objects";
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
|
|
||||||
import styles from "./Panes.module.scss";
|
import styles from "./Panes.module.scss";
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
|
@ -8,11 +8,8 @@ import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
|
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
|
||||||
|
|
||||||
import { Server } from "../../../mobx";
|
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
|
|
||||||
import { FileUploader } from "../../../context/revoltjs/FileUploads";
|
import { FileUploader } from "../../../context/revoltjs/FileUploads";
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
import { AppContext, useClient } from "../../../context/revoltjs/RevoltClient";
|
||||||
import { getChannelName } from "../../../context/revoltjs/util";
|
import { getChannelName } from "../../../context/revoltjs/util";
|
||||||
|
|
||||||
import Button from "../../../components/ui/Button";
|
import Button from "../../../components/ui/Button";
|
||||||
|
@ -24,8 +21,7 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Overview = observer(({ server }: Props) => {
|
export const Overview = observer(({ server }: Props) => {
|
||||||
const client = useContext(AppContext);
|
const client = useClient();
|
||||||
const store = useData();
|
|
||||||
|
|
||||||
const [name, setName] = useState(server.name);
|
const [name, setName] = useState(server.name);
|
||||||
const [description, setDescription] = useState(server.description ?? "");
|
const [description, setDescription] = useState(server.description ?? "");
|
||||||
|
@ -45,16 +41,14 @@ export const Overview = observer(({ server }: Props) => {
|
||||||
|
|
||||||
const [changed, setChanged] = useState(false);
|
const [changed, setChanged] = useState(false);
|
||||||
function save() {
|
function save() {
|
||||||
const changes: Partial<
|
const changes: Record<string, any> = {};
|
||||||
Pick<Servers.Server, "name" | "description" | "system_messages">
|
|
||||||
> = {};
|
|
||||||
if (name !== server.name) changes.name = name;
|
if (name !== server.name) changes.name = name;
|
||||||
if (description !== server.description)
|
if (description !== server.description)
|
||||||
changes.description = description;
|
changes.description = description;
|
||||||
if (!isEqual(systemMessages, server.system_messages))
|
if (!isEqual(systemMessages, server.system_messages))
|
||||||
changes.system_messages = systemMessages ?? undefined;
|
changes.system_messages = systemMessages ?? undefined;
|
||||||
|
|
||||||
client.servers.edit(server._id, changes);
|
server.edit(changes);
|
||||||
setChanged(false);
|
setChanged(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,17 +62,9 @@ export const Overview = observer(({ server }: Props) => {
|
||||||
fileType="icons"
|
fileType="icons"
|
||||||
behaviour="upload"
|
behaviour="upload"
|
||||||
maxFileSize={2_500_000}
|
maxFileSize={2_500_000}
|
||||||
onUpload={(icon) =>
|
onUpload={(icon) => server.edit({ icon })}
|
||||||
client.servers.edit(server._id, { icon })
|
previewURL={server.generateIconURL({ max_side: 256 }, true)}
|
||||||
}
|
remove={() => server.edit({ remove: "Icon" })}
|
||||||
previewURL={client.servers.getIconURL(
|
|
||||||
server._id,
|
|
||||||
{ max_side: 256 },
|
|
||||||
true,
|
|
||||||
)}
|
|
||||||
remove={() =>
|
|
||||||
client.servers.edit(server._id, { remove: "Icon" })
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<div className={styles.name}>
|
<div className={styles.name}>
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -120,17 +106,9 @@ export const Overview = observer(({ server }: Props) => {
|
||||||
fileType="banners"
|
fileType="banners"
|
||||||
behaviour="upload"
|
behaviour="upload"
|
||||||
maxFileSize={6_000_000}
|
maxFileSize={6_000_000}
|
||||||
onUpload={(banner) =>
|
onUpload={(banner) => server.edit({ banner })}
|
||||||
client.servers.edit(server._id, { banner })
|
previewURL={server.generateBannerURL({ width: 1000 }, true)}
|
||||||
}
|
remove={() => server.edit({ remove: "Banner" })}
|
||||||
previewURL={client.servers.getBannerURL(
|
|
||||||
server._id,
|
|
||||||
{ width: 1000 },
|
|
||||||
true,
|
|
||||||
)}
|
|
||||||
remove={() =>
|
|
||||||
client.servers.edit(server._id, { remove: "Banner" })
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -176,11 +154,10 @@ export const Overview = observer(({ server }: Props) => {
|
||||||
<Text id="general.disabled" />
|
<Text id="general.disabled" />
|
||||||
</option>
|
</option>
|
||||||
{server.channels
|
{server.channels
|
||||||
.map((id) => store.channels.get(id)!)
|
|
||||||
.filter((x) => typeof x !== "undefined")
|
.filter((x) => typeof x !== "undefined")
|
||||||
.map((channel) => (
|
.map((channel) => (
|
||||||
<option value={channel._id}>
|
<option value={channel!._id}>
|
||||||
{getChannelName(client, channel, true)}
|
{getChannelName(channel!, true)}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
import { Plus } from "@styled-icons/boxicons-regular";
|
import { Plus } from "@styled-icons/boxicons-regular";
|
||||||
import isEqual from "lodash.isequal";
|
import isEqual from "lodash.isequal";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Servers } from "revolt.js/dist/api/objects";
|
import { ChannelPermission, ServerPermission } from "revolt.js";
|
||||||
import {
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
ChannelPermission,
|
|
||||||
ServerPermission,
|
|
||||||
} from "revolt.js/dist/api/permissions";
|
|
||||||
|
|
||||||
import styles from "./Panes.module.scss";
|
import styles from "./Panes.module.scss";
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { Server } from "../../../mobx";
|
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
|
@ -73,20 +68,20 @@ export const Roles = observer(({ server }: Props) => {
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
if (!isEqual(perm, getPermissions(role))) {
|
if (!isEqual(perm, getPermissions(role))) {
|
||||||
client.servers.setPermissions(server._id, role, {
|
server.setPermissions(role, {
|
||||||
server: perm[0],
|
server: perm[0],
|
||||||
channel: perm[1],
|
channel: perm[1],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEqual(name, roleName) || !isEqual(colour, roleColour)) {
|
if (!isEqual(name, roleName) || !isEqual(colour, roleColour)) {
|
||||||
client.servers.editRole(server._id, role, { name, colour });
|
server.editRole(role, { name, colour });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteRole = () => {
|
const deleteRole = () => {
|
||||||
setRole("default");
|
setRole("default");
|
||||||
client.servers.deleteRole(server._id, role);
|
server.deleteRole(role);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import localForage from "localforage";
|
import localForage from "localforage";
|
||||||
import { createStore } from "redux";
|
import { createStore } from "redux";
|
||||||
import { Core } from "revolt.js/dist/api/objects";
|
import { RevoltConfiguration } from "revolt-api/types/Core";
|
||||||
|
|
||||||
import { Language } from "../context/Locale";
|
import { Language } from "../context/Locale";
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import { Typing } from "./reducers/typing";
|
||||||
import { Unreads } from "./reducers/unreads";
|
import { Unreads } from "./reducers/unreads";
|
||||||
|
|
||||||
export type State = {
|
export type State = {
|
||||||
config: Core.RevoltNodeConfiguration;
|
config: RevoltConfiguration;
|
||||||
locale: Language;
|
locale: Language;
|
||||||
auth: AuthState;
|
auth: AuthState;
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import type { Auth } from "revolt.js/dist/api/objects";
|
import { Session } from "revolt-api/types/Auth";
|
||||||
|
|
||||||
export interface AuthState {
|
export interface AuthState {
|
||||||
accounts: {
|
accounts: {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
session: Auth.Session;
|
session: Session;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
active?: string;
|
active?: string;
|
||||||
|
@ -13,7 +13,7 @@ export type AuthAction =
|
||||||
| { type: undefined }
|
| { type: undefined }
|
||||||
| {
|
| {
|
||||||
type: "LOGIN";
|
type: "LOGIN";
|
||||||
session: Auth.Session;
|
session: Session;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: "LOGOUT";
|
type: "LOGOUT";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type { Channel, Message } from "revolt.js";
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
|
|
||||||
import type { SyncUpdateAction } from "./sync";
|
import type { SyncUpdateAction } from "./sync";
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ export function shouldNotify(
|
||||||
case "none":
|
case "none":
|
||||||
return false;
|
return false;
|
||||||
case "mention": {
|
case "mention": {
|
||||||
if (!message.mentions?.includes(user_id)) return false;
|
if (!message.mention_ids?.includes(user_id)) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import type { MessageObject } from "../../context/revoltjs/util";
|
|
||||||
|
|
||||||
export enum QueueStatus {
|
export enum QueueStatus {
|
||||||
SENDING = "sending",
|
SENDING = "sending",
|
||||||
ERRORED = "errored",
|
ERRORED = "errored",
|
||||||
|
@ -10,7 +8,7 @@ export interface Reply {
|
||||||
mention: boolean;
|
mention: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type QueuedMessageData = Omit<MessageObject, "content" | "replies"> & {
|
export type QueuedMessageData = {
|
||||||
content: string;
|
content: string;
|
||||||
replies: Reply[];
|
replies: Reply[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import type { Core } from "revolt.js/dist/api/objects";
|
import type { RevoltConfiguration } from "revolt-api/types/Core";
|
||||||
|
|
||||||
export type ConfigAction =
|
export type ConfigAction =
|
||||||
| { type: undefined }
|
| { type: undefined }
|
||||||
| {
|
| {
|
||||||
type: "SET_CONFIG";
|
type: "SET_CONFIG";
|
||||||
config: Core.RevoltNodeConfiguration;
|
config: RevoltConfiguration;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function config(
|
export function config(
|
||||||
state = {} as Core.RevoltNodeConfiguration,
|
state = {} as RevoltConfiguration,
|
||||||
action: ConfigAction,
|
action: ConfigAction,
|
||||||
): Core.RevoltNodeConfiguration {
|
): RevoltConfiguration {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "SET_CONFIG":
|
case "SET_CONFIG":
|
||||||
return action.config;
|
return action.config;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { Sync } from "revolt.js/dist/api/objects";
|
import type { ChannelUnread } from "revolt-api/types/Sync";
|
||||||
|
|
||||||
export interface Unreads {
|
export interface Unreads {
|
||||||
[key: string]: Partial<Omit<Sync.ChannelUnread, "_id">>;
|
[key: string]: Partial<Omit<ChannelUnread, "_id">>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UnreadsAction =
|
export type UnreadsAction =
|
||||||
|
@ -13,7 +13,7 @@ export type UnreadsAction =
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: "UNREADS_SET";
|
type: "UNREADS_SET";
|
||||||
unreads: Sync.ChannelUnread[];
|
unreads: ChannelUnread[];
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: "UNREADS_MENTION";
|
type: "UNREADS_MENTION";
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/// <reference lib="webworker" />
|
/// <reference lib="webworker" />
|
||||||
import { IDBPDatabase, openDB } from "idb";
|
import { IDBPDatabase, openDB } from "idb";
|
||||||
import { getItem } from "localforage";
|
import { getItem } from "localforage";
|
||||||
import { Channel, Message, User } from "revolt.js";
|
// import { Channel, Message, User } from "revolt.js";
|
||||||
import { Server } from "revolt.js/dist/api/objects";
|
// import { Server } from "revolt.js/dist/api/objects";
|
||||||
import { precacheAndRoute } from "workbox-precaching";
|
import { precacheAndRoute } from "workbox-precaching";
|
||||||
|
|
||||||
import type { State } from "./redux";
|
import type { State } from "./redux";
|
||||||
|
@ -43,7 +43,8 @@ function decodeTime(id: string) {
|
||||||
self.addEventListener("push", (event) => {
|
self.addEventListener("push", (event) => {
|
||||||
async function process() {
|
async function process() {
|
||||||
if (event.data === null) return;
|
if (event.data === null) return;
|
||||||
const data: Message = event.data.json();
|
// ! FIXME: removed until client data is saved to local storage
|
||||||
|
/* const data: Message = event.data.json();
|
||||||
|
|
||||||
const item = await localStorage.getItem("state");
|
const item = await localStorage.getItem("state");
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
@ -142,7 +143,7 @@ self.addEventListener("push", (event) => {
|
||||||
channel?.channel_type === "TextChannel"
|
channel?.channel_type === "TextChannel"
|
||||||
? `/server/${channel.server}/channel/${channel._id}`
|
? `/server/${channel.server}/channel/${channel._id}`
|
||||||
: `/channel/${data.channel}`,
|
: `/channel/${data.channel}`,
|
||||||
});
|
}); */
|
||||||
}
|
}
|
||||||
|
|
||||||
event.waitUntil(process());
|
event.waitUntil(process());
|
||||||
|
|
24
yarn.lock
24
yarn.lock
|
@ -1114,14 +1114,6 @@
|
||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
|
||||||
integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
|
integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
|
||||||
|
|
||||||
"@insertish/mutable@1.1.0":
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@insertish/mutable/-/mutable-1.1.0.tgz#06f95f855691ccb69ee3c339887a80bcd1498116"
|
|
||||||
integrity sha512-NH7aCGFAKRE1gFprrW/HsJoWCWQy18TZBarxLdeLVWdLFvkb2lD6Z5B70oOoUHFNpykiTC8IcRonsd9Xn13n8Q==
|
|
||||||
dependencies:
|
|
||||||
eventemitter3 "^4.0.7"
|
|
||||||
lodash.isequal "^4.5.0"
|
|
||||||
|
|
||||||
"@mdn/browser-compat-data@^2.0.7":
|
"@mdn/browser-compat-data@^2.0.7":
|
||||||
version "2.0.7"
|
version "2.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/@mdn/browser-compat-data/-/browser-compat-data-2.0.7.tgz#72ec37b9c1e00ce0b4e0309d753be18e2da12ee3"
|
resolved "https://registry.yarnpkg.com/@mdn/browser-compat-data/-/browser-compat-data-2.0.7.tgz#72ec37b9c1e00ce0b4e0309d753be18e2da12ee3"
|
||||||
|
@ -3573,17 +3565,23 @@ reusify@^1.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||||
|
|
||||||
revolt.js@4.4.0-alpha.0:
|
revolt-api@0.5.1-alpha.10-patch.0:
|
||||||
version "4.4.0-alpha.0"
|
version "0.5.1-alpha.10-patch.0"
|
||||||
resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.4.0-alpha.0.tgz#6b8d7e5605c4e106800ebd7ddcda8215a8fb289b"
|
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.1-alpha.10-patch.0.tgz#97d31bec7dfa4573567097443acb059c4feaac20"
|
||||||
integrity sha512-TPb7FCC1xpAO0hJ19tXAC5ZwsceJ/yzkFlV/lESteVk4bboVINhRrsElYtJvjSKci7Ft70t0e4bbm8YSYjAblA==
|
integrity sha512-UyM890HkGlYNQOxpHuEpUsJHLt8Ujnjg9/zPEDGpbvS4iy0jmHX23Hh8tOCfb/ewxbNrtT3G1HpSWKOneW/vYg==
|
||||||
|
|
||||||
|
revolt.js@5.0.0-alpha.5:
|
||||||
|
version "5.0.0-alpha.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-5.0.0-alpha.5.tgz#96008a1bf91e80b17ff877b59ca3f4fd9151055d"
|
||||||
|
integrity sha512-HOMblFOR25pE1NMGK4EYgvWqfWADyiGTZlvFpio8CEca3lAmr2jWjJAly5BWMy1SwFcfHmtHIy6Lm5Pkgjop9Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@insertish/mutable" "1.1.0"
|
|
||||||
axios "^0.19.2"
|
axios "^0.19.2"
|
||||||
eventemitter3 "^4.0.7"
|
eventemitter3 "^4.0.7"
|
||||||
exponential-backoff "^3.1.0"
|
exponential-backoff "^3.1.0"
|
||||||
isomorphic-ws "^4.0.1"
|
isomorphic-ws "^4.0.1"
|
||||||
lodash.defaultsdeep "^4.6.1"
|
lodash.defaultsdeep "^4.6.1"
|
||||||
|
lodash.isequal "^4.5.0"
|
||||||
|
mobx "^6.3.2"
|
||||||
tsc-watch "^4.1.0"
|
tsc-watch "^4.1.0"
|
||||||
ulid "^2.3.0"
|
ulid "^2.3.0"
|
||||||
ws "^7.2.1"
|
ws "^7.2.1"
|
||||||
|
|
Loading…
Reference in a new issue