diff --git a/external/lang b/external/lang index 50838167..d4bc47b7 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 50838167d7d253de9d08715e6a6070c3ddc9fcc2 +Subproject commit d4bc47b729c7e69ce97216469692b39f4cd1640e diff --git a/src/components/common/ServerHeader.tsx b/src/components/common/ServerHeader.tsx index 0c5b3f0e..69ff5a7b 100644 --- a/src/components/common/ServerHeader.tsx +++ b/src/components/common/ServerHeader.tsx @@ -9,6 +9,7 @@ import { Text } from "preact-i18n"; import { IconButton } from "@revoltchat/ui"; +import { modalController } from "../../controllers/modals/ModalController"; import Tooltip from "./Tooltip"; interface Props { @@ -60,6 +61,9 @@ const ServerBanner = styled.div>` overflow: hidden; text-overflow: ellipsis; flex-grow: 1; + + cursor: pointer; + color: var(--foreground); } } `; @@ -121,7 +125,13 @@ export default observer(({ server }: Props) => { ) : undefined} -
{server.name}
+ + modalController.push({ type: "server_info", server }) + }> + {server.name} + {server.havePermission("ManageServer") && ( diff --git a/src/components/markdown/Markdown.module.scss b/src/components/markdown/Markdown.module.scss index c107fcfa..cff232a1 100644 --- a/src/components/markdown/Markdown.module.scss +++ b/src/components/markdown/Markdown.module.scss @@ -1,4 +1,6 @@ .markdown { + user-select: text; + :global(.emoji) { object-fit: contain; diff --git a/src/context/intermediate/Popovers.tsx b/src/context/intermediate/Popovers.tsx index f5d8f347..0dc85eed 100644 --- a/src/context/intermediate/Popovers.tsx +++ b/src/context/intermediate/Popovers.tsx @@ -3,7 +3,6 @@ import { useContext } from "preact/hooks"; import { IntermediateContext, useIntermediate } from "./Intermediate"; import { SpecialInputModal } from "./modals/Input"; import { SpecialPromptModal } from "./modals/Prompt"; -import { ChannelInfo } from "./popovers/ChannelInfo"; import { CreateBotModal } from "./popovers/CreateBot"; import { ImageViewer } from "./popovers/ImageViewer"; import { UserPicker } from "./popovers/UserPicker"; @@ -27,9 +26,6 @@ export default function Popovers() { return ; case "image_viewer": return ; - case "channel_info": - // @ts-expect-error someone figure this out :) - return ; case "create_bot": // @ts-expect-error someone figure this out :) return ; diff --git a/src/controllers/modals/ModalController.tsx b/src/controllers/modals/ModalController.tsx index 8102cab8..3f78b7bc 100644 --- a/src/controllers/modals/ModalController.tsx +++ b/src/controllers/modals/ModalController.tsx @@ -18,6 +18,7 @@ import { __thisIsAHack } from "../../context/intermediate/Intermediate"; // import { determineLink } from "../../lib/links"; import Changelog from "./components/Changelog"; +import ChannelInfo from "./components/ChannelInfo"; import Clipboard from "./components/Clipboard"; import Error from "./components/Error"; import LinkWarning from "./components/LinkWarning"; @@ -28,6 +29,7 @@ import ModifyAccount from "./components/ModifyAccount"; import OutOfDate from "./components/OutOfDate"; import PendingFriendRequests from "./components/PendingFriendRequests"; import ServerIdentity from "./components/ServerIdentity"; +import ServerInfo from "./components/ServerInfo"; import ShowToken from "./components/ShowToken"; import SignOutSessions from "./components/SignOutSessions"; import SignedOut from "./components/SignedOut"; @@ -54,6 +56,8 @@ class ModalController { isVisible: computed, }); + this.close = this.close.bind(this); + // Inject globally injectController("modal", this); } @@ -82,6 +86,13 @@ class ModalController { ); } + /** + * Close the top modal + */ + close() { + this.pop("close"); + } + /** * Remove the keyed modal from the stack */ @@ -208,6 +219,7 @@ class ModalControllerExtended extends ModalController { export const modalController = new ModalControllerExtended({ changelog: Changelog, + channel_info: ChannelInfo, clipboard: Clipboard, error: Error, link_warning: LinkWarning, @@ -218,6 +230,7 @@ export const modalController = new ModalControllerExtended({ out_of_date: OutOfDate, pending_friend_requests: PendingFriendRequests, server_identity: ServerIdentity, + server_info: ServerInfo, show_token: ShowToken, signed_out: SignedOut, sign_out_sessions: SignOutSessions, diff --git a/src/controllers/modals/components/ChannelInfo.tsx b/src/controllers/modals/components/ChannelInfo.tsx new file mode 100644 index 00000000..0e2149b0 --- /dev/null +++ b/src/controllers/modals/components/ChannelInfo.tsx @@ -0,0 +1,29 @@ +import { X } from "@styled-icons/boxicons-regular"; + +import { Column, H1, IconButton, Modal, Row } from "@revoltchat/ui"; + +import Markdown from "../../../components/markdown/Markdown"; +import { modalController } from "../ModalController"; +import { ModalProps } from "../types"; + +export default function ChannelInfo({ + channel, + ...props +}: ModalProps<"channel_info">) { + return ( + + +

{`#${channel.name}`}

+
+ + + + + }> + +
+ ); +} diff --git a/src/controllers/modals/components/ServerInfo.tsx b/src/controllers/modals/components/ServerInfo.tsx new file mode 100644 index 00000000..786026ad --- /dev/null +++ b/src/controllers/modals/components/ServerInfo.tsx @@ -0,0 +1,48 @@ +import { X } from "@styled-icons/boxicons-regular"; + +import { Text } from "preact-i18n"; + +import { Column, H1, IconButton, Modal, Row } from "@revoltchat/ui"; + +import Markdown from "../../../components/markdown/Markdown"; +import { report } from "../../safety"; +import { modalController } from "../ModalController"; +import { ModalProps } from "../types"; + +export default function ServerInfo({ + server, + ...props +}: ModalProps<"server_info">) { + return ( + + +

{server.name}

+
+ + + + + } + actions={[ + { + onClick: () => + modalController.push({ + type: "server_identity", + member: server.member!, + }), + children: "Edit Identity", + palette: "primary", + }, + { + onClick: () => report(server), + children: , + palette: "error", + }, + ]}> + +
+ ); +} diff --git a/src/controllers/modals/types.ts b/src/controllers/modals/types.ts index d95297ac..160673af 100644 --- a/src/controllers/modals/types.ts +++ b/src/controllers/modals/types.ts @@ -1,4 +1,4 @@ -import { API, Client, User, Member } from "revolt.js"; +import { API, Client, User, Member, Channel, Server } from "revolt.js"; export type Modal = { key?: string; @@ -72,6 +72,14 @@ export type Modal = { | { type: "signed_out"; } + | { + type: "channel_info"; + channel: Channel; + } + | { + type: "server_info"; + server: Server; + } ); export type ModalProps = Modal & { type: T } & { diff --git a/src/controllers/safety/index.ts b/src/controllers/safety/index.ts new file mode 100644 index 00000000..bfcb2471 --- /dev/null +++ b/src/controllers/safety/index.ts @@ -0,0 +1,16 @@ +import { Server } from "revolt.js"; + +export function report(object: Server) { + let type; + if (object instanceof Server) { + type = "Server"; + } + + window.open( + `mailto:abuse@revolt.chat?subject=${encodeURIComponent( + `${type} Report`, + )}&body=${encodeURIComponent( + `${type} ID: ${object._id}\nWrite more information here!`, + )}`, + ); +} diff --git a/src/pages/channels/ChannelHeader.tsx b/src/pages/channels/ChannelHeader.tsx index 46860e4b..e2def382 100644 --- a/src/pages/channels/ChannelHeader.tsx +++ b/src/pages/channels/ChannelHeader.tsx @@ -1,19 +1,18 @@ import { At, Hash } from "@styled-icons/boxicons-regular"; import { Notepad, Group } from "@styled-icons/boxicons-solid"; import { observer } from "mobx-react-lite"; -import { Channel } from "revolt.js"; -import { User } from "revolt.js"; +import { Channel, User } from "revolt.js"; import styled from "styled-components/macro"; import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice"; -import { useIntermediate } from "../../context/intermediate/Intermediate"; import { getChannelName } from "../../context/revoltjs/util"; import { useStatusColour } from "../../components/common/user/UserIcon"; import UserStatus from "../../components/common/user/UserStatus"; import Markdown from "../../components/markdown/Markdown"; import { PageHeader } from "../../components/ui/Header"; +import { modalController } from "../../controllers/modals/ModalController"; import HeaderActions from "./actions/HeaderActions"; export interface ChannelHeaderProps { @@ -65,8 +64,6 @@ const Info = styled.div` `; export default observer(({ channel }: ChannelHeaderProps) => { - const { openScreen } = useIntermediate(); - const name = getChannelName(channel); let icon, recipient: User | undefined; switch (channel.channel_type) { @@ -114,8 +111,8 @@ export default observer(({ channel }: ChannelHeaderProps) => { - openScreen({ - id: "channel_info", + modalController.push({ + type: "channel_info", channel, }) }>