Run prettier on all files.

This commit is contained in:
Paul
2021-07-05 11:23:23 +01:00
parent 50cd6fc1ee
commit a9ce64c9fe
181 changed files with 18084 additions and 13521 deletions

View File

@@ -1,32 +1,32 @@
import { Text } from "preact-i18n";
import Modal from "../../../components/ui/Modal";
interface Props {
onClose: () => void;
text: string;
onClose: () => void;
text: string;
}
export function ClipboardModal({ onClose, text }: Props) {
return (
<Modal
visible={true}
onClose={onClose}
title={<Text id="app.special.modals.clipboard.unavailable" />}
actions={[
{
onClick: onClose,
confirmation: true,
text: <Text id="app.special.modals.actions.close" />
}
]}
>
{location.protocol !== "https:" && (
<p>
<Text id="app.special.modals.clipboard.https" />
</p>
)}
<Text id="app.special.modals.clipboard.copy" />{" "}
<code style={{ userSelect: "all" }}>{text}</code>
</Modal>
);
return (
<Modal
visible={true}
onClose={onClose}
title={<Text id="app.special.modals.clipboard.unavailable" />}
actions={[
{
onClick: onClose,
confirmation: true,
text: <Text id="app.special.modals.actions.close" />,
},
]}>
{location.protocol !== "https:" && (
<p>
<Text id="app.special.modals.clipboard.https" />
</p>
)}
<Text id="app.special.modals.clipboard.copy" />{" "}
<code style={{ userSelect: "all" }}>{text}</code>
</Modal>
);
}

View File

@@ -1,30 +1,30 @@
import { Text } from "preact-i18n";
import Modal from "../../../components/ui/Modal";
interface Props {
onClose: () => void;
error: string;
onClose: () => void;
error: string;
}
export function ErrorModal({ onClose, error }: Props) {
return (
<Modal
visible={true}
onClose={() => false}
title={<Text id="app.special.modals.error" />}
actions={[
{
onClick: onClose,
confirmation: true,
text: <Text id="app.special.modals.actions.ok" />
},
{
onClick: () => location.reload(),
text: <Text id="app.special.modals.actions.reload" />
}
]}
>
<Text id={`error.${error}`}>{error}</Text>
</Modal>
);
return (
<Modal
visible={true}
onClose={() => false}
title={<Text id="app.special.modals.error" />}
actions={[
{
onClick: onClose,
confirmation: true,
text: <Text id="app.special.modals.actions.ok" />,
},
{
onClick: () => location.reload(),
text: <Text id="app.special.modals.actions.reload" />,
},
]}>
<Text id={`error.${error}`}>{error}</Text>
</Modal>
);
}

View File

