mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-10 01:03:36 -05:00
Merge pull request #169 from TaiAurori/master
This commit is contained in:
commit
571b30243c
2 changed files with 192 additions and 0 deletions
|
@ -24,6 +24,15 @@ import MessageBase, {
|
||||||
import Attachment from "./attachments/Attachment";
|
import Attachment from "./attachments/Attachment";
|
||||||
import { MessageReply } from "./attachments/MessageReply";
|
import { MessageReply } from "./attachments/MessageReply";
|
||||||
import Embed from "./embed/Embed";
|
import Embed from "./embed/Embed";
|
||||||
|
import EmbedInvite from "./embed/EmbedInvite";
|
||||||
|
|
||||||
|
const INVITE_PATHS = [
|
||||||
|
location.hostname + "/invite",
|
||||||
|
"app.revolt.chat/invite",
|
||||||
|
"nightly.revolt.chat/invite",
|
||||||
|
"local.revolt.chat/invite",
|
||||||
|
"rvlt.gg"
|
||||||
|
]
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
attachContext?: boolean;
|
attachContext?: boolean;
|
||||||
|
@ -142,6 +151,28 @@ const Message = observer(
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{replacement ?? <Markdown content={content} />}
|
{replacement ?? <Markdown content={content} />}
|
||||||
|
{(() => {
|
||||||
|
let isInvite = false;
|
||||||
|
INVITE_PATHS.forEach(path => {
|
||||||
|
if (content.includes(path)) {
|
||||||
|
isInvite = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (isInvite) {
|
||||||
|
const inviteRegex = new RegExp("(?:" + INVITE_PATHS.map((path, index) => path.split(".").join("\\.") + (index !== INVITE_PATHS.length - 1 ? "|" : "")).join("") + ")/([A-Za-z0-9]*)", "g");
|
||||||
|
if (inviteRegex.test(content)) {
|
||||||
|
let results: string[] = [];
|
||||||
|
let match: RegExpExecArray | null;
|
||||||
|
inviteRegex.lastIndex = 0;
|
||||||
|
while ((match = inviteRegex.exec(content)) !== null) {
|
||||||
|
if (!results.includes(match[match.length - 1])) {
|
||||||
|
results.push(match[match.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results.map(code => <EmbedInvite code={code} />);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()}
|
||||||
{queued?.error && (
|
{queued?.error && (
|
||||||
<Overline type="error" error={queued.error} />
|
<Overline type="error" error={queued.error} />
|
||||||
)}
|
)}
|
||||||
|
|
161
src/components/common/messaging/embed/EmbedInvite.tsx
Normal file
161
src/components/common/messaging/embed/EmbedInvite.tsx
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { autorun } from "mobx";
|
||||||
|
import { useHistory } from "react-router-dom";
|
||||||
|
import { RetrievedInvite } from "revolt-api/types/Invites";
|
||||||
|
|
||||||
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
|
import { defer } from "../../../../lib/defer";
|
||||||
|
|
||||||
|
import { dispatch } from "../../../../redux";
|
||||||
|
|
||||||
|
import { useClient } from "../../../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
|
import {
|
||||||
|
AppContext,
|
||||||
|
ClientStatus,
|
||||||
|
StatusContext,
|
||||||
|
} from "../../../../context/revoltjs/RevoltClient";
|
||||||
|
import { takeError } from "../../../../context/revoltjs/util";
|
||||||
|
|
||||||
|
import ServerIcon from "../../../../components/common/ServerIcon";
|
||||||
|
import Button from "../../../../components/ui/Button";
|
||||||
|
import Overline from "../../../ui/Overline";
|
||||||
|
import Preloader from "../../../ui/Preloader";
|
||||||
|
|
||||||
|
|
||||||
|
const EmbedInviteBase = styled.div`
|
||||||
|
width: 400px;
|
||||||
|
height: 80px;
|
||||||
|
background-color: var(--secondary-background);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 12px;
|
||||||
|
margin-top: 2px;
|
||||||
|
`;
|
||||||
|
const EmbedInviteDetails = styled.div`
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-left: 12px;
|
||||||
|
`;
|
||||||
|
const EmbedInviteName = styled.div`
|
||||||
|
font-weight: bold;
|
||||||
|
`;
|
||||||
|
const EmbedInviteMemberCount = styled.div`
|
||||||
|
font-size: 0.8em;
|
||||||
|
`;
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
code: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function EmbedInvite(props: Props) {
|
||||||
|
const history = useHistory();
|
||||||
|
const client = useContext(AppContext);
|
||||||
|
const status = useContext(StatusContext);
|
||||||
|
const code = props.code;
|
||||||
|
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 (typeof invite === "undefined") {
|
||||||
|
return error ? (
|
||||||
|
<EmbedInviteBase>
|
||||||
|
<ServerIcon
|
||||||
|
size={55}
|
||||||
|
/>
|
||||||
|
<EmbedInviteDetails>
|
||||||
|
<EmbedInviteName>
|
||||||
|
Invalid invite!
|
||||||
|
</EmbedInviteName>
|
||||||
|
</EmbedInviteDetails>
|
||||||
|
</EmbedInviteBase>
|
||||||
|
) : (
|
||||||
|
<EmbedInviteBase>
|
||||||
|
<Preloader type="ring" />
|
||||||
|
</EmbedInviteBase>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <EmbedInviteBase>
|
||||||
|
<ServerIcon
|
||||||
|
attachment={invite.server_icon}
|
||||||
|
server_name={invite.server_name}
|
||||||
|
size={55}
|
||||||
|
/>
|
||||||
|
<EmbedInviteDetails>
|
||||||
|
<EmbedInviteName>
|
||||||
|
{invite.server_name}
|
||||||
|
</EmbedInviteName>
|
||||||
|
<EmbedInviteMemberCount>
|
||||||
|
{invite.member_count} members
|
||||||
|
</EmbedInviteMemberCount>
|
||||||
|
</EmbedInviteDetails>
|
||||||
|
{processing ? (
|
||||||
|
<div>
|
||||||
|
<Preloader type="ring" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Button onClick={async () => {
|
||||||
|
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);
|
||||||
|
setProcessing(false);
|
||||||
|
} catch (err) {
|
||||||
|
setError(takeError(err));
|
||||||
|
setProcessing(false);
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
{client.servers.get(invite.server_id) ? "Joined" : "Join"}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</EmbedInviteBase>
|
||||||
|
}
|
Loading…
Reference in a new issue