1
0
mirror of https://github.com/spacebarchat/client.git synced 2024-11-25 11:42:30 +01:00
This commit is contained in:
Puyodead1 2023-09-22 22:18:27 -04:00
parent 8872de4ad0
commit 711e79cdfd
No known key found for this signature in database
GPG Key ID: A4FA4FEC0DD353FC
5 changed files with 108 additions and 15 deletions

View File

@ -2,8 +2,10 @@ import * as Icons from "@mdi/js";
import { Icon as MdiIcon } from "@mdi/react";
import { IconProps as IconBaseProps } from "@mdi/react/dist/IconProps";
export type IconType = keyof typeof Icons;
export interface IconProps extends Omit<IconBaseProps, "path"> {
icon: keyof typeof Icons;
icon: IconType;
}
function Icon(props: IconProps) {

View File

@ -1,7 +1,7 @@
import React from "react";
import styled from "styled-components";
const Container = styled.div`
const Container = styled.span`
background-color: hsl(var(--background-tertiary-hsl));
padding: 0 5px;
border-radius: 4px;

View File

@ -1,6 +1,7 @@
import { FormattingPatterns } from "@spacebarchat/spacebar-api-types/v9";
import Marked, { ReactRenderer } from "marked-react";
import React from "react";
import reactStringReplace from "react-string-replace";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { materialDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import styled from "styled-components";
@ -8,6 +9,7 @@ import CodeBlock from "../Codeblock";
import Link from "../Link";
import Spoiler from "../Spoiler";
import { MarkdownProps } from "./Markdown";
import Mention from "./Mention";
import Timestamp from "./Timestamp";
const Container = styled.div`
@ -125,21 +127,39 @@ const customRenderer: Partial<ReactRenderer> = {
codespan: (content: string) => <code className="inline">{content}</code>,
link: (href, text) => <Link href={href}>{text}</Link>,
text: (text: string) => {
const spoilerRe = /\|\|([\s\S]+?)\|\|/g;
let replaced: string | React.ReactNode[] = text;
const SpoilerRegex = /\|\|(?<content>[\s\S]+?)\|\|/;
if (spoilerRe.test(text)) {
// get content inside spoiler tags
const spoilerContent = text.match(spoilerRe)![0].slice(2, -2);
return <Spoiler children={spoilerContent} />;
}
// replace the spoiler with the spoiler component
replaced = reactStringReplace(text, SpoilerRegex, (match, i) => {
return <Spoiler key={i} children={match} />;
});
const match = text.match(FormattingPatterns.Timestamp);
if (match) {
const { timestamp, style } = match.groups || {};
return <Timestamp timestamp={timestamp} style={style} />;
}
replaced = reactStringReplace(replaced, FormattingPatterns.DefaultStyledTimestamp, (match, i) => (
<Timestamp key={i} timestamp={match} />
));
return text;
replaced = reactStringReplace(replaced, /<t:-?(\d{1,13}:[tTdDfFR])>/, (match, i) => {
const parts = match.split(":");
const timestamp = parts[0];
const style = parts[1];
return <Timestamp key={i} timestamp={timestamp} style={style} />;
});
replaced = reactStringReplace(replaced, FormattingPatterns.Channel, (match, i) => (
<Mention key={i} type="channel" id={match} />
));
replaced = reactStringReplace(replaced, FormattingPatterns.User, (match, i) => (
<Mention key={i} type="user" id={match} />
));
replaced = reactStringReplace(replaced, FormattingPatterns.Role, (match, i) => (
<Mention key={i} type="role" id={match} />
));
return replaced;
},
};

View File

@ -0,0 +1,71 @@
import React, { memo } from "react";
import styled from "styled-components";
import { useAppStore } from "../../stores/AppStore";
import User from "../../stores/objects/User";
const Container = styled.span`
padding: 0 2px;
border-radius: 4px;
background-color: hsl(var(--primary-hsl) / 0.3);
&:hover {
background-color: hsl(var(--primary-hsl) / 0.5);
cursor: pointer;
}
`;
interface MentionProps {
id: string;
}
function UserMention({ id }: MentionProps) {
const app = useAppStore();
const [user, setUser] = React.useState<User | null>(null);
React.useEffect(() => {
const user = app.users.get(id);
if (user) setUser(user);
}, [id]);
if (!user)
return (
<Container>
<span>@{id}</span>
</Container>
);
return (
<Container>
<span>@{user.username}</span>
</Container>
);
}
function ChannelMention({ id }: MentionProps) {
return (
<Container>
<span>#{id}</span>
</Container>
);
}
function RoleMention({ id }: MentionProps) {
return (
<Container>
<span>@{id}</span>
</Container>
);
}
interface Props {
type: "role" | "user" | "channel";
id: string;
}
function Mention({ type, id }: Props) {
if (type === "role") return <RoleMention id={id} />;
if (type === "user") return <UserMention id={id} />;
if (type === "channel") return <ChannelMention id={id} />;
return null;
}
export default memo(Mention);

View File

@ -12,7 +12,7 @@ const Container = styled.div`
interface Props {
timestamp: string;
style: string;
style?: string;
}
function Timestamp({ timestamp, style }: Props) {