@@ -1,154 +1,176 @@
import { ulid } from "ulid";
import { Text } from "preact-i18n";
import { useHistory } from "react-router";
import Modal from "../../../components/ui/Modal";
import { Children } from "../../../types/Preact";
import { takeError } from "../../revoltjs/util";
import { ulid } from "ulid";
import { Text } from "preact-i18n";
import { useContext, useState } from "preact/hooks";
import Overline from '../../../components/ui/Overline';
import InputBox from '../../../components/ui/InputBox';
import InputBox from "../../../components/ui/InputBox";
import Modal from "../../../components/ui/Modal";
import Overline from "../../../components/ui/Overline";
import { Children } from "../../../types/Preact";
import { AppContext } from "../../revoltjs/RevoltClient";
import { takeError } from "../../revoltjs/util";
interface Props {
onClose: () => void;
question: Children;
field?: Children;
defaultValue?: string;
callback: (value: string) => Promise<void>;
onClose: () => void;
question: Children;
field?: Children;
defaultValue?: string;
callback: (value: string) => Promise<void>;
}
export function InputModal({
onClose,
question,
field,
defaultValue,
callback
onClose,
question,
field,
defaultValue,
callback,
}: Props) {
const [processing, setProcessing] = useState(false);
const [value, setValue] = useState(defaultValue ?? "");
const [error, setError] = useState<undefined | string>(undefined);
const [processing, setProcessing] = useState(false);
const [value, setValue] = useState(defaultValue ?? "");
const [error, setError] = useState<undefined | string>(undefined);
return (
<Modal
visible={true}
title={question}
disabled={processing}
actions={[
{
confirmation: true,
text: <Text id="app.special.modals.actions.ok" />,
onClick: () => {
setProcessing(true);
callback(value)
.then(onClose)
.catch(err => {
setError(takeError(err));
setProcessing(false)
})
}
},
{
text: <Text id="app.special.modals.actions.cancel" />,
onClick: onClose
}
]}
onClose={onClose}
>
<form>
{ field ? <Overline error={error} block>
{field}
</Overline> : (error && <Overline error={error} type="error" block />) }
<InputBox
value={value}
onChange={e => setValue(e.currentTarget.value)}
/>
</form>
</Modal>
);
return (
<Modal
visible={true}
title={question}
disabled={processing}
actions={[
{
confirmation: true,
text: <Text id="app.special.modals.actions.ok" />,
onClick: () => {
setProcessing(true);
callback(value)
.then(onClose)
.catch((err) => {
setError(takeError(err));
setProcessing(false);
});
},
},
{
text: <Text id="app.special.modals.actions.cancel" />,
onClick: onClose,
},
]}
onClose={onClose}>
<form>
{field ? (
<Overline error={error} block>
{field}
</Overline>
) : (
error && <Overline error={error} type="error" block />
)}
<InputBox
value={value}
onChange={(e) => setValue(e.currentTarget.value)}
/>
</form>
</Modal>
);
}
type SpecialProps = { onClose: () => void } & (
{ type: "create_group" | "create_server" | "set_custom_status" | "add_friend" } |
{ type: "create_role", server: string, callback: (id: string) => void }
)
| {
type:
| "create_group"
| "create_server"
| "set_custom_status"
| "add_friend";
}
| { type: "create_role"; server: string; callback: (id: string) => void }
);
export function SpecialInputModal(props: SpecialProps) {
const history = useHistory();
const client = useContext(AppContext);
const history = useHistory();
const client = useContext(AppContext);
const { onClose } = props;
switch (props.type) {
case "create_group": {
return <InputModal
onClose={onClose}
question={<Text id="app.main.groups.create" />}
field={<Text id="app.main.groups.name" />}
callback={async name => {
const group = await client.channels.createGroup(
{
name,
nonce: ulid(),
users: []
}
);
const { onClose } = props;
switch (props.type) {
case "create_group": {
return (
<InputModal
onClose={onClose}
question={<Text id="app.main.groups.create" />}
field={<Text id="app.main.groups.name" />}
callback={async (name) => {
const group = await client.channels.createGroup({
name,
nonce: ulid(),
users: [],
});
history.push(`/channel/${group._id}`);
}}
/>;
}
case "create_server": {
return <InputModal
onClose={onClose}
question={<Text id="app.main.servers.create" />}
field={<Text id="app.main.servers.name" />}
callback={async name => {
const server = await client.servers.createServer(
{
name,
nonce: ulid()
}
);
history.push(`/channel/${group._id}`);
}}
/>
);
}
case "create_server": {
return (
<InputModal
onClose={onClose}
question={<Text id="app.main.servers.create" />}
field={<Text id="app.main.servers.name" />}
callback={async (name) => {
const server = await client.servers.createServer({
name,
nonce: ulid(),
});
history.push(`/server/${server._id}`);
}}
/>;
}
case "create_role": {
return <InputModal
onClose={onClose}
question={<Text id="app.settings.permissions.create_role" />}
field={<Text id="app.settings.permissions.role_name" />}
callback={async name => {
const role = await client.servers.createRole(props.server, name);
props.callback(role.id);
}}
/>;
}
case "set_custom_status": {
return <InputModal
onClose={onClose}
question={<Text id="app.context_menu.set_custom_status" />}
field={<Text id="app.context_menu.custom_status" />}
defaultValue={client.user?.status?.text}
callback={text =>
client.users.editUser({
status: {
...client.user?.status,
text: text.trim().length > 0 ? text : undefined
}
})
}
/>;
}
case "add_friend": {
return <InputModal
onClose={onClose}
question={"Add Friend"}
callback={username =>
client.users.addFriend(username)
}
/>;
}
default: return null;
}
history.push(`/server/${server._id}`);
}}
/>
);
}
case "create_role": {
return (
<InputModal
onClose={onClose}
question={
<Text id="app.settings.permissions.create_role" />
}
field={<Text id="app.settings.permissions.role_name" />}
callback={async (name) => {
const role = await client.servers.createRole(
props.server,
name,
);
props.callback(role.id);
}}
/>
);
}
case "set_custom_status": {
return (
<InputModal
onClose={onClose}
question={<Text id="app.context_menu.set_custom_status" />}
field={<Text id="app.context_menu.custom_status" />}
defaultValue={client.user?.status?.text}
callback={(text) =>
client.users.editUser({
status: {
...client.user?.status,
text: text.trim().length > 0 ? text : undefined,
},
})
}
/>
);
}
case "add_friend": {
return (
<InputModal
onClose={onClose}
question={"Add Friend"}
callback={(username) => client.users.addFriend(username)}
/>
);
}
default:
return null;
}
}

