mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-25 16:40:58 -05:00
chore: delete intermediate
This commit is contained in:
parent
f7ff7d0dfe
commit
f9c6f5cd9d
35 changed files with 129 additions and 1104 deletions
|
@ -13,7 +13,6 @@ import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||||
import { QueuedMessage } from "../../../mobx/stores/MessageQueue";
|
import { QueuedMessage } from "../../../mobx/stores/MessageQueue";
|
||||||
|
|
||||||
import { I18nError } from "../../../context/Locale";
|
import { I18nError } from "../../../context/Locale";
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import { modalController } from "../../../controllers/modals/ModalController";
|
import { modalController } from "../../../controllers/modals/ModalController";
|
||||||
import Markdown from "../../markdown/Markdown";
|
import Markdown from "../../markdown/Markdown";
|
||||||
|
@ -55,8 +54,6 @@ const Message = observer(
|
||||||
const client = message.client;
|
const client = message.client;
|
||||||
const user = message.author;
|
const user = message.author;
|
||||||
|
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
|
|
||||||
const content = message.content;
|
const content = message.content;
|
||||||
const head =
|
const head =
|
||||||
preferHead || (message.reply_ids && message.reply_ids.length > 0);
|
preferHead || (message.reply_ids && message.reply_ids.length > 0);
|
||||||
|
|
|
@ -19,12 +19,6 @@ import { getRenderer } from "../../../../lib/renderer/Singleton";
|
||||||
|
|
||||||
import { QueuedMessage } from "../../../../mobx/stores/MessageQueue";
|
import { QueuedMessage } from "../../../../mobx/stores/MessageQueue";
|
||||||
|
|
||||||
import {
|
|
||||||
Screen,
|
|
||||||
useIntermediate,
|
|
||||||
} from "../../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import { useClient } from "../../../../controllers/client/ClientController";
|
|
||||||
import { modalController } from "../../../../controllers/modals/ModalController";
|
import { modalController } from "../../../../controllers/modals/ModalController";
|
||||||
import Tooltip from "../../../common/Tooltip";
|
import Tooltip from "../../../common/Tooltip";
|
||||||
|
|
||||||
|
@ -89,7 +83,6 @@ const Divider = styled.div`
|
||||||
|
|
||||||
export const MessageOverlayBar = observer(({ message, queued }: Props) => {
|
export const MessageOverlayBar = observer(({ message, queued }: Props) => {
|
||||||
const client = message.client;
|
const client = message.client;
|
||||||
const { openScreen, writeClipboard } = useIntermediate();
|
|
||||||
const isAuthor = message.author_id === client.user!._id;
|
const isAuthor = message.author_id === client.user!._id;
|
||||||
|
|
||||||
const [copied, setCopied] = useState<"link" | "id">(null!);
|
const [copied, setCopied] = useState<"link" | "id">(null!);
|
||||||
|
@ -189,7 +182,7 @@ export const MessageOverlayBar = observer(({ message, queued }: Props) => {
|
||||||
<Entry
|
<Entry
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCopied("link");
|
setCopied("link");
|
||||||
writeClipboard(message.url);
|
modalController.writeText(message.url);
|
||||||
}}>
|
}}>
|
||||||
<LinkAlt size={18} />
|
<LinkAlt size={18} />
|
||||||
</Entry>
|
</Entry>
|
||||||
|
@ -200,7 +193,7 @@ export const MessageOverlayBar = observer(({ message, queued }: Props) => {
|
||||||
<Entry
|
<Entry
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCopied("id");
|
setCopied("id");
|
||||||
writeClipboard(message._id);
|
modalController.writeText(message._id);
|
||||||
}}>
|
}}>
|
||||||
<InfoSquare size={18} />
|
<InfoSquare size={18} />
|
||||||
</Entry>
|
</Entry>
|
||||||
|
|
|
@ -4,8 +4,6 @@ import styles from "./Embed.module.scss";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useContext } from "preact/hooks";
|
import { useContext } from "preact/hooks";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import { useClient } from "../../../../controllers/client/ClientController";
|
import { useClient } from "../../../../controllers/client/ClientController";
|
||||||
import { modalController } from "../../../../controllers/modals/ModalController";
|
import { modalController } from "../../../../controllers/modals/ModalController";
|
||||||
import { MessageAreaWidthContext } from "../../../../pages/channels/messaging/MessageArea";
|
import { MessageAreaWidthContext } from "../../../../pages/channels/messaging/MessageArea";
|
||||||
|
@ -25,7 +23,6 @@ const MAX_PREVIEW_SIZE = 150;
|
||||||
export default function Embed({ embed }: Props) {
|
export default function Embed({ embed }: Props) {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
|
|
||||||
const { openLink } = useIntermediate();
|
|
||||||
const maxWidth = Math.min(
|
const maxWidth = Math.min(
|
||||||
useContext(MessageAreaWidthContext) - CONTAINER_PADDING,
|
useContext(MessageAreaWidthContext) - CONTAINER_PADDING,
|
||||||
MAX_EMBED_WIDTH,
|
MAX_EMBED_WIDTH,
|
||||||
|
@ -144,7 +141,7 @@ export default function Embed({ embed }: Props) {
|
||||||
<a
|
<a
|
||||||
onMouseDown={(ev) =>
|
onMouseDown={(ev) =>
|
||||||
(ev.button === 0 || ev.button === 1) &&
|
(ev.button === 0 || ev.button === 1) &&
|
||||||
openLink(embed.url!)
|
modalController.openLink(embed.url!)
|
||||||
}
|
}
|
||||||
className={styles.title}>
|
className={styles.title}>
|
||||||
{embed.title}
|
{embed.title}
|
||||||
|
@ -195,7 +192,9 @@ export default function Embed({ embed }: Props) {
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
modalController.push({ type: "image_viewer", embed })
|
modalController.push({ type: "image_viewer", embed })
|
||||||
}
|
}
|
||||||
onMouseDown={(ev) => ev.button === 1 && openLink(embed.url)}
|
onMouseDown={(ev) =>
|
||||||
|
ev.button === 1 && modalController.openLink(embed.url)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,7 @@ import { Header, IconButton } from "@revoltchat/ui";
|
||||||
|
|
||||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
import { modalController } from "../../../controllers/modals/ModalController";
|
||||||
|
|
||||||
import Tooltip from "../Tooltip";
|
import Tooltip from "../Tooltip";
|
||||||
import UserStatus from "./UserStatus";
|
import UserStatus from "./UserStatus";
|
||||||
|
|
||||||
|
@ -48,8 +47,6 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default observer(({ user }: Props) => {
|
export default observer(({ user }: Props) => {
|
||||||
const { writeClipboard } = useIntermediate();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Header topBorder palette="secondary">
|
<Header topBorder palette="secondary">
|
||||||
<HeaderBase>
|
<HeaderBase>
|
||||||
|
@ -57,7 +54,9 @@ export default observer(({ user }: Props) => {
|
||||||
<Tooltip content={<Text id="app.special.copy_username" />}>
|
<Tooltip content={<Text id="app.special.copy_username" />}>
|
||||||
<span
|
<span
|
||||||
className="username"
|
className="username"
|
||||||
onClick={() => writeClipboard(user.username)}>
|
onClick={() =>
|
||||||
|
modalController.writeText(user.username)
|
||||||
|
}>
|
||||||
@{user.username}
|
@{user.username}
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
|
@ -14,10 +14,10 @@ import { internalEmit } from "../../lib/eventEmitter";
|
||||||
import { determineLink } from "../../lib/links";
|
import { determineLink } from "../../lib/links";
|
||||||
|
|
||||||
import { dayjs } from "../../context/Locale";
|
import { dayjs } from "../../context/Locale";
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import { emojiDictionary } from "../../assets/emojis";
|
import { emojiDictionary } from "../../assets/emojis";
|
||||||
import { useClient } from "../../controllers/client/ClientController";
|
import { useClient } from "../../controllers/client/ClientController";
|
||||||
|
import { modalController } from "../../controllers/modals/ModalController";
|
||||||
import { generateEmoji } from "../common/Emoji";
|
import { generateEmoji } from "../common/Emoji";
|
||||||
import { MarkdownProps } from "./Markdown";
|
import { MarkdownProps } from "./Markdown";
|
||||||
import Prism from "./prism";
|
import Prism from "./prism";
|
||||||
|
@ -119,7 +119,6 @@ const RE_TIME = /<t:([0-9]+):(\w)>/g;
|
||||||
|
|
||||||
export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
|
export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const { openLink } = useIntermediate();
|
|
||||||
|
|
||||||
if (typeof content === "undefined") return null;
|
if (typeof content === "undefined") return null;
|
||||||
if (!content || content.length === 0) return null;
|
if (!content || content.length === 0) return null;
|
||||||
|
@ -191,43 +190,40 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleLink = useCallback(
|
const handleLink = useCallback((ev: MouseEvent) => {
|
||||||
(ev: MouseEvent) => {
|
if (ev.currentTarget) {
|
||||||
if (ev.currentTarget) {
|
const element = ev.currentTarget as HTMLAnchorElement;
|
||||||
const element = ev.currentTarget as HTMLAnchorElement;
|
|
||||||
|
|
||||||
if (ev.shiftKey) {
|
if (ev.shiftKey) {
|
||||||
switch (element.dataset.type) {
|
switch (element.dataset.type) {
|
||||||
case "mention": {
|
case "mention": {
|
||||||
internalEmit(
|
internalEmit(
|
||||||
"MessageBox",
|
"MessageBox",
|
||||||
"append",
|
"append",
|
||||||
`<@${element.dataset.mentionId}>`,
|
`<@${element.dataset.mentionId}>`,
|
||||||
"mention",
|
"mention",
|
||||||
);
|
);
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case "channel_mention": {
|
case "channel_mention": {
|
||||||
internalEmit(
|
internalEmit(
|
||||||
"MessageBox",
|
"MessageBox",
|
||||||
"append",
|
"append",
|
||||||
`<#${element.dataset.mentionId}>`,
|
`<#${element.dataset.mentionId}>`,
|
||||||
"channel_mention",
|
"channel_mention",
|
||||||
);
|
);
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openLink(element.href)) {
|
|
||||||
ev.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
[openLink],
|
if (modalController.openLink(element.href)) {
|
||||||
);
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
|
|
|
@ -13,8 +13,6 @@ import { IconButton } from "@revoltchat/ui";
|
||||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||||
import { stopPropagation } from "../../../lib/stopPropagation";
|
import { stopPropagation } from "../../../lib/stopPropagation";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import { modalController } from "../../../controllers/modals/ModalController";
|
import { modalController } from "../../../controllers/modals/ModalController";
|
||||||
import ChannelIcon from "../../common/ChannelIcon";
|
import ChannelIcon from "../../common/ChannelIcon";
|
||||||
import Tooltip from "../../common/Tooltip";
|
import Tooltip from "../../common/Tooltip";
|
||||||
|
@ -51,7 +49,6 @@ export const UserButton = observer((props: UserProps) => {
|
||||||
channel,
|
channel,
|
||||||
...divProps
|
...divProps
|
||||||
} = props;
|
} = props;
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -149,7 +146,6 @@ export const ChannelButton = observer((props: ChannelProps) => {
|
||||||
return <UserButton {...{ active, alert, channel, user }} />;
|
return <UserButton {...{ active, alert, channel, user }} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
const alerting = alert && !muted && !active;
|
const alerting = alert && !muted && !active;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -20,8 +20,6 @@ import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import { useApplicationState } from "../../../mobx/State";
|
import { useApplicationState } from "../../../mobx/State";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import placeholderSVG from "../items/placeholder.svg";
|
import placeholderSVG from "../items/placeholder.svg";
|
||||||
|
|
||||||
import { useClient } from "../../../controllers/client/ClientController";
|
import { useClient } from "../../../controllers/client/ClientController";
|
||||||
|
@ -50,7 +48,6 @@ export default observer(() => {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const state = useApplicationState();
|
const state = useApplicationState();
|
||||||
const { channel: channel_id } = useParams<{ channel: string }>();
|
const { channel: channel_id } = useParams<{ channel: string }>();
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
|
|
||||||
const channels = [...client.channels.values()].filter(
|
const channels = [...client.channels.values()].filter(
|
||||||
(x) =>
|
(x) =>
|
||||||
|
|
|
@ -7,8 +7,7 @@ import { Button } from "@revoltchat/ui";
|
||||||
|
|
||||||
import { useApplicationState } from "../../../../mobx/State";
|
import { useApplicationState } from "../../../../mobx/State";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../../context/intermediate/Intermediate";
|
import { modalController } from "../../../../controllers/modals/ModalController";
|
||||||
|
|
||||||
import Tooltip from "../../../common/Tooltip";
|
import Tooltip from "../../../common/Tooltip";
|
||||||
|
|
||||||
const Actions = styled.div`
|
const Actions = styled.div`
|
||||||
|
@ -38,7 +37,6 @@ const Actions = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default function ThemeTools() {
|
export default function ThemeTools() {
|
||||||
const { writeClipboard, openScreen } = useIntermediate();
|
|
||||||
const theme = useApplicationState().settings.theme;
|
const theme = useApplicationState().settings.theme;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -56,7 +54,9 @@ export default function ThemeTools() {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<div
|
<div
|
||||||
className="code"
|
className="code"
|
||||||
onClick={() => writeClipboard(JSON.stringify(theme))}>
|
onClick={() =>
|
||||||
|
modalController.writeText(JSON.stringify(theme))
|
||||||
|
}>
|
||||||
<Tooltip content={<Text id="app.special.copy" />}>
|
<Tooltip content={<Text id="app.special.copy" />}>
|
||||||
{" "}
|
{" "}
|
||||||
{JSON.stringify(theme)}
|
{JSON.stringify(theme)}
|
||||||
|
@ -72,16 +72,8 @@ export default function ThemeTools() {
|
||||||
const text = await navigator.clipboard.readText();
|
const text = await navigator.clipboard.readText();
|
||||||
theme.hydrate(JSON.parse(text));
|
theme.hydrate(JSON.parse(text));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
openScreen({
|
modalController.push({
|
||||||
id: "_input",
|
type: "import_theme",
|
||||||
question: (
|
|
||||||
<Text id="app.settings.pages.appearance.import_theme" />
|
|
||||||
),
|
|
||||||
field: (
|
|
||||||
<Text id="app.settings.pages.appearance.theme_data" />
|
|
||||||
),
|
|
||||||
callback: async (text) =>
|
|
||||||
theme.hydrate(JSON.parse(text)),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
|
|
|
@ -13,7 +13,6 @@ import ModalRenderer from "../controllers/modals/ModalRenderer";
|
||||||
import Locale from "./Locale";
|
import Locale from "./Locale";
|
||||||
import Theme from "./Theme";
|
import Theme from "./Theme";
|
||||||
import { history } from "./history";
|
import { history } from "./history";
|
||||||
import Intermediate from "./intermediate/Intermediate";
|
|
||||||
|
|
||||||
const uiContext = {
|
const uiContext = {
|
||||||
Link,
|
Link,
|
||||||
|
@ -39,10 +38,8 @@ export default function Context({ children }: { children: Children }) {
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<UIProvider value={uiContext}>
|
<UIProvider value={uiContext}>
|
||||||
<Locale>
|
<Locale>
|
||||||
<Intermediate>
|
<>{children}</>
|
||||||
{children}
|
<Binder />
|
||||||
<Binder />
|
|
||||||
</Intermediate>
|
|
||||||
<ModalRenderer />
|
<ModalRenderer />
|
||||||
</Locale>
|
</Locale>
|
||||||
</UIProvider>
|
</UIProvider>
|
||||||
|
|
|
@ -1,219 +0,0 @@
|
||||||
import { Prompt } from "react-router";
|
|
||||||
import { useHistory } from "react-router-dom";
|
|
||||||
import { API, Channel, Message, Server, User } from "revolt.js";
|
|
||||||
|
|
||||||
import { createContext } from "preact";
|
|
||||||
import {
|
|
||||||
StateUpdater,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useState,
|
|
||||||
} from "preact/hooks";
|
|
||||||
|
|
||||||
import type { Action } from "@revoltchat/ui/esm/components/design/atoms/display/Modal";
|
|
||||||
|
|
||||||
import { internalSubscribe } from "../../lib/eventEmitter";
|
|
||||||
import { determineLink } from "../../lib/links";
|
|
||||||
|
|
||||||
import { useApplicationState } from "../../mobx/State";
|
|
||||||
|
|
||||||
import { modalController } from "../../controllers/modals/ModalController";
|
|
||||||
import Modals from "./Modals";
|
|
||||||
|
|
||||||
export type Screen =
|
|
||||||
| { id: "none" }
|
|
||||||
|
|
||||||
// Modals
|
|
||||||
| { id: "signed_out" }
|
|
||||||
| { id: "error"; error: string }
|
|
||||||
| { id: "clipboard"; text: string }
|
|
||||||
| { id: "token_reveal"; token: string; username: string }
|
|
||||||
| { id: "external_link_prompt"; link: string }
|
|
||||||
| { id: "sessions"; confirm: () => void }
|
|
||||||
| {
|
|
||||||
id: "_prompt";
|
|
||||||
question: Children;
|
|
||||||
content?: Children;
|
|
||||||
actions: Action[];
|
|
||||||
}
|
|
||||||
| ({ id: "special_prompt" } & (
|
|
||||||
| { type: "leave_group"; target: Channel }
|
|
||||||
| { type: "close_dm"; target: Channel }
|
|
||||||
| { type: "leave_server"; target: Server }
|
|
||||||
| { type: "delete_server"; target: Server }
|
|
||||||
| { type: "delete_channel"; target: Channel }
|
|
||||||
| {
|
|
||||||
type: "delete_bot";
|
|
||||||
target: string;
|
|
||||||
name: string;
|
|
||||||
cb?: () => void;
|
|
||||||
}
|
|
||||||
| { type: "delete_message"; target: Message }
|
|
||||||
| {
|
|
||||||
type: "create_invite";
|
|
||||||
target: Channel;
|
|
||||||
}
|
|
||||||
| { type: "kick_member"; target: Server; user: User }
|
|
||||||
| { type: "ban_member"; target: Server; user: User }
|
|
||||||
| { type: "unfriend_user"; target: User }
|
|
||||||
| { type: "block_user"; target: User }
|
|
||||||
| {
|
|
||||||
type: "create_channel";
|
|
||||||
target: Server;
|
|
||||||
cb?: (
|
|
||||||
channel: Channel & {
|
|
||||||
channel_type: "TextChannel" | "VoiceChannel";
|
|
||||||
},
|
|
||||||
) => void;
|
|
||||||
}
|
|
||||||
| { type: "create_category"; target: Server }
|
|
||||||
))
|
|
||||||
| ({ id: "special_input" } & (
|
|
||||||
| {
|
|
||||||
type:
|
|
||||||
| "create_group"
|
|
||||||
| "create_server"
|
|
||||||
| "set_custom_status"
|
|
||||||
| "add_friend";
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: "create_role";
|
|
||||||
server: Server;
|
|
||||||
callback: (id: string) => void;
|
|
||||||
}
|
|
||||||
))
|
|
||||||
| {
|
|
||||||
id: "_input";
|
|
||||||
question: Children;
|
|
||||||
field: Children;
|
|
||||||
defaultValue?: string;
|
|
||||||
callback: (value: string) => Promise<void>;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
id: "onboarding";
|
|
||||||
callback: (
|
|
||||||
username: string,
|
|
||||||
loginAfterSuccess?: true,
|
|
||||||
) => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop-overs
|
|
||||||
| { id: "profile"; user_id: string }
|
|
||||||
| {
|
|
||||||
id: "user_picker";
|
|
||||||
omit?: string[];
|
|
||||||
callback: (users: string[]) => Promise<void>;
|
|
||||||
}
|
|
||||||
| { id: "image_viewer"; attachment?: API.File; embed?: API.Image }
|
|
||||||
| { id: "channel_info"; channel: Channel }
|
|
||||||
| { id: "pending_requests"; users: User[] }
|
|
||||||
| { id: "modify_account"; field: "username" | "email" | "password" }
|
|
||||||
| { id: "create_bot"; onCreate: (bot: API.Bot) => void }
|
|
||||||
| {
|
|
||||||
id: "server_identity";
|
|
||||||
server: Server;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const IntermediateContext = createContext({
|
|
||||||
screen: { id: "none" },
|
|
||||||
focusTaken: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const IntermediateActionsContext = createContext<{
|
|
||||||
openLink: (href?: string, trusted?: boolean) => boolean;
|
|
||||||
openScreen: (screen: Screen) => void;
|
|
||||||
writeClipboard: (text: string) => void;
|
|
||||||
}>({
|
|
||||||
openLink: null!,
|
|
||||||
openScreen: null!,
|
|
||||||
writeClipboard: null!,
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
children: Children;
|
|
||||||
}
|
|
||||||
|
|
||||||
export let __thisIsAHack: StateUpdater<Screen>;
|
|
||||||
|
|
||||||
export default function Intermediate(props: Props) {
|
|
||||||
const [screen, openScreen] = useState<Screen>({ id: "none" });
|
|
||||||
__thisIsAHack = openScreen;
|
|
||||||
const history = useHistory();
|
|
||||||
|
|
||||||
const value = {
|
|
||||||
screen,
|
|
||||||
focusTaken: screen.id !== "none",
|
|
||||||
};
|
|
||||||
|
|
||||||
const actions = useMemo(() => {
|
|
||||||
return {
|
|
||||||
openLink: (href?: string, trusted?: boolean) => {
|
|
||||||
return modalController.openLink(href, trusted);
|
|
||||||
},
|
|
||||||
openScreen: (screen: Screen) => openScreen(screen),
|
|
||||||
writeClipboard: (a: string) => modalController.writeText(a),
|
|
||||||
};
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const openProfile = (user_id: string) =>
|
|
||||||
modalController.push({ type: "user_profile", user_id });
|
|
||||||
const navigate = (path: string) => history.push(path);
|
|
||||||
|
|
||||||
const subs = [
|
|
||||||
internalSubscribe(
|
|
||||||
"Intermediate",
|
|
||||||
"openProfile",
|
|
||||||
openProfile as (...args: unknown[]) => void,
|
|
||||||
),
|
|
||||||
internalSubscribe(
|
|
||||||
"Intermediate",
|
|
||||||
"navigate",
|
|
||||||
navigate as (...args: unknown[]) => void,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
return () => subs.map((unsub) => unsub());
|
|
||||||
}, [history]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IntermediateContext.Provider value={value}>
|
|
||||||
<IntermediateActionsContext.Provider value={actions}>
|
|
||||||
{screen.id !== "onboarding" && props.children}
|
|
||||||
<Modals
|
|
||||||
{...value}
|
|
||||||
{...actions}
|
|
||||||
key={
|
|
||||||
screen.id
|
|
||||||
} /** By specifying a key, we reset state whenever switching screen. */
|
|
||||||
/>
|
|
||||||
<Prompt
|
|
||||||
when={[
|
|
||||||
"modify_account",
|
|
||||||
"special_prompt",
|
|
||||||
"special_input",
|
|
||||||
"image_viewer",
|
|
||||||
"profile",
|
|
||||||
"channel_info",
|
|
||||||
"pending_requests",
|
|
||||||
"user_picker",
|
|
||||||
].includes(screen.id)}
|
|
||||||
message={(_, action) => {
|
|
||||||
if (action === "POP") {
|
|
||||||
openScreen({ id: "none" });
|
|
||||||
setTimeout(() => history.push(history.location), 0);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IntermediateActionsContext.Provider>
|
|
||||||
</IntermediateContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useIntermediate = () => useContext(IntermediateActionsContext);
|
|
|
@ -1,25 +0,0 @@
|
||||||
//import { isModalClosing } from "../../components/ui/Modal";
|
|
||||||
import { Screen } from "./Intermediate";
|
|
||||||
import { InputModal } from "./modals/Input";
|
|
||||||
import { PromptModal } from "./modals/Prompt";
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
screen: Screen;
|
|
||||||
openScreen: (screen: Screen) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Modals({ screen, openScreen }: Props) {
|
|
||||||
const onClose = () =>
|
|
||||||
//isModalClosing || screen.id === "onboarding"
|
|
||||||
openScreen({ id: "none" });
|
|
||||||
// : internalEmit("Modal", "close");
|
|
||||||
|
|
||||||
switch (screen.id) {
|
|
||||||
case "_prompt":
|
|
||||||
return <PromptModal onClose={onClose} {...screen} />;
|
|
||||||
case "_input":
|
|
||||||
return <InputModal onClose={onClose} {...screen} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
import { useContext } from "preact/hooks";
|
|
||||||
|
|
||||||
import { IntermediateContext, useIntermediate } from "./Intermediate";
|
|
||||||
import { SpecialInputModal } from "./modals/Input";
|
|
||||||
import { SpecialPromptModal } from "./modals/Prompt";
|
|
||||||
|
|
||||||
export default function Popovers() {
|
|
||||||
const { screen } = useContext(IntermediateContext);
|
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
|
|
||||||
const onClose = () =>
|
|
||||||
//isModalClosing
|
|
||||||
openScreen({ id: "none" });
|
|
||||||
//: internalEmit("Modal", "close");
|
|
||||||
|
|
||||||
switch (screen.id) {
|
|
||||||
case "special_prompt":
|
|
||||||
// @ts-expect-error someone figure this out :)
|
|
||||||
return <SpecialPromptModal onClose={onClose} {...screen} />;
|
|
||||||
case "special_input":
|
|
||||||
// @ts-expect-error someone figure this out :)
|
|
||||||
return <SpecialInputModal onClose={onClose} {...screen} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
import { useHistory } from "react-router";
|
|
||||||
import { Server } from "revolt.js";
|
|
||||||
|
|
||||||
import { Text } from "preact-i18n";
|
|
||||||
import { useContext, useState } from "preact/hooks";
|
|
||||||
|
|
||||||
import { Category, InputBox, Modal } from "@revoltchat/ui";
|
|
||||||
|
|
||||||
import { useClient } from "../../../controllers/client/ClientController";
|
|
||||||
import { I18nError } from "../../Locale";
|
|
||||||
import { takeError } from "../../revoltjs/util";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
onClose: () => void;
|
|
||||||
question: Children;
|
|
||||||
field?: Children;
|
|
||||||
description?: Children;
|
|
||||||
defaultValue?: string;
|
|
||||||
callback: (value: string) => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InputModal({
|
|
||||||
onClose,
|
|
||||||
question,
|
|
||||||
field,
|
|
||||||
description,
|
|
||||||
defaultValue,
|
|
||||||
callback,
|
|
||||||
}: Props) {
|
|
||||||
const [processing, setProcessing] = useState(false);
|
|
||||||
const [value, setValue] = useState(defaultValue ?? "");
|
|
||||||
const [error, setError] = useState<undefined | string>(undefined);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
title={question}
|
|
||||||
description={description}
|
|
||||||
disabled={processing}
|
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
confirmation: true,
|
|
||||||
children: <Text id="app.special.modals.actions.ok" />,
|
|
||||||
onClick: () => {
|
|
||||||
setProcessing(true);
|
|
||||||
callback(value)
|
|
||||||
.then(onClose)
|
|
||||||
.catch((err) => {
|
|
||||||
setError(takeError(err));
|
|
||||||
setProcessing(false);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
children: <Text id="app.special.modals.actions.cancel" />,
|
|
||||||
onClick: onClose,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
onClose={onClose}>
|
|
||||||
{field ? (
|
|
||||||
<Category>
|
|
||||||
<I18nError error={error}>{field}</I18nError>
|
|
||||||
</Category>
|
|
||||||
) : (
|
|
||||||
error && (
|
|
||||||
<Category>
|
|
||||||
<I18nError error={error} />
|
|
||||||
</Category>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
<InputBox
|
|
||||||
value={value}
|
|
||||||
style={{ width: "100%" }}
|
|
||||||
onChange={(e) => setValue(e.currentTarget.value)}
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
type SpecialProps = { onClose: () => void } & (
|
|
||||||
| {
|
|
||||||
type:
|
|
||||||
| "create_group"
|
|
||||||
| "create_server"
|
|
||||||
| "set_custom_status"
|
|
||||||
| "add_friend";
|
|
||||||
}
|
|
||||||
| { type: "create_role"; server: Server; callback: (id: string) => void }
|
|
||||||
);
|
|
||||||
|
|
||||||
export function SpecialInputModal(props: SpecialProps) {
|
|
||||||
const history = useHistory();
|
|
||||||
const client = useClient();
|
|
||||||
|
|
||||||
const { onClose } = props;
|
|
||||||
switch (props.type) {
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
.invite {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
code {
|
|
||||||
padding: 1em;
|
|
||||||
user-select: all;
|
|
||||||
font-size: 1.4em;
|
|
||||||
text-align: center;
|
|
||||||
font-family: var(--monospace-font);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.column {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
|
@ -1,561 +0,0 @@
|
||||||
import { observer } from "mobx-react-lite";
|
|
||||||
import { useHistory } from "react-router-dom";
|
|
||||||
import { Channel, Message as MessageI, Server, User } from "revolt.js";
|
|
||||||
import { ulid } from "ulid";
|
|
||||||
|
|
||||||
import styles from "./Prompt.module.scss";
|
|
||||||
import { Text } from "preact-i18n";
|
|
||||||
import { useEffect, useState } from "preact/hooks";
|
|
||||||
|
|
||||||
import { Category, Modal, InputBox, Radio } from "@revoltchat/ui";
|
|
||||||
import type { Action } from "@revoltchat/ui/esm/components/design/atoms/display/Modal";
|
|
||||||
|
|
||||||
import { TextReact } from "../../../lib/i18n";
|
|
||||||
|
|
||||||
import Message from "../../../components/common/messaging/Message";
|
|
||||||
import UserIcon from "../../../components/common/user/UserIcon";
|
|
||||||
import { useClient } from "../../../controllers/client/ClientController";
|
|
||||||
import { I18nError } from "../../Locale";
|
|
||||||
import { takeError } from "../../revoltjs/util";
|
|
||||||
import { useIntermediate } from "../Intermediate";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
onClose: () => void;
|
|
||||||
question: Children;
|
|
||||||
description?: Children;
|
|
||||||
content?: Children;
|
|
||||||
disabled?: boolean;
|
|
||||||
actions: Action[];
|
|
||||||
error?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PromptModal({
|
|
||||||
onClose,
|
|
||||||
question,
|
|
||||||
description,
|
|
||||||
content,
|
|
||||||
actions,
|
|
||||||
disabled,
|
|
||||||
error,
|
|
||||||
}: Props) {
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
title={question}
|
|
||||||
description={description}
|
|
||||||
actions={actions}
|
|
||||||
onClose={onClose}
|
|
||||||
disabled={disabled}>
|
|
||||||
{error && (
|
|
||||||
<Category>
|
|
||||||
<I18nError error={error} />
|
|
||||||
</Category>
|
|
||||||
)}
|
|
||||||
{content}
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
type SpecialProps = { onClose: () => void } & (
|
|
||||||
| { type: "leave_group"; target: Channel }
|
|
||||||
| { type: "close_dm"; target: Channel }
|
|
||||||
| { type: "delete_channel"; target: Channel }
|
|
||||||
| {
|
|
||||||
type: "create_invite";
|
|
||||||
target: Channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
| { type: "leave_server"; target: Server }
|
|
||||||
| { type: "delete_server"; target: Server }
|
|
||||||
|
|
||||||
| { type: "delete_bot"; target: string; name: string; cb?: () => void }
|
|
||||||
|
|
||||||
| { type: "delete_message"; target: MessageI }
|
|
||||||
|
|
||||||
| { type: "kick_member"; target: Server; user: User }
|
|
||||||
| { type: "ban_member"; target: Server; user: User }
|
|
||||||
|
|
||||||
| { type: "unfriend_user"; target: User }
|
|
||||||
| { type: "block_user"; target: User }
|
|
||||||
|
|
||||||
| {
|
|
||||||
type: "create_channel";
|
|
||||||
target: Server;
|
|
||||||
cb?: (
|
|
||||||
channel: Channel & {
|
|
||||||
channel_type: "TextChannel" | "VoiceChannel";
|
|
||||||
},
|
|
||||||
) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
| { type: "create_category"; target: Server }
|
|
||||||
);
|
|
||||||
|
|
||||||
export const SpecialPromptModal = observer((props: SpecialProps) => {
|
|
||||||
const client = useClient();
|
|
||||||
const history = useHistory();
|
|
||||||
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 "delete_bot":
|
|
||||||
case "unfriend_user":
|
|
||||||
case "block_user": {
|
|
||||||
const EVENTS = {
|
|
||||||
close_dm: ["confirm_close_dm", "close"],
|
|
||||||
delete_server: ["confirm_delete", "delete"],
|
|
||||||
delete_channel: ["confirm_delete", "delete"],
|
|
||||||
delete_bot: ["confirm_delete", "delete"],
|
|
||||||
leave_group: ["confirm_leave", "leave"],
|
|
||||||
leave_server: ["confirm_leave", "leave"],
|
|
||||||
unfriend_user: ["unfriend_user", "remove"],
|
|
||||||
block_user: ["block_user", "block"],
|
|
||||||
};
|
|
||||||
|
|
||||||
const event = EVENTS[props.type];
|
|
||||||
let name;
|
|
||||||
switch (props.type) {
|
|
||||||
case "unfriend_user":
|
|
||||||
case "block_user":
|
|
||||||
name = props.target.username;
|
|
||||||
break;
|
|
||||||
case "close_dm":
|
|
||||||
name = props.target.recipient?.username;
|
|
||||||
break;
|
|
||||||
case "delete_bot":
|
|
||||||
name = props.name;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
name = props.target.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PromptModal
|
|
||||||
onClose={onClose}
|
|
||||||
question={
|
|
||||||
<Text
|
|
||||||
id={`app.special.modals.prompt.${event[0]}`}
|
|
||||||
fields={{ name }}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
description={
|
|
||||||
<TextReact
|
|
||||||
id={`app.special.modals.prompt.${event[0]}_long`}
|
|
||||||
fields={{ name: <b>{name}</b> }}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
confirmation: true,
|
|
||||||
palette: "error",
|
|
||||||
children: (
|
|
||||||
<Text
|
|
||||||
id={`app.special.modals.actions.${event[1]}`}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
onClick: async () => {
|
|
||||||
setProcessing(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
switch (props.type) {
|
|
||||||
case "unfriend_user":
|
|
||||||
await props.target.removeFriend();
|
|
||||||
break;
|
|
||||||
case "block_user":
|
|
||||||
await props.target.blockUser();
|
|
||||||
break;
|
|
||||||
case "leave_group":
|
|
||||||
case "close_dm":
|
|
||||||
case "delete_channel":
|
|
||||||
case "leave_server":
|
|
||||||
case "delete_server":
|
|
||||||
if (props.type != "delete_channel")
|
|
||||||
history.push("/");
|
|
||||||
props.target.delete();
|
|
||||||
break;
|
|
||||||
case "delete_bot":
|
|
||||||
client.bots.delete(props.target);
|
|
||||||
props.cb?.();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
setError(takeError(err));
|
|
||||||
setProcessing(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.cancel" />
|
|
||||||
),
|
|
||||||
onClick: onClose,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
disabled={processing}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case "delete_message": {
|
|
||||||
return (
|
|
||||||
<PromptModal
|
|
||||||
onClose={onClose}
|
|
||||||
question={<Text id={"app.context_menu.delete_message"} />}
|
|
||||||
description={
|
|
||||||
<Text
|
|
||||||
id={`app.special.modals.prompt.confirm_delete_message_long`}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
confirmation: true,
|
|
||||||
palette: "error",
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.delete" />
|
|
||||||
),
|
|
||||||
onClick: async () => {
|
|
||||||
setProcessing(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
props.target.delete();
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
setError(takeError(err));
|
|
||||||
setProcessing(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.cancel" />
|
|
||||||
),
|
|
||||||
onClick: onClose,
|
|
||||||
palette: "plain",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
content={
|
|
||||||
<Message message={props.target} head={true} contrast />
|
|
||||||
}
|
|
||||||
disabled={processing}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case "create_invite": {
|
|
||||||
const [code, setCode] = useState("abcdef");
|
|
||||||
const { writeClipboard } = useIntermediate();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setProcessing(true);
|
|
||||||
|
|
||||||
props.target
|
|
||||||
.createInvite()
|
|
||||||
.then(({ _id }) => setCode(_id))
|
|
||||||
.catch((err) => setError(takeError(err)))
|
|
||||||
.finally(() => setProcessing(false));
|
|
||||||
}, [props.target]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PromptModal
|
|
||||||
onClose={onClose}
|
|
||||||
question={<Text id={`app.context_menu.create_invite`} />}
|
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.ok" />
|
|
||||||
),
|
|
||||||
confirmation: true,
|
|
||||||
onClick: onClose,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
children: <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": {
|
|
||||||
return (
|
|
||||||
<PromptModal
|
|
||||||
onClose={onClose}
|
|
||||||
question={<Text id={`app.context_menu.kick_member`} />}
|
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.kick" />
|
|
||||||
),
|
|
||||||
palette: "error",
|
|
||||||
confirmation: true,
|
|
||||||
onClick: async () => {
|
|
||||||
setProcessing(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
client.members
|
|
||||||
.getKey({
|
|
||||||
server: props.target._id,
|
|
||||||
user: props.user._id,
|
|
||||||
})
|
|
||||||
?.kick();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
setError(takeError(err));
|
|
||||||
setProcessing(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.cancel" />
|
|
||||||
),
|
|
||||||
onClick: onClose,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
content={
|
|
||||||
<div className={styles.column}>
|
|
||||||
<UserIcon target={props.user} size={64} />
|
|
||||||
<Text
|
|
||||||
id="app.special.modals.prompt.confirm_kick"
|
|
||||||
fields={{ name: props.user?.username }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
disabled={processing}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case "ban_member": {
|
|
||||||
const [reason, setReason] = useState<string | undefined>(undefined);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PromptModal
|
|
||||||
onClose={onClose}
|
|
||||||
question={<Text id={`app.context_menu.ban_member`} />}
|
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.ban" />
|
|
||||||
),
|
|
||||||
palette: "error",
|
|
||||||
|
|
||||||
confirmation: true,
|
|
||||||
onClick: async () => {
|
|
||||||
setProcessing(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await props.target.banUser(props.user._id, {
|
|
||||||
reason,
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
setError(takeError(err));
|
|
||||||
setProcessing(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.cancel" />
|
|
||||||
),
|
|
||||||
onClick: onClose,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
content={
|
|
||||||
<div className={styles.column}>
|
|
||||||
<UserIcon target={props.user} size={64} />
|
|
||||||
<Text
|
|
||||||
id="app.special.modals.prompt.confirm_ban"
|
|
||||||
fields={{ name: props.user?.username }}
|
|
||||||
/>
|
|
||||||
<Category>
|
|
||||||
<Text id="app.special.modals.prompt.confirm_ban_reason" />
|
|
||||||
</Category>
|
|
||||||
<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,
|
|
||||||
palette: "secondary",
|
|
||||||
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.create" />
|
|
||||||
),
|
|
||||||
onClick: async () => {
|
|
||||||
setProcessing(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const channel =
|
|
||||||
await props.target.createChannel({
|
|
||||||
type,
|
|
||||||
name,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (props.cb) {
|
|
||||||
props.cb(channel as any);
|
|
||||||
} else {
|
|
||||||
history.push(
|
|
||||||
`/server/${props.target._id}/channel/${channel._id}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
setError(takeError(err));
|
|
||||||
setProcessing(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.cancel" />
|
|
||||||
),
|
|
||||||
onClick: onClose,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
content={
|
|
||||||
<>
|
|
||||||
<Category>
|
|
||||||
<Text id="app.main.servers.channel_type" />
|
|
||||||
</Category>
|
|
||||||
<Radio
|
|
||||||
title={
|
|
||||||
<Text id="app.main.servers.text_channel" />
|
|
||||||
}
|
|
||||||
value={type === "Text"}
|
|
||||||
onSelect={() => setType("Text")}
|
|
||||||
/>
|
|
||||||
<Radio
|
|
||||||
title={
|
|
||||||
<Text id="app.main.servers.voice_channel" />
|
|
||||||
}
|
|
||||||
value={type === "Voice"}
|
|
||||||
onSelect={() => setType("Voice")}
|
|
||||||
/>
|
|
||||||
<Category>
|
|
||||||
<Text id="app.main.servers.channel_name" />
|
|
||||||
</Category>
|
|
||||||
<InputBox
|
|
||||||
value={name}
|
|
||||||
onChange={(e) => setName(e.currentTarget.value)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
disabled={processing}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case "create_category": {
|
|
||||||
const [name, setName] = useState("");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PromptModal
|
|
||||||
onClose={onClose}
|
|
||||||
question={<Text id="app.context_menu.create_category" />}
|
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
confirmation: true,
|
|
||||||
palette: "secondary",
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.create" />
|
|
||||||
),
|
|
||||||
onClick: async () => {
|
|
||||||
setProcessing(true);
|
|
||||||
try {
|
|
||||||
props.target.edit({
|
|
||||||
categories: [
|
|
||||||
...(props.target.categories ?? []),
|
|
||||||
{
|
|
||||||
id: ulid(),
|
|
||||||
title: name,
|
|
||||||
channels: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
setProcessing(false);
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
setError(takeError(err));
|
|
||||||
setProcessing(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
children: (
|
|
||||||
<Text id="app.special.modals.actions.cancel" />
|
|
||||||
),
|
|
||||||
onClick: onClose,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
content={
|
|
||||||
<>
|
|
||||||
<Category>
|
|
||||||
<Text id="app.main.servers.category_name" />
|
|
||||||
</Category>
|
|
||||||
<InputBox
|
|
||||||
value={name}
|
|
||||||
onChange={(e) => setName(e.currentTarget.value)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
disabled={processing}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
.list {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 360px;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
|
@ -13,7 +13,6 @@ import { determineFileSize } from "../../lib/fileSize";
|
||||||
|
|
||||||
import { useClient } from "../../controllers/client/ClientController";
|
import { useClient } from "../../controllers/client/ClientController";
|
||||||
import { modalController } from "../../controllers/modals/ModalController";
|
import { modalController } from "../../controllers/modals/ModalController";
|
||||||
import { useIntermediate } from "../intermediate/Intermediate";
|
|
||||||
import { takeError } from "./util";
|
import { takeError } from "./util";
|
||||||
|
|
||||||
type BehaviourType =
|
type BehaviourType =
|
||||||
|
@ -112,7 +111,6 @@ export function grabFiles(
|
||||||
|
|
||||||
export function FileUploader(props: Props) {
|
export function FileUploader(props: Props) {
|
||||||
const { fileType, maxFileSize, remove } = props;
|
const { fileType, maxFileSize, remove } = props;
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
|
|
||||||
const [uploading, setUploading] = useState(false);
|
const [uploading, setUploading] = useState(false);
|
||||||
|
@ -243,7 +241,7 @@ export function FileUploader(props: Props) {
|
||||||
document.removeEventListener("dragover", dragover);
|
document.removeEventListener("dragover", dragover);
|
||||||
document.removeEventListener("drop", drop);
|
document.removeEventListener("drop", drop);
|
||||||
};
|
};
|
||||||
}, [openScreen, props, props.append]);
|
}, [props, props.append]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.style === "icon" || props.style === "banner") {
|
if (props.style === "icon" || props.style === "banner") {
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { API, Client } from "revolt.js";
|
||||||
|
|
||||||
import { state } from "../../mobx/State";
|
import { state } from "../../mobx/State";
|
||||||
|
|
||||||
import { __thisIsAHack } from "../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import { modalController } from "../modals/ModalController";
|
import { modalController } from "../modals/ModalController";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { Prompt, useHistory } from "react-router-dom";
|
||||||
|
|
||||||
import { useEffect } from "preact/hooks";
|
import { useEffect } from "preact/hooks";
|
||||||
|
|
||||||
import { modalController } from "./ModalController";
|
import { modalController } from "./ModalController";
|
||||||
|
|
||||||
export default observer(() => {
|
export default observer(() => {
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function keyUp(event: KeyboardEvent) {
|
function keyUp(event: KeyboardEvent) {
|
||||||
if (event.key === "Escape") {
|
if (event.key === "Escape") {
|
||||||
|
@ -18,5 +21,22 @@ export default observer(() => {
|
||||||
return () => document.removeEventListener("keyup", keyUp);
|
return () => document.removeEventListener("keyup", keyUp);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return modalController.rendered;
|
return (
|
||||||
|
<>
|
||||||
|
{modalController.rendered}
|
||||||
|
<Prompt
|
||||||
|
when={modalController.isVisible}
|
||||||
|
message={(_, action) => {
|
||||||
|
if (action === "POP") {
|
||||||
|
modalController.pop("close");
|
||||||
|
setTimeout(() => history.push(history.location), 0);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
32
src/controllers/modals/components/ImportTheme.tsx
Normal file
32
src/controllers/modals/components/ImportTheme.tsx
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { Text } from "preact-i18n";
|
||||||
|
|
||||||
|
import { ModalForm } from "@revoltchat/ui";
|
||||||
|
|
||||||
|
import { state } from "../../../mobx/State";
|
||||||
|
|
||||||
|
import { ModalProps } from "../types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import theme modal
|
||||||
|
*/
|
||||||
|
export default function ImportTheme({ ...props }: ModalProps<"import_theme">) {
|
||||||
|
return (
|
||||||
|
<ModalForm
|
||||||
|
{...props}
|
||||||
|
title={<Text id="app.settings.pages.appearance.import_theme" />}
|
||||||
|
schema={{
|
||||||
|
data: "text",
|
||||||
|
}}
|
||||||
|
data={{
|
||||||
|
data: {
|
||||||
|
field: (
|
||||||
|
<Text id="app.settings.pages.appearance.theme_data" />
|
||||||
|
) as React.ReactChild,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
callback={async ({ data }) =>
|
||||||
|
state.settings.theme.hydrate(JSON.parse(data))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
|
@ -176,6 +176,9 @@ export type Modal = {
|
||||||
type: "create_category";
|
type: "create_category";
|
||||||
target: Server;
|
target: Server;
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: "import_theme";
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export type ModalProps<T extends Modal["type"]> = Modal & { type: T } & {
|
export type ModalProps<T extends Modal["type"]> = Modal & { type: T } & {
|
||||||
|
|
|
@ -26,7 +26,6 @@ import { useApplicationState } from "../mobx/State";
|
||||||
import { QueuedMessage } from "../mobx/stores/MessageQueue";
|
import { QueuedMessage } from "../mobx/stores/MessageQueue";
|
||||||
import { NotificationState } from "../mobx/stores/NotificationOptions";
|
import { NotificationState } from "../mobx/stores/NotificationOptions";
|
||||||
|
|
||||||
import { Screen, useIntermediate } from "../context/intermediate/Intermediate";
|
|
||||||
import { takeError } from "../context/revoltjs/util";
|
import { takeError } from "../context/revoltjs/util";
|
||||||
import CMNotifications from "./contextmenu/CMNotifications";
|
import CMNotifications from "./contextmenu/CMNotifications";
|
||||||
|
|
||||||
|
@ -116,7 +115,6 @@ type Action =
|
||||||
// ! FIXME: I dare someone to re-write this
|
// ! FIXME: I dare someone to re-write this
|
||||||
// Tip: This should just be split into separate context menus per logical area.
|
// Tip: This should just be split into separate context menus per logical area.
|
||||||
export default function ContextMenus() {
|
export default function ContextMenus() {
|
||||||
const { openScreen, writeClipboard } = useIntermediate();
|
|
||||||
const session = useSession()!;
|
const session = useSession()!;
|
||||||
const client = session.client!;
|
const client = session.client!;
|
||||||
const userId = client.user!._id;
|
const userId = client.user!._id;
|
||||||
|
@ -130,7 +128,7 @@ export default function ContextMenus() {
|
||||||
(async () => {
|
(async () => {
|
||||||
switch (data.action) {
|
switch (data.action) {
|
||||||
case "copy_id":
|
case "copy_id":
|
||||||
writeClipboard(data.id);
|
modalController.writeText(data.id);
|
||||||
break;
|
break;
|
||||||
case "copy_message_link":
|
case "copy_message_link":
|
||||||
{
|
{
|
||||||
|
@ -139,11 +137,13 @@ export default function ContextMenus() {
|
||||||
if (channel?.channel_type === "TextChannel")
|
if (channel?.channel_type === "TextChannel")
|
||||||
pathname = `/server/${channel.server_id}${pathname}`;
|
pathname = `/server/${channel.server_id}${pathname}`;
|
||||||
|
|
||||||
writeClipboard(window.origin + pathname);
|
modalController.writeText(window.origin + pathname);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "copy_selection":
|
case "copy_selection":
|
||||||
writeClipboard(document.getSelection()?.toString() ?? "");
|
modalController.writeText(
|
||||||
|
document.getSelection()?.toString() ?? "",
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "mark_as_read":
|
case "mark_as_read":
|
||||||
{
|
{
|
||||||
|
@ -227,7 +227,7 @@ export default function ContextMenus() {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "copy_text":
|
case "copy_text":
|
||||||
writeClipboard(data.content);
|
modalController.writeText(data.content);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "reply_message":
|
case "reply_message":
|
||||||
|
@ -286,7 +286,7 @@ export default function ContextMenus() {
|
||||||
case "copy_file_link":
|
case "copy_file_link":
|
||||||
{
|
{
|
||||||
const { filename } = data.attachment;
|
const { filename } = data.attachment;
|
||||||
writeClipboard(
|
modalController.writeText(
|
||||||
// ! FIXME: do from r.js
|
// ! FIXME: do from r.js
|
||||||
`${client.generateFileURL(
|
`${client.generateFileURL(
|
||||||
data.attachment,
|
data.attachment,
|
||||||
|
@ -303,7 +303,7 @@ export default function ContextMenus() {
|
||||||
|
|
||||||
case "copy_link":
|
case "copy_link":
|
||||||
{
|
{
|
||||||
writeClipboard(data.link);
|
modalController.writeText(data.link);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1022,7 +1022,7 @@ export default function ContextMenus() {
|
||||||
<div
|
<div
|
||||||
className="username"
|
className="username"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
writeClipboard(
|
modalController.writeText(
|
||||||
client.user!.username,
|
client.user!.username,
|
||||||
)
|
)
|
||||||
}>
|
}>
|
||||||
|
|
|
@ -7,8 +7,6 @@ import { useEffect, useState } from "preact/hooks";
|
||||||
import ContextMenus from "../lib/ContextMenus";
|
import ContextMenus from "../lib/ContextMenus";
|
||||||
import { isTouchscreenDevice } from "../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import Popovers from "../context/intermediate/Popovers";
|
|
||||||
|
|
||||||
import { Titlebar } from "../components/native/Titlebar";
|
import { Titlebar } from "../components/native/Titlebar";
|
||||||
import BottomNavigation from "../components/navigation/BottomNavigation";
|
import BottomNavigation from "../components/navigation/BottomNavigation";
|
||||||
import LeftSidebar from "../components/navigation/LeftSidebar";
|
import LeftSidebar from "../components/navigation/LeftSidebar";
|
||||||
|
@ -225,7 +223,6 @@ export default function App() {
|
||||||
</Switch>
|
</Switch>
|
||||||
</Routes>
|
</Routes>
|
||||||
<ContextMenus />
|
<ContextMenus />
|
||||||
<Popovers />
|
|
||||||
</OverlappingPanels>
|
</OverlappingPanels>
|
||||||
</AppContainer>
|
</AppContainer>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -21,8 +21,6 @@ import { voiceState, VoiceStatus } from "../../../lib/vortex/VoiceState";
|
||||||
import { useApplicationState } from "../../../mobx/State";
|
import { useApplicationState } from "../../../mobx/State";
|
||||||
import { SIDEBAR_MEMBERS } from "../../../mobx/stores/Layout";
|
import { SIDEBAR_MEMBERS } from "../../../mobx/stores/Layout";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import UpdateIndicator from "../../../components/common/UpdateIndicator";
|
import UpdateIndicator from "../../../components/common/UpdateIndicator";
|
||||||
import { modalController } from "../../../controllers/modals/ModalController";
|
import { modalController } from "../../../controllers/modals/ModalController";
|
||||||
import { ChannelHeaderProps } from "../ChannelHeader";
|
import { ChannelHeaderProps } from "../ChannelHeader";
|
||||||
|
@ -74,7 +72,6 @@ const SearchBar = styled.div`
|
||||||
|
|
||||||
export default function HeaderActions({ channel }: ChannelHeaderProps) {
|
export default function HeaderActions({ channel }: ChannelHeaderProps) {
|
||||||
const layout = useApplicationState().layout;
|
const layout = useApplicationState().layout;
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
function slideOpen() {
|
function slideOpen() {
|
||||||
|
|
|
@ -23,10 +23,9 @@ import { internalEmit, internalSubscribe } from "../../../lib/eventEmitter";
|
||||||
import { getRenderer } from "../../../lib/renderer/Singleton";
|
import { getRenderer } from "../../../lib/renderer/Singleton";
|
||||||
import { ScrollState } from "../../../lib/renderer/types";
|
import { ScrollState } from "../../../lib/renderer/types";
|
||||||
|
|
||||||
import { IntermediateContext } from "../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import { useSession } from "../../../controllers/client/ClientController";
|
import { useSession } from "../../../controllers/client/ClientController";
|
||||||
import RequiresOnline from "../../../controllers/client/jsx/RequiresOnline";
|
import RequiresOnline from "../../../controllers/client/jsx/RequiresOnline";
|
||||||
|
import { modalController } from "../../../controllers/modals/ModalController";
|
||||||
import ConversationStart from "./ConversationStart";
|
import ConversationStart from "./ConversationStart";
|
||||||
import MessageRenderer from "./MessageRenderer";
|
import MessageRenderer from "./MessageRenderer";
|
||||||
|
|
||||||
|
@ -63,7 +62,6 @@ export const MESSAGE_AREA_PADDING = 82;
|
||||||
export const MessageArea = observer(({ last_id, channel }: Props) => {
|
export const MessageArea = observer(({ last_id, channel }: Props) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const session = useSession()!;
|
const session = useSession()!;
|
||||||
const { focusTaken } = useContext(IntermediateContext);
|
|
||||||
|
|
||||||
// ? Required data for message links.
|
// ? Required data for message links.
|
||||||
const { message } = useParams<{ message: string }>();
|
const { message } = useParams<{ message: string }>();
|
||||||
|
@ -303,7 +301,7 @@ export const MessageArea = observer(({ last_id, channel }: Props) => {
|
||||||
// ? Scroll to bottom when pressing 'Escape'.
|
// ? Scroll to bottom when pressing 'Escape'.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function keyUp(e: KeyboardEvent) {
|
function keyUp(e: KeyboardEvent) {
|
||||||
if (e.key === "Escape" && !focusTaken) {
|
if (e.key === "Escape" && !modalController.isVisible) {
|
||||||
renderer.jumpToBottom(true);
|
renderer.jumpToBottom(true);
|
||||||
internalEmit("TextArea", "focus", "message");
|
internalEmit("TextArea", "focus", "message");
|
||||||
}
|
}
|
||||||
|
@ -311,7 +309,7 @@ export const MessageArea = observer(({ last_id, channel }: Props) => {
|
||||||
|
|
||||||
document.body.addEventListener("keyup", keyUp);
|
document.body.addEventListener("keyup", keyUp);
|
||||||
return () => document.body.removeEventListener("keyup", keyUp);
|
return () => document.body.removeEventListener("keyup", keyUp);
|
||||||
}, [renderer, ref, focusTaken]);
|
}, [renderer, ref]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MessageAreaWidthContext.Provider
|
<MessageAreaWidthContext.Provider
|
||||||
|
|
|
@ -6,11 +6,6 @@ import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
|
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
|
||||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import {
|
|
||||||
IntermediateContext,
|
|
||||||
useIntermediate,
|
|
||||||
} from "../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import AutoComplete, {
|
import AutoComplete, {
|
||||||
useAutoComplete,
|
useAutoComplete,
|
||||||
} from "../../../components/common/AutoComplete";
|
} from "../../../components/common/AutoComplete";
|
||||||
|
@ -50,7 +45,6 @@ interface Props {
|
||||||
|
|
||||||
export default function MessageEditor({ message, finish }: Props) {
|
export default function MessageEditor({ message, finish }: Props) {
|
||||||
const [content, setContent] = useState(message.content ?? "");
|
const [content, setContent] = useState(message.content ?? "");
|
||||||
const { focusTaken } = useContext(IntermediateContext);
|
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
finish();
|
finish();
|
||||||
|
@ -70,14 +64,14 @@ export default function MessageEditor({ message, finish }: Props) {
|
||||||
// ? Stop editing when pressing ESC.
|
// ? Stop editing when pressing ESC.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function keyUp(e: KeyboardEvent) {
|
function keyUp(e: KeyboardEvent) {
|
||||||
if (e.key === "Escape" && !focusTaken) {
|
if (e.key === "Escape" && !modalController.isVisible) {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.addEventListener("keyup", keyUp);
|
document.body.addEventListener("keyup", keyUp);
|
||||||
return () => document.body.removeEventListener("keyup", keyUp);
|
return () => document.body.removeEventListener("keyup", keyUp);
|
||||||
}, [focusTaken, finish]);
|
}, [finish]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
onChange,
|
onChange,
|
||||||
|
|
|
@ -16,8 +16,6 @@ import { Button } from "@revoltchat/ui";
|
||||||
|
|
||||||
import { voiceState, VoiceStatus } from "../../../lib/vortex/VoiceState";
|
import { voiceState, VoiceStatus } from "../../../lib/vortex/VoiceState";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import Tooltip from "../../../components/common/Tooltip";
|
import Tooltip from "../../../components/common/Tooltip";
|
||||||
import UserIcon from "../../../components/common/user/UserIcon";
|
import UserIcon from "../../../components/common/user/UserIcon";
|
||||||
import { useClient } from "../../../controllers/client/ClientController";
|
import { useClient } from "../../../controllers/client/ClientController";
|
||||||
|
@ -85,8 +83,6 @@ const VoiceBase = styled.div`
|
||||||
export default observer(({ id }: Props) => {
|
export default observer(({ id }: Props) => {
|
||||||
if (voiceState.roomId !== id) return null;
|
if (voiceState.roomId !== id) return null;
|
||||||
|
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const self = client.users.get(client.user!._id);
|
const self = client.users.get(client.user!._id);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@ import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||||
import { useApplicationState } from "../../mobx/State";
|
import { useApplicationState } from "../../mobx/State";
|
||||||
|
|
||||||
import { Overrides } from "../../context/Theme";
|
import { Overrides } from "../../context/Theme";
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
|
||||||
|
import { modalController } from "../../controllers/modals/ModalController";
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
@ -85,7 +86,6 @@ const REMOTE = "https://rvlt.gg";
|
||||||
|
|
||||||
export default function Discover() {
|
export default function Discover() {
|
||||||
const state = useApplicationState();
|
const state = useApplicationState();
|
||||||
const { openLink } = useIntermediate();
|
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { pathname, search } = useLocation();
|
const { pathname, search } = useLocation();
|
||||||
|
@ -137,7 +137,7 @@ export default function Discover() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "navigate": {
|
case "navigate": {
|
||||||
openLink(data.url);
|
modalController.openLink(data.url);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "applyTheme": {
|
case "applyTheme": {
|
||||||
|
|
|
@ -14,8 +14,6 @@ import { IconButton } from "@revoltchat/ui";
|
||||||
import { stopPropagation } from "../../lib/stopPropagation";
|
import { stopPropagation } from "../../lib/stopPropagation";
|
||||||
import { voiceState } from "../../lib/vortex/VoiceState";
|
import { voiceState } from "../../lib/vortex/VoiceState";
|
||||||
|
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import UserIcon from "../../components/common/user/UserIcon";
|
import UserIcon from "../../components/common/user/UserIcon";
|
||||||
import UserStatus from "../../components/common/user/UserStatus";
|
import UserStatus from "../../components/common/user/UserStatus";
|
||||||
import { modalController } from "../../controllers/modals/ModalController";
|
import { modalController } from "../../controllers/modals/ModalController";
|
||||||
|
@ -26,7 +24,6 @@ interface Props {
|
||||||
|
|
||||||
export const Friend = observer(({ user }: Props) => {
|
export const Friend = observer(({ user }: Props) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
|
|
||||||
const actions: Children[] = [];
|
const actions: Children[] = [];
|
||||||
let subtext: Children = null;
|
let subtext: Children = null;
|
||||||
|
|
|
@ -12,8 +12,6 @@ import { IconButton } from "@revoltchat/ui";
|
||||||
import { TextReact } from "../../lib/i18n";
|
import { TextReact } from "../../lib/i18n";
|
||||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import CollapsibleSection from "../../components/common/CollapsibleSection";
|
import CollapsibleSection from "../../components/common/CollapsibleSection";
|
||||||
import Tooltip from "../../components/common/Tooltip";
|
import Tooltip from "../../components/common/Tooltip";
|
||||||
import UserIcon from "../../components/common/user/UserIcon";
|
import UserIcon from "../../components/common/user/UserIcon";
|
||||||
|
@ -23,8 +21,6 @@ import { modalController } from "../../controllers/modals/ModalController";
|
||||||
import { Friend } from "./Friend";
|
import { Friend } from "./Friend";
|
||||||
|
|
||||||
export default observer(() => {
|
export default observer(() => {
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const users = [...client.users.values()];
|
const users = [...client.users.values()];
|
||||||
users.sort((a, b) => a.username.localeCompare(b.username));
|
users.sort((a, b) => a.username.localeCompare(b.username));
|
||||||
|
|
|
@ -23,8 +23,6 @@ import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import { useApplicationState } from "../../mobx/State";
|
import { useApplicationState } from "../../mobx/State";
|
||||||
|
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import wideSVG from "/assets/wide.svg";
|
import wideSVG from "/assets/wide.svg";
|
||||||
|
|
||||||
import { PageHeader } from "../../components/ui/Header";
|
import { PageHeader } from "../../components/ui/Header";
|
||||||
|
@ -45,7 +43,6 @@ const Overlay = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default observer(() => {
|
export default observer(() => {
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const state = useApplicationState();
|
const state = useApplicationState();
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@ import { Text } from "preact-i18n";
|
||||||
|
|
||||||
import { LineDivider } from "@revoltchat/ui";
|
import { LineDivider } from "@revoltchat/ui";
|
||||||
|
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import ButtonItem from "../../components/navigation/items/ButtonItem";
|
import ButtonItem from "../../components/navigation/items/ButtonItem";
|
||||||
import { useClient } from "../../controllers/client/ClientController";
|
import { useClient } from "../../controllers/client/ClientController";
|
||||||
import RequiresOnline from "../../controllers/client/jsx/RequiresOnline";
|
import RequiresOnline from "../../controllers/client/jsx/RequiresOnline";
|
||||||
|
@ -30,7 +28,6 @@ import { Overview } from "./server/Overview";
|
||||||
import { Roles } from "./server/Roles";
|
import { Roles } from "./server/Roles";
|
||||||
|
|
||||||
export default observer(() => {
|
export default observer(() => {
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
const { server: sid } = useParams<{ server: string }>();
|
const { server: sid } = useParams<{ server: string }>();
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const server = client.servers.get(sid);
|
const server = client.servers.get(sid);
|
||||||
|
|
|
@ -33,8 +33,6 @@ import { LineDivider } from "@revoltchat/ui";
|
||||||
|
|
||||||
import { useApplicationState } from "../../mobx/State";
|
import { useApplicationState } from "../../mobx/State";
|
||||||
|
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import UserIcon from "../../components/common/user/UserIcon";
|
import UserIcon from "../../components/common/user/UserIcon";
|
||||||
import { Username } from "../../components/common/user/UserShort";
|
import { Username } from "../../components/common/user/UserShort";
|
||||||
import UserStatus from "../../components/common/user/UserStatus";
|
import UserStatus from "../../components/common/user/UserStatus";
|
||||||
|
@ -121,7 +119,6 @@ const AccountHeader = styled.div`
|
||||||
export default observer(() => {
|
export default observer(() => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
const experiments = useApplicationState().experiments;
|
const experiments = useApplicationState().experiments;
|
||||||
|
|
||||||
function switchPage(to?: string) {
|
function switchPage(to?: string) {
|
||||||
|
|
|
@ -23,7 +23,6 @@ import { internalEmit } from "../../../lib/eventEmitter";
|
||||||
import { useTranslation } from "../../../lib/i18n";
|
import { useTranslation } from "../../../lib/i18n";
|
||||||
import { stopPropagation } from "../../../lib/stopPropagation";
|
import { stopPropagation } from "../../../lib/stopPropagation";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
|
||||||
import { FileUploader } from "../../../context/revoltjs/FileUploads";
|
import { FileUploader } from "../../../context/revoltjs/FileUploads";
|
||||||
|
|
||||||
import AutoComplete, {
|
import AutoComplete, {
|
||||||
|
@ -88,7 +87,6 @@ function BotCard({ bot, onDelete, onUpdate }: Props) {
|
||||||
);
|
);
|
||||||
const [interactionsRef, setInteractionsRef] =
|
const [interactionsRef, setInteractionsRef] =
|
||||||
useState<HTMLInputElement | null>(null);
|
useState<HTMLInputElement | null>(null);
|
||||||
const { writeClipboard, openScreen } = useIntermediate();
|
|
||||||
|
|
||||||
const [profile, setProfile] = useState<undefined | API.UserProfile>(
|
const [profile, setProfile] = useState<undefined | API.UserProfile>(
|
||||||
undefined,
|
undefined,
|
||||||
|
@ -267,7 +265,9 @@ function BotCard({ bot, onDelete, onUpdate }: Props) {
|
||||||
}>
|
}>
|
||||||
<a
|
<a
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
writeClipboard(user!._id)
|
modalController.writeText(
|
||||||
|
user!._id,
|
||||||
|
)
|
||||||
}>
|
}>
|
||||||
{user!._id}
|
{user!._id}
|
||||||
</a>
|
</a>
|
||||||
|
@ -335,7 +335,7 @@ function BotCard({ bot, onDelete, onUpdate }: Props) {
|
||||||
<CategoryButton
|
<CategoryButton
|
||||||
account
|
account
|
||||||
icon={<Key size={24} />}
|
icon={<Key size={24} />}
|
||||||
onClick={() => writeClipboard(bot.token)}
|
onClick={() => modalController.writeText(bot.token)}
|
||||||
description={
|
description={
|
||||||
<>
|
<>
|
||||||
{"••••• "}
|
{"••••• "}
|
||||||
|
@ -475,7 +475,7 @@ function BotCard({ bot, onDelete, onUpdate }: Props) {
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
writeClipboard(
|
modalController.writeText(
|
||||||
`${window.origin}/bot/${bot._id}`,
|
`${window.origin}/bot/${bot._id}`,
|
||||||
)
|
)
|
||||||
}>
|
}>
|
||||||
|
|
|
@ -14,8 +14,6 @@ import { useAutosave } from "../../../lib/debounce";
|
||||||
import { Draggable, Droppable } from "../../../lib/dnd";
|
import { Draggable, Droppable } from "../../../lib/dnd";
|
||||||
import { noop } from "../../../lib/js";
|
import { noop } from "../../../lib/js";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
|
||||||
|
|
||||||
import ChannelIcon from "../../../components/common/ChannelIcon";
|
import ChannelIcon from "../../../components/common/ChannelIcon";
|
||||||
import { modalController } from "../../../controllers/modals/ModalController";
|
import { modalController } from "../../../controllers/modals/ModalController";
|
||||||
|
|
||||||
|
@ -334,12 +332,9 @@ function ListElement({
|
||||||
index: number;
|
index: number;
|
||||||
setTitle?: (title: string) => void;
|
setTitle?: (title: string) => void;
|
||||||
deleteSelf?: () => void;
|
deleteSelf?: () => void;
|
||||||
addChannel: (
|
addChannel: (channel: Channel) => void;
|
||||||
channel: Channel & { channel_type: "TextChannel" | "VoiceChannel" },
|
|
||||||
) => void;
|
|
||||||
draggable?: boolean;
|
draggable?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { openScreen } = useIntermediate();
|
|
||||||
const [editing, setEditing] = useState<string>();
|
const [editing, setEditing] = useState<string>();
|
||||||
const startEditing = () => setTitle && setEditing(category.title);
|
const startEditing = () => setTitle && setEditing(category.title);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue