for-legacy-web/src/pages/invite/Invite.tsx

205 lines
8.2 KiB
TypeScript

import { ArrowBack } from "@styled-icons/boxicons-regular";
import { autorun } from "mobx";
import { Redirect, useHistory, useParams } from "react-router-dom";
import { RetrievedInvite } from "revolt-api/types/Invites";
import styles from "./Invite.module.scss";
import { Text } from "preact-i18n";
import { useContext, useEffect, useState } from "preact/hooks";
import { defer } from "../../lib/defer";
import { TextReact } from "../../lib/i18n";
import { dispatch } from "../../redux";
import RequiresOnline from "../../context/revoltjs/RequiresOnline";
import {
AppContext,
ClientStatus,
StatusContext,
} from "../../context/revoltjs/RevoltClient";
import { takeError } from "../../context/revoltjs/util";
import ServerIcon from "../../components/common/ServerIcon";
import UserIcon from "../../components/common/user/UserIcon";
import Button from "../../components/ui/Button";
import Overline from "../../components/ui/Overline";
import Preloader from "../../components/ui/Preloader";
export default function Invite() {
const history = useHistory();
const client = useContext(AppContext);
const status = useContext(StatusContext);
const { code } = useParams<{ code: string }>();
const [processing, setProcessing] = useState(false);
const [error, setError] = useState<string | undefined>(undefined);
const [invite, setInvite] = useState<RetrievedInvite | undefined>(
undefined,
);
useEffect(() => {
if (
typeof invite === "undefined" &&
(status === ClientStatus.ONLINE || status === ClientStatus.READY)
) {
client
.fetchInvite(code)
.then((data) => setInvite(data))
.catch((err) => setError(takeError(err)));
}
}, [client, code, invite, status]);
if (code === undefined) return <Redirect to="/" />;
if (typeof invite === "undefined") {
return (
<div className={styles.preloader}>
<RequiresOnline>
{error ? (
<div
className={styles.invite}
style={{
backgroundImage: `url('https://autumn.revolt.chat/banners/yMurJiXf45VJpbal0X2zQkm4vaXsXGaRtoPUIcvPcH')`,
width: "100%",
height: "100%",
}}>
<div className={styles.details}>
<h1>
<Text id="app.special.invite.invalid" />
</h1>
<h2>
<Text id="app.special.invite.invalid_desc" />
</h2>
<div style="cursor: pointer;">
<Button contrast>
<ArrowBack
size={32}
onClick={() => history.push("/")}
/>
</Button>
</div>
</div>
</div>
) : (
<Preloader type="spinner" />
)}
</RequiresOnline>
</div>
);
}
return (
<div
className={styles.invite}
style={{
backgroundImage: invite.server_banner
? `url('${client.generateFileURL(invite.server_banner)}')`
: undefined,
}}>
<div className={styles.leave}>
<ArrowBack size={32} onClick={() => history.push("/")} />
</div>
{!processing && (
<div className={styles.icon}>
<ServerIcon
attachment={invite.server_icon}
server_name={invite.server_name}
size={64}
/>
</div>
)}
<div className={styles.details}>
{processing ? (
<Preloader type="ring" />
) : (
<>
<h1>{invite.server_name}</h1>
<h2>
#{invite.channel_name} {" "}
<Text
id="app.special.invite.user_count"
fields={{
member_count: invite.member_count,
}}
/>
</h2>
<h3>
<TextReact
id="app.special.invite.invited_by"
fields={{
user: (
<>
<UserIcon
size={24}
attachment={invite.user_avatar}
/>{" "}
{invite.user_name}
</>
),
}}
/>
</h3>
<Overline type="error" error={error} />
<Button
contrast
onClick={async () => {
if (status === ClientStatus.READY) {
return history.push("/");
}
try {
setProcessing(true);
if (invite.type === "Server") {
if (
client.servers.get(invite.server_id)
) {
history.push(
`/server/${invite.server_id}/channel/${invite.channel_id}`,
);
}
const dispose = autorun(() => {
const server = client.servers.get(
invite.server_id,
);
defer(() => {
if (server) {
dispatch({
type: "UNREADS_MARK_MULTIPLE_READ",
channels:
server.channel_ids,
});
history.push(
`/server/${server._id}/channel/${invite.channel_id}`,
);
}
});
dispose();
});
}
await client.joinInvite(code);
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
}}>
{status === ClientStatus.READY ? (
<Text id="app.special.invite.login" />
) : (
<Text id="app.special.invite.accept" />
)}
</Button>
</>
)}
</div>
</div>
);
}