mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-29 10:20:59 -05:00
100 error milestone.
Remove hooks completely. :)
This commit is contained in:
parent
3184269ba4
commit
c21453b281
22 changed files with 257 additions and 506 deletions
|
@ -1,17 +1,14 @@
|
||||||
import { Money } from "@styled-icons/boxicons-regular";
|
import { Money } from "@styled-icons/boxicons-regular";
|
||||||
import { Envelope, Edit, UserPlus, Shield } from "@styled-icons/boxicons-solid";
|
import { Envelope, Edit, UserPlus, Shield } from "@styled-icons/boxicons-solid";
|
||||||
import { Link, useHistory } from "react-router-dom";
|
import { Link, useHistory } from "react-router-dom";
|
||||||
import { Users } from "revolt.js/dist/api/objects";
|
import { Profile, RelationshipStatus } from "revolt-api/types/Users";
|
||||||
import { UserPermission } from "revolt.js/dist/api/permissions";
|
import { UserPermission } from "revolt.js/dist/api/permissions";
|
||||||
import { Route } from "revolt.js/dist/api/routes";
|
import { Route } from "revolt.js/dist/api/routes";
|
||||||
import { decodeTime } from "ulid";
|
|
||||||
|
|
||||||
import styles from "./UserProfile.module.scss";
|
import styles from "./UserProfile.module.scss";
|
||||||
import { Localizer, Text } from "preact-i18n";
|
import { Localizer, Text } from "preact-i18n";
|
||||||
import { useContext, useEffect, useLayoutEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useLayoutEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
|
|
||||||
import ChannelIcon from "../../../components/common/ChannelIcon";
|
import ChannelIcon from "../../../components/common/ChannelIcon";
|
||||||
import Tooltip from "../../../components/common/Tooltip";
|
import Tooltip from "../../../components/common/Tooltip";
|
||||||
import UserIcon from "../../../components/common/user/UserIcon";
|
import UserIcon from "../../../components/common/user/UserIcon";
|
||||||
|
@ -27,14 +24,13 @@ import {
|
||||||
StatusContext,
|
StatusContext,
|
||||||
useClient,
|
useClient,
|
||||||
} from "../../revoltjs/RevoltClient";
|
} from "../../revoltjs/RevoltClient";
|
||||||
import { useForceUpdate, useUserPermission } from "../../revoltjs/hooks";
|
|
||||||
import { useIntermediate } from "../Intermediate";
|
import { useIntermediate } from "../Intermediate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user_id: string;
|
user_id: string;
|
||||||
dummy?: boolean;
|
dummy?: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
dummyProfile?: Users.Profile;
|
dummyProfile?: Profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Badges {
|
enum Badges {
|
||||||
|
@ -48,7 +44,7 @@ enum Badges {
|
||||||
export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
const { openScreen, writeClipboard } = useIntermediate();
|
const { openScreen, writeClipboard } = useIntermediate();
|
||||||
|
|
||||||
const [profile, setProfile] = useState<undefined | null | Users.Profile>(
|
const [profile, setProfile] = useState<undefined | null | Profile>(
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
const [mutual, setMutual] = useState<
|
const [mutual, setMutual] = useState<
|
||||||
|
@ -60,22 +56,18 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
const status = useContext(StatusContext);
|
const status = useContext(StatusContext);
|
||||||
const [tab, setTab] = useState("profile");
|
const [tab, setTab] = useState("profile");
|
||||||
|
|
||||||
const ctx = useForceUpdate();
|
const user = client.users.get(user_id);
|
||||||
const permissions = useUserPermission(client.user!._id, ctx);
|
if (!user) {
|
||||||
|
|
||||||
const store = useData();
|
|
||||||
if (!store.users.has(user_id)) {
|
|
||||||
useEffect(onClose, []);
|
useEffect(onClose, []);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = store.users.get(user_id)!;
|
const users = mutual?.users.map((id) => client.users.get(id));
|
||||||
const users = mutual?.users.map((id) => store.users.get(id));
|
|
||||||
|
|
||||||
const mutualGroups = [...store.channels.values()].filter(
|
const mutualGroups = [...client.channels.values()].filter(
|
||||||
(channel) =>
|
(channel) =>
|
||||||
channel?.channel_type === "Group" &&
|
channel?.channel_type === "Group" &&
|
||||||
channel.recipients!.includes(user_id),
|
channel.recipient_ids!.includes(user_id),
|
||||||
);
|
);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
|
@ -94,7 +86,7 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
if (dummy) return;
|
if (dummy) return;
|
||||||
if (status === ClientStatus.ONLINE && typeof mutual === "undefined") {
|
if (status === ClientStatus.ONLINE && typeof mutual === "undefined") {
|
||||||
setMutual(null);
|
setMutual(null);
|
||||||
client.users.fetchMutual(user_id).then((data) => setMutual(data));
|
user.fetchMutual().then(setMutual);
|
||||||
}
|
}
|
||||||
}, [mutual, status]);
|
}, [mutual, status]);
|
||||||
|
|
||||||
|
@ -103,10 +95,9 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
if (status === ClientStatus.ONLINE && typeof profile === "undefined") {
|
if (status === ClientStatus.ONLINE && typeof profile === "undefined") {
|
||||||
setProfile(null);
|
setProfile(null);
|
||||||
|
|
||||||
if (permissions & UserPermission.ViewProfile) {
|
if (user.permission & UserPermission.ViewProfile) {
|
||||||
client.users
|
user.fetchProfile()
|
||||||
.fetchProfile(user_id)
|
.then(setProfile)
|
||||||
.then((data) => setProfile(data))
|
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,10 +105,8 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
|
|
||||||
const backgroundURL =
|
const backgroundURL =
|
||||||
profile &&
|
profile &&
|
||||||
client.users.getBackgroundURL(profile, { width: 1000 }, true);
|
client.generateFileURL(profile.background, { width: 1000 }, true);
|
||||||
const badges =
|
const badges = user.badges ?? 0;
|
||||||
(user.badges ?? 0) |
|
|
||||||
(decodeTime(user._id) < 1623751765790 ? Badges.EarlyAdopter : 0);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -150,7 +139,7 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{user.relationship === Users.Relationship.Friend && (
|
{user.relationship === RelationshipStatus.Friend && (
|
||||||
<Localizer>
|
<Localizer>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
|
@ -166,7 +155,7 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Localizer>
|
</Localizer>
|
||||||
)}
|
)}
|
||||||
{user.relationship === Users.Relationship.User && (
|
{user.relationship === RelationshipStatus.User && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onClose();
|
onClose();
|
||||||
|
@ -176,12 +165,9 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
<Edit size={28} />
|
<Edit size={28} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
{(user.relationship === Users.Relationship.Incoming ||
|
{(user.relationship === RelationshipStatus.Incoming ||
|
||||||
user.relationship === Users.Relationship.None) && (
|
user.relationship === RelationshipStatus.None) && (
|
||||||
<IconButton
|
<IconButton onClick={() => user.addFriend()}>
|
||||||
onClick={() =>
|
|
||||||
client.users.addFriend(user.username)
|
|
||||||
}>
|
|
||||||
<UserPlus size={28} />
|
<UserPlus size={28} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
|
@ -192,7 +178,7 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
onClick={() => setTab("profile")}>
|
onClick={() => setTab("profile")}>
|
||||||
<Text id="app.special.popovers.user_profile.profile" />
|
<Text id="app.special.popovers.user_profile.profile" />
|
||||||
</div>
|
</div>
|
||||||
{user.relationship !== Users.Relationship.User && (
|
{user.relationship !== RelationshipStatus.User && (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
data-active={tab === "friends"}
|
data-active={tab === "friends"}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import { autorun } from "mobx";
|
||||||
import { Route, Switch, useHistory, useParams } from "react-router-dom";
|
import { Route, Switch, useHistory, useParams } from "react-router-dom";
|
||||||
import { Message, SYSTEM_USER_ID, User } from "revolt.js";
|
import { Presence, RelationshipStatus } from "revolt-api/types/Users";
|
||||||
import { Users } from "revolt.js/dist/api/objects";
|
import { SYSTEM_USER_ID } from "revolt.js";
|
||||||
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
import { decodeTime } from "ulid";
|
import { decodeTime } from "ulid";
|
||||||
|
|
||||||
import { useContext, useEffect } from "preact/hooks";
|
import { useContext, useEffect } from "preact/hooks";
|
||||||
|
@ -50,41 +52,36 @@ function Notifier({ options, notifs }: Props) {
|
||||||
const playSound = useContext(SoundContext);
|
const playSound = useContext(SoundContext);
|
||||||
|
|
||||||
async function message(msg: Message) {
|
async function message(msg: Message) {
|
||||||
if (msg.author === client.user!._id) return;
|
if (msg.author_id === client.user!._id) return;
|
||||||
if (msg.channel === channel_id && document.hasFocus()) return;
|
if (msg.channel_id === channel_id && document.hasFocus()) return;
|
||||||
if (client.user!.status?.presence === Users.Presence.Busy) return;
|
if (client.user!.status?.presence === Presence.Busy) return;
|
||||||
|
if (msg.author?.relationship === RelationshipStatus.Blocked) return;
|
||||||
|
|
||||||
const channel = client.channels.get(msg.channel);
|
const notifState = getNotificationState(notifs, msg.channel!);
|
||||||
const author = client.users.get(msg.author);
|
|
||||||
if (!channel) return;
|
|
||||||
if (author?.relationship === Users.Relationship.Blocked) return;
|
|
||||||
|
|
||||||
const notifState = getNotificationState(notifs, channel);
|
|
||||||
if (!shouldNotify(notifState, msg, client.user!._id)) return;
|
if (!shouldNotify(notifState, msg, client.user!._id)) return;
|
||||||
|
|
||||||
playSound("message");
|
playSound("message");
|
||||||
if (!showNotification) return;
|
if (!showNotification) return;
|
||||||
|
|
||||||
let title;
|
let title;
|
||||||
switch (channel.channel_type) {
|
switch (msg.channel?.channel_type) {
|
||||||
case "SavedMessages":
|
case "SavedMessages":
|
||||||
return;
|
return;
|
||||||
case "DirectMessage":
|
case "DirectMessage":
|
||||||
title = `@${author?.username}`;
|
title = `@${msg.author?.username}`;
|
||||||
break;
|
break;
|
||||||
case "Group":
|
case "Group":
|
||||||
if (author?._id === SYSTEM_USER_ID) {
|
if (msg.author?._id === SYSTEM_USER_ID) {
|
||||||
title = channel.name;
|
title = msg.channel.name;
|
||||||
} else {
|
} else {
|
||||||
title = `@${author?.username} - ${channel.name}`;
|
title = `@${msg.author?.username} - ${msg.channel.name}`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "TextChannel":
|
case "TextChannel":
|
||||||
const server = client.servers.get(channel.server);
|
title = `@${msg.author?.username} (#${msg.channel.name}, ${msg.channel.server?.name})`;
|
||||||
title = `@${author?.username} (#${channel.name}, ${server?.name})`;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
title = msg.channel;
|
title = msg.channel?._id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,70 +100,82 @@ function Notifier({ options, notifs }: Props) {
|
||||||
let body, icon;
|
let body, icon;
|
||||||
if (typeof msg.content === "string") {
|
if (typeof msg.content === "string") {
|
||||||
body = client.markdownToText(msg.content);
|
body = client.markdownToText(msg.content);
|
||||||
icon = client.users.getAvatarURL(msg.author, { max_side: 256 });
|
icon = msg.author?.generateAvatarURL({ max_side: 256 });
|
||||||
} else {
|
} else {
|
||||||
const users = client.users;
|
const users = client.users;
|
||||||
switch (msg.content.type) {
|
switch (msg.content.type) {
|
||||||
case "user_added":
|
case "user_added":
|
||||||
case "user_remove":
|
case "user_remove":
|
||||||
body = translate(
|
{
|
||||||
`app.main.channel.system.${
|
let user = users.get(msg.content.id);
|
||||||
msg.content.type === "user_added"
|
body = translate(
|
||||||
? "added_by"
|
`app.main.channel.system.${
|
||||||
: "removed_by"
|
msg.content.type === "user_added"
|
||||||
}`,
|
? "added_by"
|
||||||
{
|
: "removed_by"
|
||||||
user: users.get(msg.content.id)?.username,
|
}`,
|
||||||
other_user: users.get(msg.content.by)?.username,
|
{
|
||||||
},
|
user: user?.username,
|
||||||
);
|
other_user: users.get(msg.content.by)?.username,
|
||||||
icon = client.users.getAvatarURL(msg.content.id, {
|
},
|
||||||
max_side: 256,
|
);
|
||||||
});
|
icon = user?.generateAvatarURL({
|
||||||
|
max_side: 256,
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "user_joined":
|
case "user_joined":
|
||||||
case "user_left":
|
case "user_left":
|
||||||
case "user_kicked":
|
case "user_kicked":
|
||||||
case "user_banned":
|
case "user_banned":
|
||||||
body = translate(
|
{
|
||||||
`app.main.channel.system.${msg.content.type}`,
|
let user = users.get(msg.content.id);
|
||||||
{ user: users.get(msg.content.id)?.username },
|
body = translate(
|
||||||
);
|
`app.main.channel.system.${msg.content.type}`,
|
||||||
icon = client.users.getAvatarURL(msg.content.id, {
|
{ user: user?.username },
|
||||||
max_side: 256,
|
);
|
||||||
});
|
icon = user?.generateAvatarURL({
|
||||||
|
max_side: 256,
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "channel_renamed":
|
case "channel_renamed":
|
||||||
body = translate(
|
{
|
||||||
`app.main.channel.system.channel_renamed`,
|
let user = users.get(msg.content.by);
|
||||||
{
|
body = translate(
|
||||||
user: users.get(msg.content.by)?.username,
|
`app.main.channel.system.channel_renamed`,
|
||||||
name: msg.content.name,
|
{
|
||||||
},
|
user: users.get(msg.content.by)?.username,
|
||||||
);
|
name: msg.content.name,
|
||||||
icon = client.users.getAvatarURL(msg.content.by, {
|
},
|
||||||
max_side: 256,
|
);
|
||||||
});
|
icon = user?.generateAvatarURL({
|
||||||
|
max_side: 256,
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "channel_description_changed":
|
case "channel_description_changed":
|
||||||
case "channel_icon_changed":
|
case "channel_icon_changed":
|
||||||
body = translate(
|
{
|
||||||
`app.main.channel.system.${msg.content.type}`,
|
let user = users.get(msg.content.by);
|
||||||
{ user: users.get(msg.content.by)?.username },
|
body = translate(
|
||||||
);
|
`app.main.channel.system.${msg.content.type}`,
|
||||||
icon = client.users.getAvatarURL(msg.content.by, {
|
{ user: users.get(msg.content.by)?.username },
|
||||||
max_side: 256,
|
);
|
||||||
});
|
icon = user?.generateAvatarURL({
|
||||||
|
max_side: 256,
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const notif = await createNotification(title, {
|
const notif = await createNotification(title!, {
|
||||||
icon,
|
icon,
|
||||||
image,
|
image,
|
||||||
body,
|
body,
|
||||||
timestamp: decodeTime(msg._id),
|
timestamp: decodeTime(msg._id),
|
||||||
tag: msg.channel,
|
tag: msg.channel?._id,
|
||||||
badge: "/assets/icons/android-chrome-512x512.png",
|
badge: "/assets/icons/android-chrome-512x512.png",
|
||||||
silent: true,
|
silent: true,
|
||||||
});
|
});
|
||||||
|
@ -174,7 +183,7 @@ function Notifier({ options, notifs }: Props) {
|
||||||
if (notif) {
|
if (notif) {
|
||||||
notif.addEventListener("click", () => {
|
notif.addEventListener("click", () => {
|
||||||
window.focus();
|
window.focus();
|
||||||
const id = msg.channel;
|
const id = msg.channel_id;
|
||||||
if (id !== channel_id) {
|
if (id !== channel_id) {
|
||||||
const channel = client.channels.get(id);
|
const channel = client.channels.get(id);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
|
@ -189,15 +198,15 @@ function Notifier({ options, notifs }: Props) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notifications[msg.channel] = notif;
|
notifications[msg.channel_id] = notif;
|
||||||
notif.addEventListener(
|
notif.addEventListener(
|
||||||
"close",
|
"close",
|
||||||
() => delete notifications[msg.channel],
|
() => delete notifications[msg.channel_id],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function relationship(user: User, property: string) {
|
/*async function relationship(user: User, property: string) {
|
||||||
if (client.user?.status?.presence === Users.Presence.Busy) return;
|
if (client.user?.status?.presence === Users.Presence.Busy) return;
|
||||||
if (property !== "relationship") return;
|
if (property !== "relationship") return;
|
||||||
if (!showNotification) return;
|
if (!showNotification) return;
|
||||||
|
@ -219,7 +228,7 @@ function Notifier({ options, notifs }: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const notif = await createNotification(event, {
|
const notif = await createNotification(event, {
|
||||||
icon: client.users.getAvatarURL(user._id, { max_side: 256 }),
|
icon: user.generateAvatarURL({ max_side: 256 }),
|
||||||
badge: "/assets/icons/android-chrome-512x512.png",
|
badge: "/assets/icons/android-chrome-512x512.png",
|
||||||
timestamp: +new Date(),
|
timestamp: +new Date(),
|
||||||
});
|
});
|
||||||
|
@ -227,15 +236,17 @@ function Notifier({ options, notifs }: Props) {
|
||||||
notif?.addEventListener("click", () => {
|
notif?.addEventListener("click", () => {
|
||||||
history.push(`/friends`);
|
history.push(`/friends`);
|
||||||
});
|
});
|
||||||
}
|
}*/
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// ! FIXME: need event from client about relationship
|
||||||
|
|
||||||
client.addListener("message", message);
|
client.addListener("message", message);
|
||||||
client.users.addListener("mutation", relationship);
|
// client.users.addListener("mutation", relationship);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
client.removeListener("message", message);
|
client.removeListener("message", message);
|
||||||
client.users.removeListener("mutation", relationship);
|
// client.users.removeListener("mutation", relationship);
|
||||||
};
|
};
|
||||||
}, [client, playSound, guild_id, channel_id, showNotification, notifs]);
|
}, [client, playSound, guild_id, channel_id, showNotification, notifs]);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { SingletonMessageRenderer } from "../../lib/renderer/Singleton";
|
import { SingletonMessageRenderer } from "../../lib/renderer/Singleton";
|
||||||
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
import { dispatch } from "../../redux";
|
import { dispatch } from "../../redux";
|
||||||
import { connectState } from "../../redux/connector";
|
import { connectState } from "../../redux/connector";
|
||||||
import { AuthState } from "../../redux/reducers/auth";
|
import { AuthState } from "../../redux/reducers/auth";
|
||||||
|
@ -36,8 +35,6 @@ export interface ClientOperations {
|
||||||
logout: (shouldRequest?: boolean) => Promise<void>;
|
logout: (shouldRequest?: boolean) => Promise<void>;
|
||||||
loggedIn: () => boolean;
|
loggedIn: () => boolean;
|
||||||
ready: () => boolean;
|
ready: () => boolean;
|
||||||
|
|
||||||
openDM: (user_id: string) => Promise<string>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// By the time they are used, they should all be initialized.
|
// By the time they are used, they should all be initialized.
|
||||||
|
@ -53,7 +50,6 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function Context({ auth, children }: Props) {
|
function Context({ auth, children }: Props) {
|
||||||
const history = useHistory();
|
|
||||||
const { openScreen } = useIntermediate();
|
const { openScreen } = useIntermediate();
|
||||||
const [status, setStatus] = useState(ClientStatus.INIT);
|
const [status, setStatus] = useState(ClientStatus.INIT);
|
||||||
const [client, setClient] = useState<Client>(
|
const [client, setClient] = useState<Client>(
|
||||||
|
@ -89,7 +85,6 @@ function Context({ auth, children }: Props) {
|
||||||
autoReconnect: false,
|
autoReconnect: false,
|
||||||
apiURL: import.meta.env.VITE_API_URL,
|
apiURL: import.meta.env.VITE_API_URL,
|
||||||
debug: import.meta.env.DEV,
|
debug: import.meta.env.DEV,
|
||||||
db,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setClient(client);
|
setClient(client);
|
||||||
|
@ -150,11 +145,6 @@ function Context({ auth, children }: Props) {
|
||||||
loggedIn: () => typeof auth.active !== "undefined",
|
loggedIn: () => typeof auth.active !== "undefined",
|
||||||
ready: () =>
|
ready: () =>
|
||||||
operations.loggedIn() && typeof client.user !== "undefined",
|
operations.loggedIn() && typeof client.user !== "undefined",
|
||||||
openDM: async (user_id: string) => {
|
|
||||||
const channel = await client.users.openDM(user_id);
|
|
||||||
history.push(`/channel/${channel!._id}`);
|
|
||||||
return channel!._id;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}, [client, auth.active]);
|
}, [client, auth.active]);
|
||||||
|
|
||||||
|
@ -165,10 +155,6 @@ function Context({ auth, children }: Props) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
if (client.db) {
|
|
||||||
await client.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auth.active) {
|
if (auth.active) {
|
||||||
dispatch({ type: "QUEUE_FAIL_ALL" });
|
dispatch({ type: "QUEUE_FAIL_ALL" });
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* This file monitors the message cache to delete any queued messages that have already sent.
|
* This file monitors the message cache to delete any queued messages that have already sent.
|
||||||
*/
|
*/
|
||||||
import { Message } from "revolt.js";
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
|
|
||||||
import { useContext, useEffect } from "preact/hooks";
|
import { useContext, useEffect } from "preact/hooks";
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This file monitors changes to settings and syncs them to the server.
|
* This file monitors changes to settings and syncs them to the server.
|
||||||
*/
|
*/
|
||||||
import isEqual from "lodash.isequal";
|
import isEqual from "lodash.isequal";
|
||||||
import { Sync } from "revolt.js/dist/api/objects";
|
import { UserSettings } from "revolt-api/types/Sync";
|
||||||
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
||||||
|
|
||||||
import { useContext, useEffect } from "preact/hooks";
|
import { useContext, useEffect } from "preact/hooks";
|
||||||
|
@ -31,7 +31,7 @@ type Props = {
|
||||||
const lastValues: { [key in SyncKeys]?: any } = {};
|
const lastValues: { [key in SyncKeys]?: any } = {};
|
||||||
|
|
||||||
export function mapSync(
|
export function mapSync(
|
||||||
packet: Sync.UserSettings,
|
packet: UserSettings,
|
||||||
revision?: Record<string, number>,
|
revision?: Record<string, number>,
|
||||||
) {
|
) {
|
||||||
const update: { [key in SyncKeys]?: [number, SyncData[key]] } = {};
|
const update: { [key in SyncKeys]?: [number, SyncData[key]] } = {};
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { Client, Message } from "revolt.js/dist";
|
import { Client } from "revolt.js/dist";
|
||||||
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
||||||
|
|
||||||
import { StateUpdater } from "preact/hooks";
|
import { StateUpdater } from "preact/hooks";
|
||||||
|
|
||||||
import { DataStore } from "../../mobx";
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
import { dispatch } from "../../redux";
|
import { dispatch } from "../../redux";
|
||||||
|
|
||||||
import { ClientOperations, ClientStatus } from "./RevoltClient";
|
import { ClientOperations, ClientStatus } from "./RevoltClient";
|
||||||
|
@ -78,10 +77,10 @@ export function registerEvents(
|
||||||
},
|
},
|
||||||
|
|
||||||
message: (message: Message) => {
|
message: (message: Message) => {
|
||||||
if (message.mentions?.includes(client.user!._id)) {
|
if (message.mention_ids?.includes(client.user!._id)) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "UNREADS_MENTION",
|
type: "UNREADS_MENTION",
|
||||||
channel: message.channel,
|
channel: message.channel_id,
|
||||||
message: message._id,
|
message: message._id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -110,13 +109,6 @@ export function registerEvents(
|
||||||
console.log("(o) Object mutated", target, "\nChanged:", key);
|
console.log("(o) Object mutated", target, "\nChanged:", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import.meta.env.DEV) {
|
|
||||||
client.users.addListener("mutation", logMutation);
|
|
||||||
client.servers.addListener("mutation", logMutation);
|
|
||||||
client.channels.addListener("mutation", logMutation);
|
|
||||||
client.members.addListener("mutation", logMutation);
|
|
||||||
}
|
|
||||||
|
|
||||||
const online = () => {
|
const online = () => {
|
||||||
if (operations.ready()) {
|
if (operations.ready()) {
|
||||||
setStatus(ClientStatus.RECONNECTING);
|
setStatus(ClientStatus.RECONNECTING);
|
||||||
|
@ -144,13 +136,6 @@ export function registerEvents(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import.meta.env.DEV) {
|
|
||||||
client.users.removeListener("mutation", logMutation);
|
|
||||||
client.servers.removeListener("mutation", logMutation);
|
|
||||||
client.channels.removeListener("mutation", logMutation);
|
|
||||||
client.members.removeListener("mutation", logMutation);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.removeEventListener("online", online);
|
window.removeEventListener("online", online);
|
||||||
window.removeEventListener("offline", offline);
|
window.removeEventListener("offline", offline);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
import { Client, PermissionCalculator } from "revolt.js";
|
|
||||||
|
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
|
||||||
|
|
||||||
//#region Hooks v1 (deprecated)
|
|
||||||
import { AppContext } from "./RevoltClient";
|
|
||||||
|
|
||||||
export interface HookContext {
|
|
||||||
client: Client;
|
|
||||||
forceUpdate: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useForceUpdate(context?: HookContext): HookContext {
|
|
||||||
const client = useContext(AppContext);
|
|
||||||
if (context) return context;
|
|
||||||
|
|
||||||
const H = useState(0);
|
|
||||||
let updateState: (_: number) => void;
|
|
||||||
if (Array.isArray(H)) {
|
|
||||||
const [, u] = H;
|
|
||||||
updateState = u;
|
|
||||||
} else {
|
|
||||||
console.warn("Failed to construct using useState.");
|
|
||||||
updateState = () => {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return { client, forceUpdate: () => updateState(Math.random()) };
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUserPermission(id: string, context?: HookContext) {
|
|
||||||
const ctx = useForceUpdate(context);
|
|
||||||
|
|
||||||
const mutation = (target: string) => target === id && ctx.forceUpdate();
|
|
||||||
useEffect(() => {
|
|
||||||
ctx.client.users.addListener("update", mutation);
|
|
||||||
return () => ctx.client.users.removeListener("update", mutation);
|
|
||||||
}, [id]);
|
|
||||||
|
|
||||||
const calculator = new PermissionCalculator(ctx.client);
|
|
||||||
return calculator.forUser(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useChannelPermission(id: string, context?: HookContext) {
|
|
||||||
const ctx = useForceUpdate(context);
|
|
||||||
|
|
||||||
const channel = ctx.client.channels.get(id);
|
|
||||||
const server =
|
|
||||||
channel &&
|
|
||||||
(channel.channel_type === "TextChannel" ||
|
|
||||||
channel.channel_type === "VoiceChannel")
|
|
||||||
? channel.server
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const mutation = (target: string) => target === id && ctx.forceUpdate();
|
|
||||||
const mutationServer = (target: string) =>
|
|
||||||
target === server && ctx.forceUpdate();
|
|
||||||
const mutationMember = (target: string) =>
|
|
||||||
target.substr(26) === ctx.client.user!._id && ctx.forceUpdate();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
ctx.client.channels.addListener("update", mutation);
|
|
||||||
|
|
||||||
if (server) {
|
|
||||||
ctx.client.servers.addListener("update", mutationServer);
|
|
||||||
ctx.client.members.addListener("update", mutationMember);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
ctx.client.channels.removeListener("update", mutation);
|
|
||||||
|
|
||||||
if (server) {
|
|
||||||
ctx.client.servers.removeListener("update", mutationServer);
|
|
||||||
ctx.client.members.removeListener("update", mutationMember);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [id]);
|
|
||||||
|
|
||||||
const calculator = new PermissionCalculator(ctx.client);
|
|
||||||
return calculator.forChannel(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useServerPermission(id: string, context?: HookContext) {
|
|
||||||
const ctx = useForceUpdate(context);
|
|
||||||
|
|
||||||
const mutation = (target: string) => target === id && ctx.forceUpdate();
|
|
||||||
const mutationMember = (target: string) =>
|
|
||||||
target.substr(26) === ctx.client.user!._id && ctx.forceUpdate();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
ctx.client.servers.addListener("update", mutation);
|
|
||||||
ctx.client.members.addListener("update", mutationMember);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
ctx.client.servers.removeListener("update", mutation);
|
|
||||||
ctx.client.members.removeListener("update", mutationMember);
|
|
||||||
};
|
|
||||||
}, [id]);
|
|
||||||
|
|
||||||
const calculator = new PermissionCalculator(ctx.client);
|
|
||||||
return calculator.forServer(id);
|
|
||||||
}
|
|
||||||
//#endregion
|
|
|
@ -12,18 +12,17 @@ import {
|
||||||
} from "@styled-icons/boxicons-regular";
|
} from "@styled-icons/boxicons-regular";
|
||||||
import { Cog, UserVoice } from "@styled-icons/boxicons-solid";
|
import { Cog, UserVoice } from "@styled-icons/boxicons-solid";
|
||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom";
|
||||||
import {
|
import { Attachment } from "revolt-api/types/Autumn";
|
||||||
Attachment,
|
import { Presence, RelationshipStatus } from "revolt-api/types/Users";
|
||||||
Channels,
|
|
||||||
Message,
|
|
||||||
Servers,
|
|
||||||
Users,
|
|
||||||
} from "revolt.js/dist/api/objects";
|
|
||||||
import {
|
import {
|
||||||
ChannelPermission,
|
ChannelPermission,
|
||||||
ServerPermission,
|
ServerPermission,
|
||||||
UserPermission,
|
UserPermission,
|
||||||
} from "revolt.js/dist/api/permissions";
|
} from "revolt.js/dist/api/permissions";
|
||||||
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
|
import { User } from "revolt.js/dist/maps/Users";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
|
@ -34,8 +33,6 @@ import {
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
import { useContext } from "preact/hooks";
|
import { useContext } from "preact/hooks";
|
||||||
|
|
||||||
import { Channel, Server, User } from "../mobx";
|
|
||||||
import { useData } from "../mobx/State";
|
|
||||||
import { dispatch } from "../redux";
|
import { dispatch } from "../redux";
|
||||||
import { connectState } from "../redux/connector";
|
import { connectState } from "../redux/connector";
|
||||||
import {
|
import {
|
||||||
|
@ -52,12 +49,6 @@ import {
|
||||||
StatusContext,
|
StatusContext,
|
||||||
useClient,
|
useClient,
|
||||||
} from "../context/revoltjs/RevoltClient";
|
} from "../context/revoltjs/RevoltClient";
|
||||||
import {
|
|
||||||
useChannelPermission,
|
|
||||||
useForceUpdate,
|
|
||||||
useServerPermission,
|
|
||||||
useUserPermission,
|
|
||||||
} from "../context/revoltjs/hooks";
|
|
||||||
import { takeError } from "../context/revoltjs/util";
|
import { takeError } from "../context/revoltjs/util";
|
||||||
|
|
||||||
import Tooltip from "../components/common/Tooltip";
|
import Tooltip from "../components/common/Tooltip";
|
||||||
|
@ -91,13 +82,13 @@ type Action =
|
||||||
| { action: "reply_message"; id: string }
|
| { action: "reply_message"; id: string }
|
||||||
| { action: "quote_message"; content: string }
|
| { action: "quote_message"; content: string }
|
||||||
| { action: "edit_message"; id: string }
|
| { action: "edit_message"; id: string }
|
||||||
| { action: "delete_message"; target: Channels.Message }
|
| { action: "delete_message"; target: Message }
|
||||||
| { action: "open_file"; attachment: Attachment }
|
| { action: "open_file"; attachment: Attachment }
|
||||||
| { action: "save_file"; attachment: Attachment }
|
| { action: "save_file"; attachment: Attachment }
|
||||||
| { action: "copy_file_link"; attachment: Attachment }
|
| { action: "copy_file_link"; attachment: Attachment }
|
||||||
| { action: "open_link"; link: string }
|
| { action: "open_link"; link: string }
|
||||||
| { action: "copy_link"; link: string }
|
| { action: "copy_link"; link: string }
|
||||||
| { action: "remove_member"; channel: string; user: User }
|
| { action: "remove_member"; channel: Channel; user: User }
|
||||||
| { action: "kick_member"; target: Server; user: User }
|
| { action: "kick_member"; target: Server; user: User }
|
||||||
| { action: "ban_member"; target: Server; user: User }
|
| { action: "ban_member"; target: Server; user: User }
|
||||||
| { action: "view_profile"; user: User }
|
| { action: "view_profile"; user: User }
|
||||||
|
@ -107,7 +98,7 @@ type Action =
|
||||||
| { action: "add_friend"; user: User }
|
| { action: "add_friend"; user: User }
|
||||||
| { action: "remove_friend"; user: User }
|
| { action: "remove_friend"; user: User }
|
||||||
| { action: "cancel_friend"; user: User }
|
| { action: "cancel_friend"; user: User }
|
||||||
| { action: "set_presence"; presence: Users.Presence }
|
| { action: "set_presence"; presence: Presence }
|
||||||
| { action: "set_status" }
|
| { action: "set_status" }
|
||||||
| { action: "clear_status" }
|
| { action: "clear_status" }
|
||||||
| { action: "create_channel"; target: Server }
|
| { action: "create_channel"; target: Server }
|
||||||
|
@ -196,7 +187,8 @@ function ContextMenus(props: Props) {
|
||||||
});
|
});
|
||||||
|
|
||||||
client.channels
|
client.channels
|
||||||
.sendMessage(data.message.channel, {
|
.get(data.message.channel)!
|
||||||
|
.sendMessage({
|
||||||
nonce: data.message.id,
|
nonce: data.message.id,
|
||||||
content: data.message.data.content as string,
|
content: data.message.data.content as string,
|
||||||
replies: data.message.data.replies,
|
replies: data.message.data.replies,
|
||||||
|
@ -313,10 +305,7 @@ function ContextMenus(props: Props) {
|
||||||
|
|
||||||
case "remove_member":
|
case "remove_member":
|
||||||
{
|
{
|
||||||
client.channels.removeMember(
|
data.channel.removeMember(data.user._id);
|
||||||
data.channel,
|
|
||||||
data.user._id,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -326,9 +315,7 @@ function ContextMenus(props: Props) {
|
||||||
|
|
||||||
case "message_user":
|
case "message_user":
|
||||||
{
|
{
|
||||||
const channel = await client.users.openDM(
|
const channel = await data.user.openDM();
|
||||||
data.user._id,
|
|
||||||
);
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
history.push(`/channel/${channel._id}`);
|
history.push(`/channel/${channel._id}`);
|
||||||
}
|
}
|
||||||
|
@ -337,7 +324,7 @@ function ContextMenus(props: Props) {
|
||||||
|
|
||||||
case "add_friend":
|
case "add_friend":
|
||||||
{
|
{
|
||||||
await client.users.addFriend(data.user.username);
|
await data.user.addFriend();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -349,7 +336,7 @@ function ContextMenus(props: Props) {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "unblock_user":
|
case "unblock_user":
|
||||||
await client.users.unblockUser(data.user._id);
|
await data.user.unblockUser();
|
||||||
break;
|
break;
|
||||||
case "remove_friend":
|
case "remove_friend":
|
||||||
openScreen({
|
openScreen({
|
||||||
|
@ -359,12 +346,12 @@ function ContextMenus(props: Props) {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "cancel_friend":
|
case "cancel_friend":
|
||||||
await client.users.removeFriend(data.user._id);
|
await data.user.removeFriend();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "set_presence":
|
case "set_presence":
|
||||||
{
|
{
|
||||||
await client.users.editUser({
|
await client.users.edit({
|
||||||
status: {
|
status: {
|
||||||
...client.user?.status,
|
...client.user?.status,
|
||||||
presence: data.presence,
|
presence: data.presence,
|
||||||
|
@ -383,7 +370,7 @@ function ContextMenus(props: Props) {
|
||||||
case "clear_status":
|
case "clear_status":
|
||||||
{
|
{
|
||||||
const { text, ...status } = client.user?.status ?? {};
|
const { text, ...status } = client.user?.status ?? {};
|
||||||
await client.users.editUser({ status });
|
await client.users.edit({ status });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -463,9 +450,6 @@ function ContextMenus(props: Props) {
|
||||||
unread,
|
unread,
|
||||||
contextualChannel: cxid,
|
contextualChannel: cxid,
|
||||||
}: ContextMenuData) => {
|
}: ContextMenuData) => {
|
||||||
const store = useData();
|
|
||||||
|
|
||||||
const forceUpdate = useForceUpdate();
|
|
||||||
const elements: Children[] = [];
|
const elements: Children[] = [];
|
||||||
let lastDivider = false;
|
let lastDivider = false;
|
||||||
|
|
||||||
|
@ -495,11 +479,8 @@ function ContextMenus(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server_list) {
|
if (server_list) {
|
||||||
const server = store.servers.get(server_list);
|
const server = client.servers.get(server_list)!;
|
||||||
const permissions = useServerPermission(
|
const permissions = server.permission;
|
||||||
server_list,
|
|
||||||
forceUpdate,
|
|
||||||
);
|
|
||||||
if (server) {
|
if (server) {
|
||||||
if (permissions & ServerPermission.ManageChannels)
|
if (permissions & ServerPermission.ManageChannels)
|
||||||
generateAction({
|
generateAction({
|
||||||
|
@ -526,13 +507,13 @@ function ContextMenus(props: Props) {
|
||||||
pushDivider();
|
pushDivider();
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel = cid ? store.channels.get(cid) : undefined;
|
const channel = cid ? client.channels.get(cid) : undefined;
|
||||||
const contextualChannel = cxid
|
const contextualChannel = cxid
|
||||||
? store.channels.get(cxid)
|
? client.channels.get(cxid)
|
||||||
: undefined;
|
: undefined;
|
||||||
const targetChannel = channel ?? contextualChannel;
|
const targetChannel = channel ?? contextualChannel;
|
||||||
|
|
||||||
const user = uid ? store.users.get(uid) : undefined;
|
const user = uid ? client.users.get(uid) : undefined;
|
||||||
const serverChannel =
|
const serverChannel =
|
||||||
targetChannel &&
|
targetChannel &&
|
||||||
(targetChannel.channel_type === "TextChannel" ||
|
(targetChannel.channel_type === "TextChannel" ||
|
||||||
|
@ -540,23 +521,17 @@ function ContextMenus(props: Props) {
|
||||||
? targetChannel
|
? targetChannel
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const s = serverChannel ? serverChannel.server! : sid;
|
const s = serverChannel ? serverChannel.server_id! : sid;
|
||||||
const server = s ? store.servers.get(s) : undefined;
|
const server = s ? client.servers.get(s) : undefined;
|
||||||
|
|
||||||
const channelPermissions = targetChannel
|
const channelPermissions = targetChannel?.permission || 0;
|
||||||
? useChannelPermission(targetChannel._id, forceUpdate)
|
const serverPermissions =
|
||||||
: 0;
|
(server
|
||||||
const serverPermissions = server
|
? server.permission
|
||||||
? useServerPermission(server._id, forceUpdate)
|
: serverChannel
|
||||||
: serverChannel
|
? serverChannel.server?.permission
|
||||||
? useServerPermission(
|
: 0) || 0;
|
||||||
serverChannel.server!,
|
const userPermissions = (user ? user.permission : 0) || 0;
|
||||||
forceUpdate,
|
|
||||||
)
|
|
||||||
: 0;
|
|
||||||
const userPermissions = user
|
|
||||||
? useUserPermission(user._id, forceUpdate)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
if (channel && unread) {
|
if (channel && unread) {
|
||||||
generateAction({ action: "mark_as_read", channel });
|
generateAction({ action: "mark_as_read", channel });
|
||||||
|
@ -576,29 +551,29 @@ function ContextMenus(props: Props) {
|
||||||
if (user) {
|
if (user) {
|
||||||
let actions: Action["action"][];
|
let actions: Action["action"][];
|
||||||
switch (user.relationship) {
|
switch (user.relationship) {
|
||||||
case Users.Relationship.User:
|
case RelationshipStatus.User:
|
||||||
actions = [];
|
actions = [];
|
||||||
break;
|
break;
|
||||||
case Users.Relationship.Friend:
|
case RelationshipStatus.Friend:
|
||||||
actions = ["remove_friend", "block_user"];
|
actions = ["remove_friend", "block_user"];
|
||||||
break;
|
break;
|
||||||
case Users.Relationship.Incoming:
|
case RelationshipStatus.Incoming:
|
||||||
actions = [
|
actions = [
|
||||||
"add_friend",
|
"add_friend",
|
||||||
"cancel_friend",
|
"cancel_friend",
|
||||||
"block_user",
|
"block_user",
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Users.Relationship.Outgoing:
|
case RelationshipStatus.Outgoing:
|
||||||
actions = ["cancel_friend", "block_user"];
|
actions = ["cancel_friend", "block_user"];
|
||||||
break;
|
break;
|
||||||
case Users.Relationship.Blocked:
|
case RelationshipStatus.Blocked:
|
||||||
actions = ["unblock_user"];
|
actions = ["unblock_user"];
|
||||||
break;
|
break;
|
||||||
case Users.Relationship.BlockedOther:
|
case RelationshipStatus.BlockedOther:
|
||||||
actions = ["block_user"];
|
actions = ["block_user"];
|
||||||
break;
|
break;
|
||||||
case Users.Relationship.None:
|
case RelationshipStatus.None:
|
||||||
default:
|
default:
|
||||||
actions = ["add_friend", "block_user"];
|
actions = ["add_friend", "block_user"];
|
||||||
}
|
}
|
||||||
|
@ -629,12 +604,12 @@ function ContextMenus(props: Props) {
|
||||||
if (contextualChannel) {
|
if (contextualChannel) {
|
||||||
if (contextualChannel.channel_type === "Group" && uid) {
|
if (contextualChannel.channel_type === "Group" && uid) {
|
||||||
if (
|
if (
|
||||||
contextualChannel.owner === userId &&
|
contextualChannel.owner_id === userId &&
|
||||||
userId !== uid
|
userId !== uid
|
||||||
) {
|
) {
|
||||||
generateAction({
|
generateAction({
|
||||||
action: "remove_member",
|
action: "remove_member",
|
||||||
channel: contextualChannel._id,
|
channel: contextualChannel,
|
||||||
user: user!,
|
user: user!,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -697,7 +672,7 @@ function ContextMenus(props: Props) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.author === userId) {
|
if (message.author_id === userId) {
|
||||||
generateAction({
|
generateAction({
|
||||||
action: "edit_message",
|
action: "edit_message",
|
||||||
id: message._id,
|
id: message._id,
|
||||||
|
@ -705,7 +680,7 @@ function ContextMenus(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
message.author === userId ||
|
message.author_id === userId ||
|
||||||
channelPermissions &
|
channelPermissions &
|
||||||
ChannelPermission.ManageMessages
|
ChannelPermission.ManageMessages
|
||||||
) {
|
) {
|
||||||
|
@ -820,7 +795,7 @@ function ContextMenus(props: Props) {
|
||||||
generateAction(
|
generateAction(
|
||||||
{
|
{
|
||||||
action: "open_server_channel_settings",
|
action: "open_server_channel_settings",
|
||||||
server: channel.server!,
|
server: channel.server_id!,
|
||||||
id: channel._id,
|
id: channel._id,
|
||||||
},
|
},
|
||||||
"open_channel_settings",
|
"open_channel_settings",
|
||||||
|
@ -885,9 +860,7 @@ function ContextMenus(props: Props) {
|
||||||
onClose={contextClick}
|
onClose={contextClick}
|
||||||
className="Status">
|
className="Status">
|
||||||
{() => {
|
{() => {
|
||||||
const store = useData();
|
const user = client.user!;
|
||||||
const user = store.users.get(client.user!._id)!;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="header">
|
<div className="header">
|
||||||
|
@ -927,7 +900,7 @@ function ContextMenus(props: Props) {
|
||||||
<MenuItem
|
<MenuItem
|
||||||
data={{
|
data={{
|
||||||
action: "set_presence",
|
action: "set_presence",
|
||||||
presence: Users.Presence.Online,
|
presence: Presence.Online,
|
||||||
}}
|
}}
|
||||||
disabled={!isOnline}>
|
disabled={!isOnline}>
|
||||||
<div className="indicator online" />
|
<div className="indicator online" />
|
||||||
|
@ -936,7 +909,7 @@ function ContextMenus(props: Props) {
|
||||||
<MenuItem
|
<MenuItem
|
||||||
data={{
|
data={{
|
||||||
action: "set_presence",
|
action: "set_presence",
|
||||||
presence: Users.Presence.Idle,
|
presence: Presence.Idle,
|
||||||
}}
|
}}
|
||||||
disabled={!isOnline}>
|
disabled={!isOnline}>
|
||||||
<div className="indicator idle" />
|
<div className="indicator idle" />
|
||||||
|
@ -945,7 +918,7 @@ function ContextMenus(props: Props) {
|
||||||
<MenuItem
|
<MenuItem
|
||||||
data={{
|
data={{
|
||||||
action: "set_presence",
|
action: "set_presence",
|
||||||
presence: Users.Presence.Busy,
|
presence: Presence.Busy,
|
||||||
}}
|
}}
|
||||||
disabled={!isOnline}>
|
disabled={!isOnline}>
|
||||||
<div className="indicator busy" />
|
<div className="indicator busy" />
|
||||||
|
@ -954,7 +927,7 @@ function ContextMenus(props: Props) {
|
||||||
<MenuItem
|
<MenuItem
|
||||||
data={{
|
data={{
|
||||||
action: "set_presence",
|
action: "set_presence",
|
||||||
presence: Users.Presence.Invisible,
|
presence: Presence.Invisible,
|
||||||
}}
|
}}
|
||||||
disabled={!isOnline}>
|
disabled={!isOnline}>
|
||||||
<div className="indicator invisible" />
|
<div className="indicator invisible" />
|
||||||
|
@ -982,7 +955,7 @@ function ContextMenus(props: Props) {
|
||||||
<ContextMenuWithData
|
<ContextMenuWithData
|
||||||
id="NotificationOptions"
|
id="NotificationOptions"
|
||||||
onClose={contextClick}>
|
onClose={contextClick}>
|
||||||
{({ channel }: { channel: Channels.Channel }) => {
|
{({ channel }: { channel: Channel }) => {
|
||||||
const state = props.notifications[channel._id];
|
const state = props.notifications[channel._id];
|
||||||
const actual = getNotificationState(
|
const actual = getNotificationState(
|
||||||
props.notifications,
|
props.notifications,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import EventEmitter3 from "eventemitter3";
|
import EventEmitter3 from "eventemitter3";
|
||||||
import { Client, Message } from "revolt.js";
|
import { Client } from "revolt.js";
|
||||||
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
|
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { mapMessage } from "../../../context/revoltjs/util";
|
|
||||||
|
|
||||||
import { SMOOTH_SCROLL_ON_RECEIVE } from "../Singleton";
|
import { SMOOTH_SCROLL_ON_RECEIVE } from "../Singleton";
|
||||||
import { RendererRoutines } from "../types";
|
import { RendererRoutines } from "../types";
|
||||||
|
|
||||||
|
@ -8,14 +6,10 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
if (renderer.client!.websocket.connected) {
|
if (renderer.client!.websocket.connected) {
|
||||||
if (nearby)
|
if (nearby)
|
||||||
renderer
|
renderer
|
||||||
.client!.channels.fetchMessagesWithUsers(
|
.client!.channels.get(id)!
|
||||||
id,
|
.fetchMessagesWithUsers({ nearby, limit: 100 })
|
||||||
{ nearby, limit: 100 },
|
.then(({ messages }) => {
|
||||||
true,
|
messages.sort((a, b) => a._id.localeCompare(b._id));
|
||||||
)
|
|
||||||
.then(({ messages: data }) => {
|
|
||||||
data.sort((a, b) => a._id.localeCompare(b._id));
|
|
||||||
const messages = data.map((x) => mapMessage(x));
|
|
||||||
renderer.setState(
|
renderer.setState(
|
||||||
id,
|
id,
|
||||||
{
|
{
|
||||||
|
@ -29,16 +23,16 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
});
|
});
|
||||||
else
|
else
|
||||||
renderer
|
renderer
|
||||||
.client!.channels.fetchMessagesWithUsers(id, {}, true)
|
.client!.channels.get(id)!
|
||||||
.then(({ messages: data }) => {
|
.fetchMessagesWithUsers({})
|
||||||
data.reverse();
|
.then(({ messages }) => {
|
||||||
const messages = data.map((x) => mapMessage(x));
|
messages.reverse();
|
||||||
renderer.setState(
|
renderer.setState(
|
||||||
id,
|
id,
|
||||||
{
|
{
|
||||||
type: "RENDER",
|
type: "RENDER",
|
||||||
messages,
|
messages,
|
||||||
atTop: data.length < 50,
|
atTop: messages.length < 50,
|
||||||
atBottom: true,
|
atBottom: true,
|
||||||
},
|
},
|
||||||
{ type: "ScrollToBottom", smooth },
|
{ type: "ScrollToBottom", smooth },
|
||||||
|
@ -54,7 +48,7 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
if (renderer.state.messages.find((x) => x._id === message._id)) return;
|
if (renderer.state.messages.find((x) => x._id === message._id)) return;
|
||||||
if (!renderer.state.atBottom) return;
|
if (!renderer.state.atBottom) return;
|
||||||
|
|
||||||
let messages = [...renderer.state.messages, mapMessage(message)];
|
let messages = [...renderer.state.messages, message];
|
||||||
let atTop = renderer.state.atTop;
|
let atTop = renderer.state.atTop;
|
||||||
if (messages.length > 150) {
|
if (messages.length > 150) {
|
||||||
messages = messages.slice(messages.length - 150);
|
messages = messages.slice(messages.length - 150);
|
||||||
|
@ -62,7 +56,7 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.setState(
|
renderer.setState(
|
||||||
message.channel,
|
message.channel_id,
|
||||||
{
|
{
|
||||||
...renderer.state,
|
...renderer.state,
|
||||||
messages,
|
messages,
|
||||||
|
@ -72,7 +66,8 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
edit: async (renderer, id, patch) => {
|
edit: async (renderer, id, patch) => {
|
||||||
const channel = renderer.channel;
|
// ! FIXME: verify if this is needed anymore
|
||||||
|
/*const channel = renderer.channel;
|
||||||
if (!channel) return;
|
if (!channel) return;
|
||||||
if (renderer.state.type !== "RENDER") return;
|
if (renderer.state.type !== "RENDER") return;
|
||||||
|
|
||||||
|
@ -91,7 +86,7 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
},
|
},
|
||||||
{ type: "StayAtBottom" },
|
{ type: "StayAtBottom" },
|
||||||
);
|
);
|
||||||
}
|
}*/
|
||||||
},
|
},
|
||||||
delete: async (renderer, id) => {
|
delete: async (renderer, id) => {
|
||||||
const channel = renderer.channel;
|
const channel = renderer.channel;
|
||||||
|
@ -122,14 +117,11 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
if (state.type !== "RENDER") return;
|
if (state.type !== "RENDER") return;
|
||||||
if (state.atTop) return;
|
if (state.atTop) return;
|
||||||
|
|
||||||
const { messages: data } =
|
const { messages: data } = await renderer
|
||||||
await renderer.client!.channels.fetchMessagesWithUsers(
|
.client!.channels.get(channel)!
|
||||||
channel,
|
.fetchMessagesWithUsers({
|
||||||
{
|
before: state.messages[0]._id,
|
||||||
before: state.messages[0]._id,
|
});
|
||||||
},
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
return renderer.setState(channel, {
|
return renderer.setState(channel, {
|
||||||
|
@ -139,7 +131,7 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
}
|
}
|
||||||
|
|
||||||
data.reverse();
|
data.reverse();
|
||||||
let messages = [...data.map((x) => mapMessage(x)), ...state.messages];
|
let messages = [...data, ...state.messages];
|
||||||
|
|
||||||
let atTop = false;
|
let atTop = false;
|
||||||
if (data.length < 50) {
|
if (data.length < 50) {
|
||||||
|
@ -166,15 +158,12 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
if (state.type !== "RENDER") return;
|
if (state.type !== "RENDER") return;
|
||||||
if (state.atBottom) return;
|
if (state.atBottom) return;
|
||||||
|
|
||||||
const { messages: data } =
|
const { messages: data } = await renderer
|
||||||
await renderer.client!.channels.fetchMessagesWithUsers(
|
.client!.channels.get(channel)!
|
||||||
channel,
|
.fetchMessagesWithUsers({
|
||||||
{
|
after: state.messages[state.messages.length - 1]._id,
|
||||||
after: state.messages[state.messages.length - 1]._id,
|
sort: "Oldest",
|
||||||
sort: "Oldest",
|
});
|
||||||
},
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
return renderer.setState(channel, {
|
return renderer.setState(channel, {
|
||||||
|
@ -183,7 +172,7 @@ export const SimpleRenderer: RendererRoutines = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let messages = [...state.messages, ...data.map((x) => mapMessage(x))];
|
let messages = [...state.messages, ...data];
|
||||||
|
|
||||||
let atBottom = false;
|
let atBottom = false;
|
||||||
if (data.length < 50) {
|
if (data.length < 50) {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import { Message } from "revolt.js";
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
|
|
||||||
import { MessageObject } from "../../context/revoltjs/util";
|
|
||||||
|
|
||||||
import { SingletonRenderer } from "./Singleton";
|
import { SingletonRenderer } from "./Singleton";
|
||||||
|
|
||||||
|
@ -20,7 +18,7 @@ export type RenderState =
|
||||||
type: "RENDER";
|
type: "RENDER";
|
||||||
atTop: boolean;
|
atTop: boolean;
|
||||||
atBottom: boolean;
|
atBottom: boolean;
|
||||||
messages: MessageObject[];
|
messages: Message[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface RendererRoutines {
|
export interface RendererRoutines {
|
||||||
|
|
|
@ -29,15 +29,15 @@ export default function Open() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (id === "saved") {
|
if (id === "saved") {
|
||||||
for (const channel of client.channels.toArray()) {
|
for (const channel of [...client.channels.values()]) {
|
||||||
if (channel?.channel_type === "SavedMessages") {
|
if (channel?.channel_type === "SavedMessages") {
|
||||||
history.push(`/channel/${channel._id}`);
|
history.push(`/channel/${channel._id}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.users
|
client
|
||||||
.openDM(client.user?._id as string)
|
.user!.openDM()
|
||||||
.then((channel) => history.push(`/channel/${channel?._id}`))
|
.then((channel) => history.push(`/channel/${channel?._id}`))
|
||||||
.catch((error) => openScreen({ id: "error", error }));
|
.catch((error) => openScreen({ id: "error", error }));
|
||||||
|
|
||||||
|
@ -46,19 +46,20 @@ export default function Open() {
|
||||||
|
|
||||||
let user = client.users.get(id);
|
let user = client.users.get(id);
|
||||||
if (user) {
|
if (user) {
|
||||||
const channel: string | undefined = client.channels
|
const channel: string | undefined = [
|
||||||
.toArray()
|
...client.channels.values(),
|
||||||
.find(
|
].find(
|
||||||
(channel) =>
|
(channel) =>
|
||||||
channel?.channel_type === "DirectMessage" &&
|
channel?.channel_type === "DirectMessage" &&
|
||||||
channel.recipients.includes(id),
|
channel.recipient_ids!.includes(id),
|
||||||
)?._id;
|
)?._id;
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
history.push(`/channel/${channel}`);
|
history.push(`/channel/${channel}`);
|
||||||
} else {
|
} else {
|
||||||
client.users
|
client.users
|
||||||
.openDM(id)
|
.get(id)
|
||||||
|
?.openDM()
|
||||||
.then((channel) => history.push(`/channel/${channel?._id}`))
|
.then((channel) => history.push(`/channel/${channel?._id}`))
|
||||||
.catch((error) => openScreen({ id: "error", error }));
|
.catch((error) => openScreen({ id: "error", error }));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useParams, useHistory } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { Channels } from "revolt.js/dist/api/objects";
|
import { Channel as ChannelI } from "revolt.js/dist/maps/Channels";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
|
|
||||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import { Channel as MobXChannel } from "../../mobx";
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
import { dispatch, getState } from "../../redux";
|
import { dispatch, getState } from "../../redux";
|
||||||
|
|
||||||
|
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
import AgeGate from "../../components/common/AgeGate";
|
import AgeGate from "../../components/common/AgeGate";
|
||||||
import MessageBox from "../../components/common/messaging/MessageBox";
|
import MessageBox from "../../components/common/messaging/MessageBox";
|
||||||
import JumpToBottom from "../../components/common/messaging/bars/JumpToBottom";
|
import JumpToBottom from "../../components/common/messaging/bars/JumpToBottom";
|
||||||
|
@ -37,8 +37,8 @@ const ChannelContent = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export function Channel({ id }: { id: string }) {
|
export function Channel({ id }: { id: string }) {
|
||||||
const store = useData();
|
const client = useClient();
|
||||||
const channel = store.channels.get(id);
|
const channel = client.channels.get(id);
|
||||||
if (!channel) return null;
|
if (!channel) return null;
|
||||||
|
|
||||||
if (channel.channel_type === "VoiceChannel") {
|
if (channel.channel_type === "VoiceChannel") {
|
||||||
|
@ -49,7 +49,7 @@ export function Channel({ id }: { id: string }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const MEMBERS_SIDEBAR_KEY = "sidebar_members";
|
const MEMBERS_SIDEBAR_KEY = "sidebar_members";
|
||||||
const TextChannel = observer(({ channel }: { channel: MobXChannel }) => {
|
const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
|
||||||
const [showMembers, setMembers] = useState(
|
const [showMembers, setMembers] = useState(
|
||||||
getState().sectionToggle[MEMBERS_SIDEBAR_KEY] ?? true,
|
getState().sectionToggle[MEMBERS_SIDEBAR_KEY] ?? true,
|
||||||
);
|
);
|
||||||
|
@ -101,7 +101,7 @@ const TextChannel = observer(({ channel }: { channel: MobXChannel }) => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function VoiceChannel({ channel }: { channel: MobXChannel }) {
|
function VoiceChannel({ channel }: { channel: ChannelI }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ChannelHeader channel={channel} />
|
<ChannelHeader channel={channel} />
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
import { At, Hash, Menu } from "@styled-icons/boxicons-regular";
|
import { At, Hash, Menu } from "@styled-icons/boxicons-regular";
|
||||||
import { Notepad, Group } from "@styled-icons/boxicons-solid";
|
import { Notepad, Group } from "@styled-icons/boxicons-solid";
|
||||||
import { observable } from "mobx";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
import { User } from "revolt.js/dist/maps/Users";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { useContext } from "preact/hooks";
|
|
||||||
|
|
||||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import { Channel, User } from "../../mobx";
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
|
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||||
import { AppContext, useClient } from "../../context/revoltjs/RevoltClient";
|
|
||||||
import { getChannelName } from "../../context/revoltjs/util";
|
import { getChannelName } from "../../context/revoltjs/util";
|
||||||
|
|
||||||
import { useStatusColour } from "../../components/common/user/UserIcon";
|
import { useStatusColour } from "../../components/common/user/UserIcon";
|
||||||
|
@ -71,10 +66,8 @@ const Info = styled.div`
|
||||||
|
|
||||||
export default observer(({ channel, toggleSidebar }: ChannelHeaderProps) => {
|
export default observer(({ channel, toggleSidebar }: ChannelHeaderProps) => {
|
||||||
const { openScreen } = useIntermediate();
|
const { openScreen } = useIntermediate();
|
||||||
const client = useClient();
|
|
||||||
const state = useData();
|
|
||||||
|
|
||||||
const name = getChannelName(client, channel);
|
const name = getChannelName(channel);
|
||||||
let icon, recipient: User | undefined;
|
let icon, recipient: User | undefined;
|
||||||
switch (channel.channel_type) {
|
switch (channel.channel_type) {
|
||||||
case "SavedMessages":
|
case "SavedMessages":
|
||||||
|
@ -82,8 +75,7 @@ export default observer(({ channel, toggleSidebar }: ChannelHeaderProps) => {
|
||||||
break;
|
break;
|
||||||
case "DirectMessage":
|
case "DirectMessage":
|
||||||
icon = <At size={24} />;
|
icon = <At size={24} />;
|
||||||
const uid = client.channels.getRecipient(channel._id);
|
recipient = channel.recipient;
|
||||||
recipient = state.users.get(uid);
|
|
||||||
break;
|
break;
|
||||||
case "Group":
|
case "Group":
|
||||||
icon = <Group size={24} />;
|
icon = <Group size={24} />;
|
||||||
|
|
|
@ -29,7 +29,6 @@ export default function HeaderActions({
|
||||||
toggleSidebar,
|
toggleSidebar,
|
||||||
}: ChannelHeaderProps) {
|
}: ChannelHeaderProps) {
|
||||||
const { openScreen } = useIntermediate();
|
const { openScreen } = useIntermediate();
|
||||||
const client = useContext(AppContext);
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -41,13 +40,10 @@ export default function HeaderActions({
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
openScreen({
|
openScreen({
|
||||||
id: "user_picker",
|
id: "user_picker",
|
||||||
omit: channel.recipients!,
|
omit: channel.recipient_ids!,
|
||||||
callback: async (users) => {
|
callback: async (users) => {
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
await client.channels.addMember(
|
await channel.addMember(user);
|
||||||
channel._id,
|
|
||||||
user,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,8 +3,6 @@ import styled from "styled-components";
|
||||||
|
|
||||||
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";
|
||||||
|
|
||||||
|
@ -28,14 +26,13 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default observer(({ id }: Props) => {
|
export default observer(({ id }: Props) => {
|
||||||
const store = useData();
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const channel = store.channels.get(id);
|
const channel = client.channels.get(id);
|
||||||
if (!channel) return null;
|
if (!channel) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StartBase>
|
<StartBase>
|
||||||
<h1>{getChannelName(client, channel, true)}</h1>
|
<h1>{getChannelName(channel, true)}</h1>
|
||||||
<h4>
|
<h4>
|
||||||
<Text id="app.main.channel.start.group" />
|
<Text id="app.main.channel.start.group" />
|
||||||
</h4>
|
</h4>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { useContext, useEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
@ -10,7 +11,6 @@ import {
|
||||||
useIntermediate,
|
useIntermediate,
|
||||||
} from "../../../context/intermediate/Intermediate";
|
} from "../../../context/intermediate/Intermediate";
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||||
import { MessageObject } from "../../../context/revoltjs/util";
|
|
||||||
|
|
||||||
import AutoComplete, {
|
import AutoComplete, {
|
||||||
useAutoComplete,
|
useAutoComplete,
|
||||||
|
@ -44,7 +44,7 @@ const EditorBase = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
message: MessageObject;
|
message: Message;
|
||||||
finish: () => void;
|
finish: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ export default function MessageEditor({ message, finish }: Props) {
|
||||||
const [content, setContent] = useState((message.content as string) ?? "");
|
const [content, setContent] = useState((message.content as string) ?? "");
|
||||||
const { focusTaken } = useContext(IntermediateContext);
|
const { focusTaken } = useContext(IntermediateContext);
|
||||||
const { openScreen } = useIntermediate();
|
const { openScreen } = useIntermediate();
|
||||||
const client = useContext(AppContext);
|
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
finish();
|
finish();
|
||||||
|
@ -60,13 +59,11 @@ export default function MessageEditor({ message, finish }: Props) {
|
||||||
if (content.length === 0) {
|
if (content.length === 0) {
|
||||||
openScreen({
|
openScreen({
|
||||||
id: "special_prompt",
|
id: "special_prompt",
|
||||||
// @ts-expect-error
|
|
||||||
type: "delete_message",
|
type: "delete_message",
|
||||||
// @ts-expect-error
|
|
||||||
target: message,
|
target: message,
|
||||||
});
|
});
|
||||||
} else if (content !== message.content) {
|
} else if (content !== message.content) {
|
||||||
await client.channels.editMessage(message.channel, message._id, {
|
await message.editMessage({
|
||||||
content,
|
content,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { X } from "@styled-icons/boxicons-regular";
|
import { X } from "@styled-icons/boxicons-regular";
|
||||||
import { Users } from "revolt.js/dist/api/objects";
|
import { RelationshipStatus } from "revolt-api/types/Users";
|
||||||
|
import { SYSTEM_USER_ID } from "revolt.js";
|
||||||
|
import { Message as MessageObject } from "revolt.js/dist/maps/Messages";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { decodeTime } from "ulid";
|
import { decodeTime } from "ulid";
|
||||||
|
|
||||||
|
@ -15,7 +17,6 @@ import { QueuedMessage } from "../../../redux/reducers/queue";
|
||||||
|
|
||||||
import RequiresOnline from "../../../context/revoltjs/RequiresOnline";
|
import RequiresOnline from "../../../context/revoltjs/RequiresOnline";
|
||||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||||
import { MessageObject } from "../../../context/revoltjs/util";
|
|
||||||
|
|
||||||
import Message from "../../../components/common/messaging/Message";
|
import Message from "../../../components/common/messaging/Message";
|
||||||
import { SystemMessage } from "../../../components/common/messaging/SystemMessage";
|
import { SystemMessage } from "../../../components/common/messaging/SystemMessage";
|
||||||
|
@ -60,7 +61,7 @@ function MessageRenderer({ id, state, queue, highlight }: Props) {
|
||||||
function editLast() {
|
function editLast() {
|
||||||
if (state.type !== "RENDER") return;
|
if (state.type !== "RENDER") return;
|
||||||
for (let i = state.messages.length - 1; i >= 0; i--) {
|
for (let i = state.messages.length - 1; i >= 0; i--) {
|
||||||
if (state.messages[i].author === userId) {
|
if (state.messages[i].author_id === userId) {
|
||||||
setEditing(state.messages[i]._id);
|
setEditing(state.messages[i]._id);
|
||||||
internalEmit("MessageArea", "jump_to_bottom");
|
internalEmit("MessageArea", "jump_to_bottom");
|
||||||
return;
|
return;
|
||||||
|
@ -129,10 +130,15 @@ function MessageRenderer({ id, state, queue, highlight }: Props) {
|
||||||
|
|
||||||
for (const message of state.messages) {
|
for (const message of state.messages) {
|
||||||
if (previous) {
|
if (previous) {
|
||||||
compare(message._id, message.author, previous._id, previous.author);
|
compare(
|
||||||
|
message._id,
|
||||||
|
message.author_id,
|
||||||
|
previous._id,
|
||||||
|
previous.author_id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.author === "00000000000000000000000000") {
|
if (message.author_id === SYSTEM_USER_ID) {
|
||||||
render.push(
|
render.push(
|
||||||
<SystemMessage
|
<SystemMessage
|
||||||
key={message._id}
|
key={message._id}
|
||||||
|
@ -143,10 +149,7 @@ function MessageRenderer({ id, state, queue, highlight }: Props) {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// ! FIXME: temp solution
|
// ! FIXME: temp solution
|
||||||
if (
|
if (message.author?.relationship === RelationshipStatus.Blocked) {
|
||||||
client.users.get(message.author)?.relationship ===
|
|
||||||
Users.Relationship.Blocked
|
|
||||||
) {
|
|
||||||
blocked++;
|
blocked++;
|
||||||
} else {
|
} else {
|
||||||
if (blocked > 0) pushBlocked();
|
if (blocked > 0) pushBlocked();
|
||||||
|
@ -183,7 +186,7 @@ function MessageRenderer({ id, state, queue, highlight }: Props) {
|
||||||
if (nonces.includes(msg.id)) continue;
|
if (nonces.includes(msg.id)) continue;
|
||||||
|
|
||||||
if (previous) {
|
if (previous) {
|
||||||
compare(msg.id, userId!, previous._id, previous.author);
|
compare(msg.id, userId!, previous._id, previous.author_id);
|
||||||
|
|
||||||
previous = {
|
previous = {
|
||||||
_id: msg.id,
|
_id: msg.id,
|
||||||
|
@ -191,7 +194,8 @@ function MessageRenderer({ id, state, queue, highlight }: Props) {
|
||||||
} as any;
|
} as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
render.push(
|
// ! FIXME: add queued messages back
|
||||||
|
/* render.push(
|
||||||
<Message
|
<Message
|
||||||
message={{
|
message={{
|
||||||
...msg.data,
|
...msg.data,
|
||||||
|
@ -202,7 +206,7 @@ function MessageRenderer({ id, state, queue, highlight }: Props) {
|
||||||
head={head}
|
head={head}
|
||||||
attachContext
|
attachContext
|
||||||
/>,
|
/>,
|
||||||
);
|
); */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
render.push(
|
render.push(
|
||||||
|
|
|
@ -6,8 +6,6 @@ import styled from "styled-components";
|
||||||
import { Text } from "preact-i18n";
|
import { Text } from "preact-i18n";
|
||||||
import { useContext } from "preact/hooks";
|
import { useContext } from "preact/hooks";
|
||||||
|
|
||||||
import { useData } from "../../../mobx/State";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
VoiceContext,
|
VoiceContext,
|
||||||
VoiceOperationsContext,
|
VoiceOperationsContext,
|
||||||
|
@ -77,14 +75,13 @@ export default observer(({ id }: Props) => {
|
||||||
const { isProducing, startProducing, stopProducing, disconnect } =
|
const { isProducing, startProducing, stopProducing, disconnect } =
|
||||||
useContext(VoiceOperationsContext);
|
useContext(VoiceOperationsContext);
|
||||||
|
|
||||||
const store = useData();
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const self = store.users.get(client.user!._id);
|
const self = client.users.get(client.user!._id);
|
||||||
|
|
||||||
//const ctx = useForceUpdate();
|
//const ctx = useForceUpdate();
|
||||||
//const self = useSelf(ctx);
|
//const self = useSelf(ctx);
|
||||||
const keys = participants ? Array.from(participants.keys()) : undefined;
|
const keys = participants ? Array.from(participants.keys()) : undefined;
|
||||||
const users = keys?.map((key) => store.users.get(key));
|
const users = keys?.map((key) => client.users.get(key));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VoiceBase>
|
<VoiceBase>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { Wrench } from "@styled-icons/boxicons-solid";
|
import { Wrench } from "@styled-icons/boxicons-solid";
|
||||||
import { isObservable, isObservableProp } from "mobx";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Channels } from "revolt.js/dist/api/objects";
|
|
||||||
|
|
||||||
import { useContext } from "preact/hooks";
|
import { useContext } from "preact/hooks";
|
||||||
|
|
||||||
|
@ -9,17 +7,13 @@ import PaintCounter from "../../lib/PaintCounter";
|
||||||
import { TextReact } from "../../lib/i18n";
|
import { TextReact } from "../../lib/i18n";
|
||||||
|
|
||||||
import { AppContext } from "../../context/revoltjs/RevoltClient";
|
import { AppContext } from "../../context/revoltjs/RevoltClient";
|
||||||
import { useUserPermission } from "../../context/revoltjs/hooks";
|
|
||||||
|
|
||||||
import UserIcon from "../../components/common/user/UserIcon";
|
|
||||||
import Header from "../../components/ui/Header";
|
import Header from "../../components/ui/Header";
|
||||||
|
|
||||||
import { useData } from "../../mobx/State";
|
|
||||||
|
|
||||||
export default function Developer() {
|
export default function Developer() {
|
||||||
// const voice = useContext(VoiceContext);
|
// const voice = useContext(VoiceContext);
|
||||||
const client = useContext(AppContext);
|
const client = useContext(AppContext);
|
||||||
const userPermission = useUserPermission(client.user!._id);
|
const userPermission = client.user!.permission;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -40,10 +34,6 @@ export default function Developer() {
|
||||||
fields={{ provider: <b>GAMING!</b> }}
|
fields={{ provider: <b>GAMING!</b> }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ObserverTest />
|
|
||||||
<ObserverTest2 />
|
|
||||||
<ObserverTest3 />
|
|
||||||
<ObserverTest4 />
|
|
||||||
<div style={{ padding: "16px" }}>
|
<div style={{ padding: "16px" }}>
|
||||||
{/*<span>
|
{/*<span>
|
||||||
<b>Voice Status:</b> {VoiceStatus[voice.status]}
|
<b>Voice Status:</b> {VoiceStatus[voice.status]}
|
||||||
|
@ -62,67 +52,3 @@ export default function Developer() {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ObserverTest = observer(() => {
|
|
||||||
const client = useContext(AppContext);
|
|
||||||
const store = useData();
|
|
||||||
return (
|
|
||||||
<div style={{ padding: "16px" }}>
|
|
||||||
<p>
|
|
||||||
username:{" "}
|
|
||||||
{store.users.get(client.user!._id)?.username ?? "no user!"}
|
|
||||||
<PaintCounter small />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const ObserverTest2 = observer(() => {
|
|
||||||
const client = useContext(AppContext);
|
|
||||||
const store = useData();
|
|
||||||
return (
|
|
||||||
<div style={{ padding: "16px" }}>
|
|
||||||
<p>
|
|
||||||
status:{" "}
|
|
||||||
{JSON.stringify(store.users.get(client.user!._id)?.status) ??
|
|
||||||
"none"}
|
|
||||||
<PaintCounter small />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const ObserverTest3 = observer(() => {
|
|
||||||
const client = useContext(AppContext);
|
|
||||||
const store = useData();
|
|
||||||
return (
|
|
||||||
<div style={{ padding: "16px" }}>
|
|
||||||
<p>
|
|
||||||
avatar{" "}
|
|
||||||
<UserIcon
|
|
||||||
size={64}
|
|
||||||
attachment={
|
|
||||||
store.users.get(client.user!._id)?.avatar ?? undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<PaintCounter small />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const ObserverTest4 = observer(() => {
|
|
||||||
const client = useContext(AppContext);
|
|
||||||
const store = useData();
|
|
||||||
return (
|
|
||||||
<div style={{ padding: "16px" }}>
|
|
||||||
<p>
|
|
||||||
status text:{" "}
|
|
||||||
{JSON.stringify(
|
|
||||||
store.users.get(client.user!._id)?.status?.text,
|
|
||||||
) ?? "none"}
|
|
||||||
<PaintCounter small />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
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 { useHistory } from "react-router-dom";
|
||||||
import { RelationshipStatus } from "revolt-api/types/Users";
|
import { RelationshipStatus } from "revolt-api/types/Users";
|
||||||
import { User } from "revolt.js/dist/maps/Users";
|
import { User } from "revolt.js/dist/maps/Users";
|
||||||
|
|
||||||
|
@ -30,9 +31,8 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Friend = observer(({ user }: Props) => {
|
export const Friend = observer(({ user }: Props) => {
|
||||||
const client = useContext(AppContext);
|
const history = useHistory();
|
||||||
const { openScreen } = useIntermediate();
|
const { openScreen } = useIntermediate();
|
||||||
const { openDM } = useContext(OperationsContext);
|
|
||||||
const { connect } = useContext(VoiceOperationsContext);
|
const { connect } = useContext(VoiceOperationsContext);
|
||||||
|
|
||||||
const actions: Children[] = [];
|
const actions: Children[] = [];
|
||||||
|
@ -46,14 +46,29 @@ export const Friend = observer(({ user }: Props) => {
|
||||||
type="circle"
|
type="circle"
|
||||||
className={classNames(styles.button, styles.success)}
|
className={classNames(styles.button, styles.success)}
|
||||||
onClick={(ev) =>
|
onClick={(ev) =>
|
||||||
stopPropagation(ev, openDM(user._id).then(connect))
|
stopPropagation(
|
||||||
|
ev,
|
||||||
|
user.openDM().then((channel) => {
|
||||||
|
connect(channel._id);
|
||||||
|
history.push(`/channel/${channel._id}`);
|
||||||
|
}),
|
||||||
|
)
|
||||||
}>
|
}>
|
||||||
<PhoneCall size={20} />
|
<PhoneCall size={20} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
type="circle"
|
type="circle"
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
onClick={(ev) => stopPropagation(ev, openDM(user._id))}>
|
onClick={(ev) =>
|
||||||
|
stopPropagation(
|
||||||
|
ev,
|
||||||
|
user
|
||||||
|
.openDM()
|
||||||
|
.then((channel) =>
|
||||||
|
history.push(`/channel/${channel._id}`),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}>
|
||||||
<Envelope size={20} />
|
<Envelope size={20} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</>,
|
</>,
|
||||||
|
|
|
@ -14,7 +14,6 @@ import {
|
||||||
StatusContext,
|
StatusContext,
|
||||||
useClient,
|
useClient,
|
||||||
} from "../../../context/revoltjs/RevoltClient";
|
} from "../../../context/revoltjs/RevoltClient";
|
||||||
import { useForceUpdate } from "../../../context/revoltjs/hooks";
|
|
||||||
|
|
||||||
import Tooltip from "../../../components/common/Tooltip";
|
import Tooltip from "../../../components/common/Tooltip";
|
||||||
import UserIcon from "../../../components/common/user/UserIcon";
|
import UserIcon from "../../../components/common/user/UserIcon";
|
||||||
|
|
Loading…
Reference in a new issue