Use tabWidth 4 without actual tabs.

This commit is contained in:
Paul
2021-07-05 11:25:20 +01:00
parent a9ce64c9fe
commit 14809f1989
180 changed files with 16619 additions and 16622 deletions

View File

@@ -3,30 +3,30 @@ 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

@@ -3,28 +3,28 @@ 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

@@ -13,164 +13,164 @@ 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

@@ -12,67 +12,67 @@ 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

@@ -21,453 +21,453 @@ 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,
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>
);
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);
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);
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.ban_member`} />}
actions={[
{
text: <Text id="app.special.modals.actions.ban" />,
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.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);
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(),
},
);
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;
}
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

@@ -3,22 +3,22 @@ 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" />,
},
]}
/>
);
}