mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-22 18:32:34 +01:00
you get a link, and you get a link, and everyone gets a link
This commit is contained in:
parent
2db53e2765
commit
0d4ade85b5
16
src/components/Link.tsx
Normal file
16
src/components/Link.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
export const Link = styled.a`
|
||||||
|
// remove the default underline
|
||||||
|
text-decoration: none;
|
||||||
|
// set the color to the primary color
|
||||||
|
color: var(--primary-light);
|
||||||
|
// remove the color when already visited because ew
|
||||||
|
&:visited {
|
||||||
|
color: var(--primary-light);
|
||||||
|
}
|
||||||
|
// when hovered, add underline
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
`;
|
@ -8,8 +8,13 @@ import { QueuedMessage } from "../../stores/MessageQueue";
|
|||||||
import { default as MessageObject } from "../../stores/objects/Message";
|
import { default as MessageObject } from "../../stores/objects/Message";
|
||||||
import { calendarStrings } from "../../utils/i18n";
|
import { calendarStrings } from "../../utils/i18n";
|
||||||
import Avatar from "../Avatar";
|
import Avatar from "../Avatar";
|
||||||
|
import { Link } from "../Link";
|
||||||
import { IContextMenuItem } from "./../ContextMenuItem";
|
import { IContextMenuItem } from "./../ContextMenuItem";
|
||||||
|
|
||||||
|
// max width/height for images
|
||||||
|
const maxWidth = 400;
|
||||||
|
const maxHeight = 300;
|
||||||
|
|
||||||
type MessageLike = MessageObject | QueuedMessage;
|
type MessageLike = MessageObject | QueuedMessage;
|
||||||
|
|
||||||
const MessageListItem = styled.li`
|
const MessageListItem = styled.li`
|
||||||
@ -55,10 +60,6 @@ const MessageContent = styled.div<{ sending?: boolean; failed?: boolean }>`
|
|||||||
color: ${(props) => (props.failed ? "var(--error)" : undefined)};
|
color: ${(props) => (props.failed ? "var(--error)" : undefined)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// max width/height for images
|
|
||||||
const maxWidth = 400;
|
|
||||||
const maxHeight = 300;
|
|
||||||
|
|
||||||
function calculateImageRatio(width: number, height: number) {
|
function calculateImageRatio(width: number, height: number) {
|
||||||
let o = 1;
|
let o = 1;
|
||||||
width > maxWidth && (o = maxWidth / width);
|
width > maxWidth && (o = maxWidth / width);
|
||||||
@ -96,6 +97,40 @@ function calculateScaledDimensions(
|
|||||||
return { scaledWidth, scaledHeight };
|
return { scaledWidth, scaledHeight };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.js-craft.io/blog/react-detect-url-text-convert-link/
|
||||||
|
const Linkify = ({ children }: { children: string }) => {
|
||||||
|
const isUrl = (word: string) => {
|
||||||
|
const urlPattern =
|
||||||
|
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
|
||||||
|
return word.match(urlPattern);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const addMarkup = (word: string) => {
|
||||||
|
// return isUrl(word) ? `<a href="${word}" target="_blank" noreferer>${word}</a>` : word;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// split spaces and newlines
|
||||||
|
const words = children.split(/(\s+)/);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{words.map((x) => {
|
||||||
|
if (isUrl(x)) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Link href={x} target="_blank" rel="noreferrer">
|
||||||
|
{x}
|
||||||
|
</Link>{" "}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <>{x}</>;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
message: MessageLike;
|
message: MessageLike;
|
||||||
isHeader?: boolean;
|
isHeader?: boolean;
|
||||||
@ -188,7 +223,7 @@ function Message({ message, isHeader, isSending, isFailed }: Props) {
|
|||||||
|
|
||||||
{message.type === MessageType.Default ? (
|
{message.type === MessageType.Default ? (
|
||||||
<MessageContent sending={isSending} failed={isFailed}>
|
<MessageContent sending={isSending} failed={isFailed}>
|
||||||
{message.content}
|
{message.content ? <Linkify>{message.content}</Linkify> : null}
|
||||||
{"attachments" in message &&
|
{"attachments" in message &&
|
||||||
message.attachments.map((attachment) => {
|
message.attachments.map((attachment) => {
|
||||||
let a: JSX.Element = <></>;
|
let a: JSX.Element = <></>;
|
||||||
|
Loading…
Reference in New Issue
Block a user