diff --git a/src/components/common/AgeGate.tsx b/src/components/common/AgeGate.tsx new file mode 100644 index 00000000..b78f60b9 --- /dev/null +++ b/src/components/common/AgeGate.tsx @@ -0,0 +1,90 @@ +import { useHistory } from "react-router-dom"; +import { useState } from "preact/hooks"; +import styled from "styled-components"; +import { dispatch, getState } from "../../redux"; +import Checkbox from "../ui/Checkbox"; +import Button from "../ui/Button"; +import { Children } from "../../types/Preact"; +import { Channel } from "revolt.js"; +import { Text } from "preact-i18n"; + +const Base = styled.div` + display: flex; + flex-grow: 1; + flex-direction: column; + align-items: center; + justify-content: center; + user-select: none; + padding: 12px; + + img { + height: 150px; + } + + .subtext { + color: var(--secondary-foreground); + margin-bottom: 12px; + font-size: 14px; + } + + .actions { + margin-top: 20px; + display: flex; + gap: 12px; + } +`; + +type Props = { + gated: boolean; + children: Children; +} & { + type: 'channel'; + channel: Channel; +} + +export default function AgeGate(props: Props) { + const history = useHistory(); + const [consent, setConsent] = useState(getState().sectionToggle['nsfw'] ?? false); + const [ageGate, setAgeGate] = useState(false); + + if (ageGate || !props.gated) { + return <>{ props.children }; + } else { + if (!(props.channel.channel_type === 'Group' || props.channel.channel_type === 'TextChannel')) return <>{ props.children }; + + return ( + + +

{props.channel.name}

+ + {" "} + + + + { + setConsent(v); + if (v) { + dispatch({ type: 'SECTION_TOGGLE_SET', id: 'nsfw', state: true }); + } else { + dispatch({ type: 'SECTION_TOGGLE_UNSET', id: 'nsfw' }); + } + }}> + + +
+ + +
+ + ); + } +} diff --git a/src/components/common/messaging/MessageBase.tsx b/src/components/common/messaging/MessageBase.tsx index c5e6ebb8..e040168e 100644 --- a/src/components/common/messaging/MessageBase.tsx +++ b/src/components/common/messaging/MessageBase.tsx @@ -21,7 +21,7 @@ export interface BaseMessageProps { export default styled.div` display: flex; - overflow-x: none; + overflow: none; padding: 0.125rem; flex-direction: row; padding-right: 16px; diff --git a/src/components/markdown/Renderer.tsx b/src/components/markdown/Renderer.tsx index 1b531460..205328ce 100644 --- a/src/components/markdown/Renderer.tsx +++ b/src/components/markdown/Renderer.tsx @@ -66,16 +66,9 @@ export const md: MarkdownIt = MarkdownIt({ .use(MarkdownKatex, { throwOnError: false, maxExpand: 0, + maxSize: 10 }); -// ? Force links to open _blank. -// From: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer -const defaultRender = - md.renderer.rules.link_open || - function (tokens, idx, options, _env, self) { - return self.renderToken(tokens, idx, options); - }; - // TODO: global.d.ts file for defining globals declare global { interface Window { @@ -124,15 +117,19 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) { }, []); const handleLink = useCallback((ev: MouseEvent) => { - ev.preventDefault(); if (ev.currentTarget) { const element = ev.currentTarget as HTMLAnchorElement; const url = new URL(element.href, location.href); const pathname = url.pathname; if (pathname.startsWith("/@")) { - internalEmit("Intermediate", "openProfile", pathname.substr(2)); + let id = pathname.substr(2); + if (/[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}/.test(id)) { + ev.preventDefault(); + internalEmit("Intermediate", "openProfile", id); + } } else { + ev.preventDefault(); internalEmit("Intermediate", "navigate", pathname); } } diff --git a/src/pages/channels/Channel.tsx b/src/pages/channels/Channel.tsx index f68b29a4..6484bdc9 100644 --- a/src/pages/channels/Channel.tsx +++ b/src/pages/channels/Channel.tsx @@ -13,8 +13,7 @@ import { useChannel, useForceUpdate } from "../../context/revoltjs/hooks"; import MessageBox from "../../components/common/messaging/MessageBox"; import JumpToBottom from "../../components/common/messaging/bars/JumpToBottom"; import TypingIndicator from "../../components/common/messaging/bars/TypingIndicator"; -import Button from "../../components/ui/Button"; -import Checkbox from "../../components/ui/Checkbox"; +import AgeGate from "../../components/common/AgeGate"; import MemberSidebar from "../../components/navigation/right/MemberSidebar"; import ChannelHeader from "./ChannelHeader"; @@ -36,32 +35,6 @@ const ChannelContent = styled.div` flex-direction: column; `; -const AgeGate = styled.div` - display: flex; - flex-grow: 1; - flex-direction: column; - align-items: center; - justify-content: center; - user-select: none; - padding: 12px; - - img { - height: 150px; - } - - .subtext { - color: var(--secondary-foreground); - margin-bottom: 12px; - font-size: 14px; - } - - .actions { - margin-top: 20px; - display: flex; - gap: 12px; - } -`; - export function Channel({ id }: { id: string }) { const ctx = useForceUpdate(); const channel = useChannel(id, ctx); @@ -77,52 +50,18 @@ export function Channel({ id }: { id: string }) { const MEMBERS_SIDEBAR_KEY = "sidebar_members"; function TextChannel({ channel }: { channel: Channels.Channel }) { - if ( - (channel.channel_type === "TextChannel" || - channel.channel_type === "Group") && - channel.name.includes("nsfw") - ) { - const goBack = useHistory(); - const [consent, setConsent] = useState(false); - const [ageGate, setAgeGate] = useState(false); - if (!ageGate) { - return ( - - -

{channel.name}

- - This channel is marked as NSFW.{" "} - Learn more - - - setConsent(v)}> - I confirm that I am at least 18 years old. - -
- - -
-
- ); - } - } - const [showMembers, setMembers] = useState( getState().sectionToggle[MEMBERS_SIDEBAR_KEY] ?? true, ); let id = channel._id; return ( - <> + { @@ -154,7 +93,7 @@ function TextChannel({ channel }: { channel: Channels.Channel }) { )} - + ); }