feat: port input modals to new system

This commit is contained in:
Paul Makles
2022-07-05 17:53:41 +01:00
parent 23dec32476
commit 79c90c1b00
19 changed files with 275 additions and 127 deletions

View File

@@ -25,6 +25,7 @@ import { useIntermediate } from "../../../context/intermediate/Intermediate";
import placeholderSVG from "../items/placeholder.svg";
import { useClient } from "../../../controllers/client/ClientController";
import { modalController } from "../../../controllers/modals/ModalController";
import { GenericSidebarBase, GenericSidebarList } from "../SidebarBase";
import ButtonItem, { ChannelButton } from "../items/ButtonItem";
import ConnectionStatus from "../items/ConnectionStatus";
@@ -131,8 +132,7 @@ export default observer(() => {
<Text id="app.main.categories.conversations" />
<IconButton
onClick={() =>
openScreen({
id: "special_input",
modalController.push({
type: "create_group",
})
}>

View File

@@ -7,9 +7,8 @@ import { ServerList } from "@revoltchat/ui";
import { useApplicationState } from "../../../mobx/State";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import { useClient } from "../../../controllers/client/ClientController";
import { modalController } from "../../../controllers/modals/ModalController";
/**
* Server list sidebar shim component
@@ -17,13 +16,11 @@ import { useClient } from "../../../controllers/client/ClientController";
export default observer(() => {
const client = useClient();
const state = useApplicationState();
const { openScreen } = useIntermediate();
const { server: server_id } = useParams<{ server?: string }>();
const createServer = useCallback(
() =>
openScreen({
id: "special_input",
modalController.push({
type: "create_server",
}),
[],

View File

@@ -8,7 +8,21 @@ import { useApplicationState } from "../../../mobx/State";
import { FONTS, Fonts, FONT_KEYS } from "../../../context/Theme";
import { ShimDisplayEmoji } from "../appearance_legacy/Shims";
import { EmojiSelector } from "./legacy/EmojiSelector";
/**
* ! LEGACY
* Component providing a way to change emoji pack.
*/
export const ShimDisplayEmoji = observer(() => {
const settings = useApplicationState().settings;
return (
<EmojiSelector
value={settings.get("appearance:emoji")}
setValue={(v) => settings.set("appearance:emoji", v)}
/>
);
});
export default observer(() => {
const settings = useApplicationState().settings;

View File

@@ -93,96 +93,6 @@ export function SpecialInputModal(props: SpecialProps) {
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,
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" />}
description={
<div>
By creating this server, you agree to the{" "}
<a
href="https://revolt.chat/aup"
target="_blank"
rel="noreferrer">
Acceptable Use Policy.
</a>
</div>
}
callback={async (name) => {
const server = await client.servers.createServer({
name,
});
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 props.server.createRole(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 ?? undefined}
callback={(text) =>
client.users.edit({
status: {
...client.user?.status,
text: text.trim().length > 0 ? text : undefined,
},
})
}
/>
);
}
case "add_friend": {
return (
<InputModal
onClose={onClose}
question={"Add Friend"}
callback={(username) =>
client.api
.post(`/users/friend`, { username })
.then(undefined)
}
/>
);
}
default:
return null;
}

View File

@@ -27,6 +27,11 @@ export function takeError(error: any): string {
return "UnknownError";
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function mapError(error: any): never {
throw takeError(error);
}
export function getChannelName(
channel: Channel,
prefixType?: boolean,

View File

@@ -16,9 +16,14 @@ import { getApplicationState } from "../../mobx/State";
import { history } from "../../context/history";
import { __thisIsAHack } from "../../context/intermediate/Intermediate";
import AddFriend from "./components/AddFriend";
import Changelog from "./components/Changelog";
import ChannelInfo from "./components/ChannelInfo";
import Clipboard from "./components/Clipboard";
import CreateGroup from "./components/CreateGroup";
import CreateRole from "./components/CreateRole";
import CreateServer from "./components/CreateServer";
import CustomStatus from "./components/CustomStatus";
import Error from "./components/Error";
import ImageViewer from "./components/ImageViewer";
import LinkWarning from "./components/LinkWarning";
@@ -222,10 +227,15 @@ class ModalControllerExtended extends ModalController<Modal> {
}
export const modalController = new ModalControllerExtended({
add_friend: AddFriend,
changelog: Changelog,
channel_info: ChannelInfo,
clipboard: Clipboard,
create_group: CreateGroup,
create_role: CreateRole,
create_server: CreateServer,
create_bot: CreateBotModal,
custom_status: CustomStatus,
error: Error,
image_viewer: ImageViewer,
link_warning: LinkWarning,

View File

@@ -0,0 +1,31 @@
import { ModalForm } from "@revoltchat/ui";
import { noop } from "../../../lib/js";
import { useClient } from "../../client/ClientController";
import { ModalProps } from "../types";
/**
* Add friend modal
*/
export default function AddFriend({ ...props }: ModalProps<"add_friend">) {
const client = useClient();
return (
<ModalForm
{...props}
title="Add Friend"
schema={{
username: "text",
}}
data={{
username: {
field: "Username",
},
}}
callback={({ username }) =>
client.api.post(`/users/friend`, { username }).then(noop)
}
/>
);
}

View File

@@ -0,0 +1,45 @@
import { useHistory } from "react-router-dom";
import { Text } from "preact-i18n";
import { ModalForm } from "@revoltchat/ui";
import { mapError } from "../../../context/revoltjs/util";
import { useClient } from "../../client/ClientController";
import { ModalProps } from "../types";
/**
* Group creation modal
*/
export default function CreateGroup({ ...props }: ModalProps<"create_group">) {
const history = useHistory();
const client = useClient();
return (
<ModalForm
{...props}
title={<Text id="app.main.groups.create" />}
schema={{
name: "text",
}}
data={{
name: {
field: (
<Text id="app.main.groups.name" />
) as React.ReactChild,
},
}}
callback={async ({ name }) => {
const group = await client.channels
.createGroup({
name,
users: [],
})
.catch(mapError);
history.push(`/channel/${group._id}`);
}}
/>
);
}

View File

@@ -0,0 +1,35 @@
import { Text } from "preact-i18n";
import { ModalForm } from "@revoltchat/ui";
import { ModalProps } from "../types";
/**
* Role creation modal
*/
export default function CreateRole({
server,
callback,
...props
}: ModalProps<"create_role">) {
return (
<ModalForm
{...props}
title={<Text id="app.settings.permissions.create_role" />}
schema={{
name: "text",
}}
data={{
name: {
field: (
<Text id="app.settings.permissions.role_name" />
) as React.ReactChild,
},
}}
callback={async ({ name }) => {
const role = await server.createRole(name);
callback(role.id);
}}
/>
);
}

View File

@@ -0,0 +1,57 @@
import { useHistory } from "react-router-dom";
import { Text } from "preact-i18n";
import { ModalForm } from "@revoltchat/ui";
import { mapError } from "../../../context/revoltjs/util";
import { useClient } from "../../client/ClientController";
import { ModalProps } from "../types";
/**
* Server creation modal
*/
export default function CreateServer({
...props
}: ModalProps<"create_server">) {
const history = useHistory();
const client = useClient();
return (
<ModalForm
{...props}
title={<Text id="app.main.servers.create" />}
description={
<div>
By creating this server, you agree to the{" "}
<a
href="https://revolt.chat/aup"
target="_blank"
rel="noreferrer">
Acceptable Use Policy.
</a>
</div>
}
schema={{
name: "text",
}}
data={{
name: {
field: (
<Text id="app.main.servers.name" />
) as React.ReactChild,
},
}}
callback={async ({ name }) => {
const server = await client.servers
.createServer({
name,
})
.catch(mapError);
history.push(`/server/${server._id}`);
}}
/>
);
}

View File

@@ -0,0 +1,43 @@
import { Text } from "preact-i18n";
import { ModalForm } from "@revoltchat/ui";
import { useClient } from "../../client/ClientController";
import { ModalProps } from "../types";
/**
* Custom status modal
*/
export default function CustomStatus({
...props
}: ModalProps<"custom_status">) {
const client = useClient();
return (
<ModalForm
{...props}
title={<Text id="app.context_menu.set_custom_status" />}
schema={{
text: "text",
}}
defaults={{
text: client.user?.status?.text as string,
}}
data={{
text: {
field: (
<Text id="app.context_menu.custom_status" />
) as React.ReactChild,
},
}}
callback={({ text }) =>
client.users.edit({
status: {
...client.user?.status,
text: text.trim().length > 0 ? text : undefined,
},
})
}
/>
);
}

View File

@@ -3,6 +3,14 @@ import { API, Client, User, Member, Channel, Server } from "revolt.js";
export type Modal = {
key?: string;
} & (
| {
type:
| "signed_out"
| "create_group"
| "create_server"
| "custom_status"
| "add_friend";
}
| ({
type: "mfa_flow";
} & (
@@ -69,9 +77,6 @@ export type Modal = {
type: "server_identity";
member: Member;
}
| {
type: "signed_out";
}
| {
type: "channel_info";
channel: Channel;
@@ -107,6 +112,11 @@ export type Modal = {
loginAfterSuccess?: true,
) => Promise<void>;
}
| {
type: "create_role";
server: Server;
callback: (id: string) => void;
}
);
export type ModalProps<T extends Modal["type"]> = Modal & { type: T } & {

View File

@@ -368,9 +368,8 @@ export default function ContextMenus() {
break;
case "set_status":
openScreen({
id: "special_input",
type: "set_custom_status",
modalController.push({
type: "custom_status",
});
break;

View File

@@ -85,8 +85,7 @@ export default observer(() => {
<Tooltip content={"Create Group"} placement="bottom">
<IconButton
onClick={() =>
openScreen({
id: "special_input",
modalController.push({
type: "create_group",
})
}>
@@ -96,8 +95,7 @@ export default observer(() => {
<Tooltip content={"Add Friend"} placement="bottom">
<IconButton
onClick={() =>
openScreen({
id: "special_input",
modalController.push({
type: "add_friend",
})
}>

View File

@@ -29,6 +29,7 @@ import wideSVG from "/assets/wide.svg";
import { PageHeader } from "../../components/ui/Header";
import { useClient } from "../../controllers/client/ClientController";
import { modalController } from "../../controllers/modals/ModalController";
const Overlay = styled.div`
display: grid;
@@ -98,8 +99,7 @@ export default observer(() => {
<div className={styles.actions}>
<a
onClick={() =>
openScreen({
id: "special_input",
modalController.push({
type: "create_group",
})
}>

View File

@@ -347,9 +347,8 @@ export default observer(() => {
<a
className="status"
onClick={() =>
openScreen({
id: "special_input",
type: "set_custom_status",
modalController.push({
type: "custom_status",
})
}>
Change your status...

View File

@@ -16,10 +16,9 @@ import {
Category,
} from "@revoltchat/ui";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import { PermissionList } from "../../../components/settings/roles/PermissionList";
import { RoleOrDefault } from "../../../components/settings/roles/RoleSelection";
import { modalController } from "../../../controllers/modals/ModalController";
interface Props {
server: Server;
@@ -54,18 +53,14 @@ export const Roles = observer(({ server }: Props) => {
// Consolidate all permissions that we can change right now.
const currentRoles = useRoles(server);
// Pull in modal context.
const { openScreen } = useIntermediate();
return (
<PermissionsLayout
server={server}
rank={server.member?.ranking ?? Infinity}
onCreateRole={(callback) =>
openScreen({
id: "special_input",
modalController.push({
type: "create_role",
server: server as any,
server,
callback,
})
}