View File

@@ -1,71 +1,78 @@
import { SubmitHandler, useForm } from "react-hook-form";
import styles from "./Onboarding.module.scss";
import { Text } from "preact-i18n";
import { useState } from "preact/hooks";
import { SubmitHandler, useForm } from "react-hook-form";
import styles from "./Onboarding.module.scss";
import { takeError } from "../../revoltjs/util";
import wideSVG from "../../../assets/wide.svg";
import Button from "../../../components/ui/Button";
import FormField from "../../../pages/login/FormField";
import Preloader from "../../../components/ui/Preloader";
import wideSVG from '../../../assets/wide.svg';
import FormField from "../../../pages/login/FormField";
import { takeError } from "../../revoltjs/util";
interface Props {
onClose: () => void;
callback: (username: string, loginAfterSuccess?: true) => Promise<void>;
onClose: () => void;
callback: (username: string, loginAfterSuccess?: true) => Promise<void>;
}
interface FormInputs {
username: string
username: string;
}
export function OnboardingModal({ onClose, callback }: Props) {
const { handleSubmit, register } = useForm<FormInputs>();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | undefined>(undefined);
const { handleSubmit, register } = useForm<FormInputs>();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | undefined>(undefined);
const onSubmit: SubmitHandler<FormInputs> = ({ username }) => {
setLoading(true);
callback(username, true)
.then(onClose)
.catch((err: any) => {
setError(takeError(err));
setLoading(false);
});
}
const onSubmit: SubmitHandler<FormInputs> = ({ username }) => {
setLoading(true);
callback(username, true)
.then(onClose)
.catch((err: any) => {
setError(takeError(err));
setLoading(false);
});
};
return (
<div className={styles.onboarding}>
<div className={styles.header}>
<h1>
<Text id="app.special.modals.onboarding.welcome" />
<img src={wideSVG} />
</h1>
</div>
<div className={styles.form}>
{loading ? (
<Preloader type="spinner" />
) : (
<>
<p>
<Text id="app.special.modals.onboarding.pick" />
</p>
<form onSubmit={handleSubmit(onSubmit) as JSX.GenericEventHandler<HTMLFormElement>}>
<div>
<FormField
type="username"
register={register}
showOverline
error={error}
/>
</div>
<Button type="submit">
<Text id="app.special.modals.actions.continue" />
</Button>
</form>
</>
)}
</div>
<div />
</div>
);
return (
<div className={styles.onboarding}>
<div className={styles.header}>
<h1>
<Text id="app.special.modals.onboarding.welcome" />
<img src={wideSVG} />
</h1>
</div>
<div className={styles.form}>
{loading ? (
<Preloader type="spinner" />
) : (
<>
<p>
<Text id="app.special.modals.onboarding.pick" />
</p>
<form
onSubmit={
handleSubmit(
onSubmit,
) as JSX.GenericEventHandler<HTMLFormElement>
}>
<div>
<FormField
type="username"
register={register}
showOverline
error={error}
/>
</div>
<Button type="submit">
<Text id="app.special.modals.actions.continue" />
</Button>
</form>
</>
)}
</div>
<div />
</div>
);
}

View File

@@ -1,346 +1,473 @@
import { ulid } from "ulid";
import { Text } from "preact-i18n";
import styles from './Prompt.module.scss';
import { useHistory } from "react-router-dom";
import Radio from "../../../components/ui/Radio";
import { Children } from "../../../types/Preact";
import { useIntermediate } from "../Intermediate";
import InputBox from "../../../components/ui/InputBox";
import Overline from "../../../components/ui/Overline";
import { AppContext } from "../../revoltjs/RevoltClient";
import { mapMessage, takeError } from "../../revoltjs/util";
import Modal, { Action } from "../../../components/ui/Modal";
import { Channels, Servers, Users } from "revolt.js/dist/api/objects";
import { ulid } from "ulid";
import styles from "./Prompt.module.scss";
import { Text } from "preact-i18n";
import { useContext, useEffect, useState } from "preact/hooks";
import UserIcon from "../../../components/common/user/UserIcon";
import Message from "../../../components/common/messaging/Message";
import { TextReact } from "../../../lib/i18n";
import Message from "../../../components/common/messaging/Message";
import UserIcon from "../../../components/common/user/UserIcon";
import InputBox from "../../../components/ui/InputBox";
import Modal, { Action } from "../../../components/ui/Modal";
import Overline from "../../../components/ui/Overline";
import Radio from "../../../components/ui/Radio";
import { Children } from "../../../types/Preact";
import { AppContext } from "../../revoltjs/RevoltClient";
import { mapMessage, takeError } from "../../revoltjs/util";
import { useIntermediate } from "../Intermediate";
interface Props {
onClose: () => void;
question: Children;
content?: Children;
disabled?: boolean;
actions: Action[];
error?: string;
onClose: () => void;
question: Children;
content?: Children;
disabled?: boolean;
actions: Action[];
error?: string;
}
export function PromptModal({ onClose, question, content, actions, disabled, error }: Props) {
return (
<Modal
visible={true}
title={question}
actions={actions}
onClose={onClose}
disabled={disabled}>
{ error && <Overline error={error} type="error" /> }
{ content }
</Modal>
);
export function PromptModal({
onClose,
question,
content,
actions,
disabled,
error,
}: Props) {
return (
<Modal
visible={true}
title={question}
actions={actions}
onClose={onClose}
disabled={disabled}>
{error && <Overline error={error} type="error" />}
{content}
</Modal>
);
}
type SpecialProps = { onClose: () => void } & (
{ type: "leave_group", target: Channels.GroupChannel } |
{ type: "close_dm", target: Channels.DirectMessageChannel } |
{ type: "leave_server", target: Servers.Server } |
{ type: "delete_server", target: Servers.Server } |
{ type: "delete_channel", target: Channels.TextChannel } |
{ type: "delete_message", target: Channels.Message } |
{ type: "create_invite", target: Channels.TextChannel | Channels.GroupChannel } |
{ type: "kick_member", target: Servers.Server, user: string } |
{ type: "ban_member", target: Servers.Server, user: string } |
{ type: "unfriend_user", target: Users.User } |
{ type: "block_user", target: Users.User } |
{ type: "create_channel", target: Servers.Server }
)
| { type: "leave_group"; target: Channels.GroupChannel }
| { type: "close_dm"; target: Channels.DirectMessageChannel }
| { type: "leave_server"; target: Servers.Server }
| { type: "delete_server"; target: Servers.Server }
| { type: "delete_channel"; target: Channels.TextChannel }
| { type: "delete_message"; target: Channels.Message }
| {
type: "create_invite";
target: Channels.TextChannel | Channels.GroupChannel;
}
| { type: "kick_member"; target: Servers.Server; user: string }
| { type: "ban_member"; target: Servers.Server; user: string }
| { type: "unfriend_user"; target: Users.User }
| { type: "block_user"; target: Users.User }
| { type: "create_channel"; target: Servers.Server }
);
export function SpecialPromptModal(props: SpecialProps) {
const client = useContext(AppContext);
const [ processing, setProcessing ] = useState(false);
const [ error, setError ] = useState<undefined | string>(undefined);
const client = useContext(AppContext);
const [processing, setProcessing] = useState(false);
const [error, setError] = useState<undefined | string>(undefined);
const { onClose } = props;
switch (props.type) {
case 'leave_group':
case 'close_dm':
case 'leave_server':
case 'delete_server':
case 'delete_channel':
case 'unfriend_user':
case 'block_user': {
const EVENTS = {
'close_dm': ['confirm_close_dm', 'close'],
'delete_server': ['confirm_delete', 'delete'],
'delete_channel': ['confirm_delete', 'delete'],
'leave_group': ['confirm_leave', 'leave'],
'leave_server': ['confirm_leave', 'leave'],
'unfriend_user': ['unfriend_user', 'remove'],
'block_user': ['block_user', 'block']
};
const { onClose } = props;
switch (props.type) {
case "leave_group":
case "close_dm":
case "leave_server":
case "delete_server":
case "delete_channel":
case "unfriend_user":
case "block_user": {
const EVENTS = {
close_dm: ["confirm_close_dm", "close"],
delete_server: ["confirm_delete", "delete"],
delete_channel: ["confirm_delete", "delete"],
leave_group: ["confirm_leave", "leave"],
leave_server: ["confirm_leave", "leave"],
unfriend_user: ["unfriend_user", "remove"],
block_user: ["block_user", "block"],
};
let event = EVENTS[props.type];
let name;
switch (props.type) {
case 'unfriend_user':
case 'block_user': name = props.target.username; break;
case 'close_dm': name = client.users.get(client.channels.getRecipient(props.target._id))?.username; break;
default: name = props.target.name;
}
let event = EVENTS[props.type];
let name;
switch (props.type) {
case "unfriend_user":
case "block_user":
name = props.target.username;
break;
case "close_dm":
name = client.users.get(
client.channels.getRecipient(props.target._id),
)?.username;
break;
default:
name = props.target.name;
}
return (
<PromptModal
onClose={onClose}
question={<Text
id={`app.special.modals.prompt.${event[0]}`}
fields={{ name }}
/>}
actions={[
{
confirmation: true,
contrast: true,
error: true,
text: <Text id={`app.special.modals.actions.${event[1]}`} />,
onClick: async () => {
setProcessing(true);
return (
<PromptModal
onClose={onClose}
question={
<Text
id={`app.special.modals.prompt.${event[0]}`}
fields={{ name }}
/>
}
actions={[
{
confirmation: true,
contrast: true,
error: true,
text: (
<Text
id={`app.special.modals.actions.${event[1]}`}
/>
),
onClick: async () => {
setProcessing(true);
try {
switch (props.type) {
case 'unfriend_user':
await client.users.removeFriend(props.target._id); break;
case 'block_user':
await client.users.blockUser(props.target._id); break;
case 'leave_group':
case 'close_dm':
case 'delete_channel':
await client.channels.delete(props.target._id); break;
case 'leave_server':
case 'delete_server':
await client.servers.delete(props.target._id); break;
}
try {
switch (props.type) {
case "unfriend_user":
await client.users.removeFriend(
props.target._id,
);
break;
case "block_user":
await client.users.blockUser(
props.target._id,
);
break;
case "leave_group":
case "close_dm":
case "delete_channel":
await client.channels.delete(
props.target._id,
);
break;
case "leave_server":
case "delete_server":
await client.servers.delete(
props.target._id,
);
break;
}
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
}
},
{ text: <Text id="app.special.modals.actions.cancel" />, onClick: onClose }
]}
content={<TextReact id={`app.special.modals.prompt.${event[0]}_long`} fields={{ name: <b>{ name }</b> }} />}
disabled={processing}
error={error}
/>
)
}
case 'delete_message': {
return (
<PromptModal
onClose={onClose}
question={<Text id={'app.context_menu.delete_message'} />}
actions={[
{
confirmation: true,
contrast: true,
error: true,
text: <Text id="app.special.modals.actions.delete" />,
onClick: async () => {
setProcessing(true);
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
},
},
{
text: (
<Text id="app.special.modals.actions.cancel" />
),
onClick: onClose,
},
]}
content={
<TextReact
id={`app.special.modals.prompt.${event[0]}_long`}
fields={{ name: <b>{name}</b> }}
/>
}
disabled={processing}
error={error}
/>
);
}
case "delete_message": {
return (
<PromptModal
onClose={onClose}
question={<Text id={"app.context_menu.delete_message"} />}
actions={[
{
confirmation: true,
contrast: true,
error: true,
text: (
<Text id="app.special.modals.actions.delete" />
),
onClick: async () => {
setProcessing(true);
try {
await client.channels.deleteMessage(props.target.channel, props.target._id);
try {
await client.channels.deleteMessage(
props.target.channel,
props.target._id,
);
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
}
},
{ text: <Text id="app.special.modals.actions.cancel" />, onClick: onClose }
]}
content={<>
<Text id={`app.special.modals.prompt.confirm_delete_message_long`} />
<Message message={mapMessage(props.target)} head={true} contrast />
</>}
disabled={processing}
error={error}
/>
)
}
case "create_invite": {
const [ code, setCode ] = useState('abcdef');
const { writeClipboard } = useIntermediate();
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
},
},
{
text: (
<Text id="app.special.modals.actions.cancel" />
),
onClick: onClose,
},
]}
content={
<>
<Text
id={`app.special.modals.prompt.confirm_delete_message_long`}
/>
<Message
message={mapMessage(props.target)}
head={true}
contrast
/>
</>
}
disabled={processing}
error={error}
/>
);
}
case "create_invite": {
const [code, setCode] = useState("abcdef");
const { writeClipboard } = useIntermediate();
useEffect(() => {
setProcessing(true);
useEffect(() => {
setProcessing(true);
client.channels.createInvite(props.target._id)
.then(code => setCode(code))
.catch(err => setError(takeError(err)))
.finally(() => setProcessing(false));
}, []);
client.channels
.createInvite(props.target._id)
.then((code) => setCode(code))
.catch((err) => setError(takeError(err)))
.finally(() => setProcessing(false));
}, []);
return (
<PromptModal
onClose={onClose}
question={<Text id={`app.context_menu.create_invite`} />}
actions={[
{
text: <Text id="app.special.modals.actions.ok" />,
confirmation: true,
onClick: onClose
},
{
text: <Text id="app.context_menu.copy_link" />,
onClick: () => writeClipboard(`${window.location.protocol}//${window.location.host}/invite/${code}`)
}
]}
content={
processing ?
<Text id="app.special.modals.prompt.create_invite_generate" />
: <div className={styles.invite}>
<Text id="app.special.modals.prompt.create_invite_created" />
<code>{code}</code>
</div>
}
disabled={processing}
error={error}
/>
)
}
case "kick_member": {
const user = client.users.get(props.user);
return (
<PromptModal
onClose={onClose}
question={<Text id={`app.context_menu.create_invite`} />}
actions={[
{
text: <Text id="app.special.modals.actions.ok" />,
confirmation: true,
onClick: onClose,
},
{
text: <Text id="app.context_menu.copy_link" />,
onClick: () =>
writeClipboard(
`${window.location.protocol}//${window.location.host}/invite/${code}`,
),
},
]}
content={
processing ? (
<Text id="app.special.modals.prompt.create_invite_generate" />
) : (
<div className={styles.invite}>
<Text id="app.special.modals.prompt.create_invite_created" />
<code>{code}</code>
</div>
)
}
disabled={processing}
error={error}
/>
);
}
case "kick_member": {
const user = client.users.get(props.user);
return (
<PromptModal
onClose={onClose}
question={<Text id={`app.context_menu.kick_member`} />}
actions={[
{
text: <Text id="app.special.modals.actions.kick" />,
contrast: true,
error: true,
confirmation: true,
onClick: async () => {
setProcessing(true);
try {
await client.servers.members.kickMember(props.target._id, props.user);
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
}
},
{ text: <Text id="app.special.modals.actions.cancel" />, onClick: onClose }
]}
content={<div className={styles.column}>
<UserIcon target={user} size={64} />
<Text
id="app.special.modals.prompt.confirm_kick"
fields={{ name: user?.username }} />
</div>}
disabled={processing}
error={error}
/>
)
}
case "ban_member": {
const [ reason, setReason ] = useState<string | undefined>(undefined);
const user = client.users.get(props.user);
return (
<PromptModal
onClose={onClose}
question={<Text id={`app.context_menu.kick_member`} />}
actions={[
{
text: <Text id="app.special.modals.actions.kick" />,
contrast: true,
error: true,
confirmation: true,
onClick: async () => {
setProcessing(true);
return (
<PromptModal
onClose={onClose}
question={<Text id={`app.context_menu.ban_member`} />}
actions={[
{
text: <Text id="app.special.modals.actions.ban" />,
contrast: true,
error: true,
confirmation: true,
onClick: async () => {
setProcessing(true);
try {
await client.servers.banUser(props.target._id, props.user, { reason });
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
}
},
{ text: <Text id="app.special.modals.actions.cancel" />, onClick: onClose }
]}
content={<div className={styles.column}>
<UserIcon target={user} size={64} />
<Text
id="app.special.modals.prompt.confirm_ban"
fields={{ name: user?.username }} />
<Overline><Text id="app.special.modals.prompt.confirm_ban_reason" /></Overline>
<InputBox value={reason ?? ''} onChange={e => setReason(e.currentTarget.value)} />
</div>}
disabled={processing}
error={error}
/>
)
}
case 'create_channel': {
const [ name, setName ] = useState('');
const [ type, setType ] = useState<'Text' | 'Voice'>('Text');
const history = useHistory();
try {
await client.servers.members.kickMember(
props.target._id,
props.user,
);
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
},
},
{
text: (
<Text id="app.special.modals.actions.cancel" />
),
onClick: onClose,
},
]}
content={
<div className={styles.column}>
<UserIcon target={user} size={64} />
<Text
id="app.special.modals.prompt.confirm_kick"
fields={{ name: user?.username }}
/>
</div>
}
disabled={processing}
error={error}
/>
);
}
case "ban_member": {
const [reason, setReason] = useState<string | undefined>(undefined);
const user = client.users.get(props.user);
return (
<PromptModal
onClose={onClose}
question={<Text id="app.context_menu.create_channel" />}
actions={[
{
confirmation: true,
contrast: true,
text: <Text id="app.special.modals.actions.create" />,
onClick: async () => {
setProcessing(true);
return (
<PromptModal
onClose={onClose}
question={<Text id={`app.context_menu.ban_member`} />}
actions={[
{
text: <Text id="app.special.modals.actions.ban" />,
contrast: true,
error: true,
confirmation: true,
onClick: async () => {
setProcessing(true);
try {
const channel = await client.servers.createChannel(
props.target._id,
{
type,
name,
nonce: ulid()
}
);
history.push(`/server/${props.target._id}/channel/${channel._id}`);
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
}
},
{ text: <Text id="app.special.modals.actions.cancel" />, onClick: onClose }
]}
content={<>
<Overline block type="subtle"><Text id="app.main.servers.channel_type" /></Overline>
<Radio checked={type === 'Text'} onSelect={() => setType('Text')}>
<Text id="app.main.servers.text_channel" /></Radio>
<Radio checked={type === 'Voice'} onSelect={() => setType('Voice')}>
<Text id="app.main.servers.voice_channel" /></Radio>
<Overline block type="subtle"><Text id="app.main.servers.channel_name" /></Overline>
<InputBox
value={name}
onChange={e => setName(e.currentTarget.value)} />
</>}
disabled={processing}
error={error}
/>
)
}
default: return null;
}
try {
await client.servers.banUser(
props.target._id,
props.user,
{ reason },
);
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
},
},
{
text: (
<Text id="app.special.modals.actions.cancel" />
),
onClick: onClose,
},
]}
content={
<div className={styles.column}>
<UserIcon target={user} size={64} />
<Text
id="app.special.modals.prompt.confirm_ban"
fields={{ name: user?.username }}
/>
<Overline>
<Text id="app.special.modals.prompt.confirm_ban_reason" />
</Overline>
<InputBox
value={reason ?? ""}
onChange={(e) =>
setReason(e.currentTarget.value)
}
/>
</div>
}
disabled={processing}
error={error}
/>
);
}
case "create_channel": {
const [name, setName] = useState("");
const [type, setType] = useState<"Text" | "Voice">("Text");
const history = useHistory();
return (
<PromptModal
onClose={onClose}
question={<Text id="app.context_menu.create_channel" />}
actions={[
{
confirmation: true,
contrast: true,
text: (
<Text id="app.special.modals.actions.create" />
),
onClick: async () => {
setProcessing(true);
try {
const channel =
await client.servers.createChannel(
props.target._id,
{
type,
name,
nonce: ulid(),
},
);
history.push(
`/server/${props.target._id}/channel/${channel._id}`,
);
onClose();
} catch (err) {
setError(takeError(err));
setProcessing(false);
}
},
},
{
text: (
<Text id="app.special.modals.actions.cancel" />
),
onClick: onClose,
},
]}
content={
<>
<Overline block type="subtle">
<Text id="app.main.servers.channel_type" />
</Overline>
<Radio
checked={type === "Text"}
onSelect={() => setType("Text")}>
<Text id="app.main.servers.text_channel" />
</Radio>
<Radio
checked={type === "Voice"}
onSelect={() => setType("Voice")}>
<Text id="app.main.servers.voice_channel" />
</Radio>
<Overline block type="subtle">
<Text id="app.main.servers.channel_name" />
</Overline>
<InputBox
value={name}
onChange={(e) => setName(e.currentTarget.value)}
/>
</>
}
disabled={processing}
error={error}
/>
);
}
default:
return null;
}
}

View File

@@ -1,23 +1,24 @@
import { Text } from "preact-i18n";
import Modal from "../../../components/ui/Modal";
interface Props {
onClose: () => void;
onClose: () => void;
}
export function SignedOutModal({ onClose }: Props) {
return (
<Modal
visible={true}
onClose={onClose}
title={<Text id="app.special.modals.signed_out" />}
actions={[
{
onClick: onClose,
confirmation: true,
text: <Text id="app.special.modals.actions.ok" />
}
]}
/>
);
return (
<Modal
visible={true}
onClose={onClose}
title={<Text id="app.special.modals.signed_out" />}
actions={[
{
onClick: onClose,
confirmation: true,
text: <Text id="app.special.modals.actions.ok" />,
},
]}
/>
);
}