forked from rDrama/rDrama
Replace QuotedMessage with QuotedMessageLink
parent
aea590dda1
commit
fe1d97a517
|
@ -21,7 +21,6 @@ body {
|
|||
|
||||
.App-heading {
|
||||
flex-basis: 3rem;
|
||||
border-bottom: 1px dashed var(--primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
@ -47,7 +46,6 @@ body {
|
|||
scrollbar-width: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-bottom: 1px dashed var(--primary);
|
||||
}
|
||||
|
||||
.App-content::-webkit-scrollbar {
|
||||
|
@ -81,8 +79,13 @@ body {
|
|||
}
|
||||
|
||||
.App-bottom-extra {
|
||||
padding: 1rem;
|
||||
height: 64px;
|
||||
padding: .25rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
.App-content {
|
||||
height: 50vh;
|
||||
}
|
||||
}
|
||||
|
||||
/* On mobile, hide the sidebar and make the input full-width. */
|
||||
|
@ -104,3 +107,7 @@ body {
|
|||
lite-youtube {
|
||||
min-width: min(80vw, 500px);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
border: none !important;
|
||||
}
|
|
@ -80,14 +80,11 @@ function AppInner() {
|
|||
</div>
|
||||
<div className="App-bottom-wrapper">
|
||||
<div className="App-bottom">
|
||||
<div
|
||||
className="App-bottom-extra"
|
||||
style={{
|
||||
visibility: quote ? "visible" : "hidden",
|
||||
}}
|
||||
>
|
||||
{quote && (
|
||||
<div className="App-bottom-extra">
|
||||
{quote && <QuotedMessage />}
|
||||
</div>
|
||||
)}
|
||||
<UserInput />
|
||||
<UsersTyping />
|
||||
</div>
|
||||
|
|
|
@ -1,36 +1,31 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import cx from "classnames";
|
||||
import key from "weak-key";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { Username } from "./Username";
|
||||
import { useChat, useRootContext } from "../../hooks";
|
||||
import { QuotedMessageLink } from "./QuotedMessageLink";
|
||||
import "./ChatMessage.css";
|
||||
|
||||
interface ChatMessageProps extends IChatMessage {
|
||||
interface ChatMessageProps {
|
||||
message: IChatMessage;
|
||||
timestampUpdates: number;
|
||||
showUser?: boolean;
|
||||
}
|
||||
|
||||
const TIMESTAMP_UPDATE_INTERVAL = 20000;
|
||||
const SCROLL_TO_QUOTED_OVERFLOW = 250;
|
||||
const QUOTED_MESSAGE_CONTEXTUAL_HIGHLIGHTING_DURATION = 2500;
|
||||
const QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH = 30;
|
||||
|
||||
export function ChatMessage({
|
||||
id,
|
||||
avatar,
|
||||
message,
|
||||
showUser = true,
|
||||
namecolor,
|
||||
username,
|
||||
hat,
|
||||
text,
|
||||
text_html,
|
||||
text_censored,
|
||||
time,
|
||||
quotes,
|
||||
timestampUpdates,
|
||||
}: ChatMessageProps) {
|
||||
const message = {
|
||||
const {
|
||||
id,
|
||||
avatar,
|
||||
namecolor,
|
||||
|
@ -41,7 +36,7 @@ export function ChatMessage({
|
|||
text_censored,
|
||||
time,
|
||||
quotes,
|
||||
};
|
||||
} = message;
|
||||
const {
|
||||
username: loggedInUsername,
|
||||
admin,
|
||||
|
@ -49,6 +44,7 @@ export function ChatMessage({
|
|||
themeColor,
|
||||
} = useRootContext();
|
||||
const { messageLookup, deleteMessage, quoteMessage } = useChat();
|
||||
const quotedMessage = messageLookup[quotes];
|
||||
const content = censored ? text_censored : text_html;
|
||||
const hasMention = content.includes(loggedInUsername);
|
||||
const mentionStyle = hasMention
|
||||
|
@ -62,10 +58,10 @@ export function ChatMessage({
|
|||
setConfirmedDelete(true);
|
||||
}
|
||||
}, [text, confirmedDelete]);
|
||||
const timestamp = useMemo(() => formatTimeAgo(time), [
|
||||
time,
|
||||
timestampUpdates,
|
||||
]);
|
||||
const timestamp = useMemo(
|
||||
() => formatTimeAgo(time),
|
||||
[time, timestampUpdates]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="ChatMessage" style={mentionStyle} id={id}>
|
||||
|
@ -80,45 +76,7 @@ export function ChatMessage({
|
|||
<div className="ChatMessage-timestamp">{timestamp}</div>
|
||||
</div>
|
||||
)}
|
||||
{quotes && (
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => {
|
||||
const element = document.getElementById(quotes);
|
||||
|
||||
if (element) {
|
||||
element.scrollIntoView();
|
||||
element.style.background = `#${themeColor}33`;
|
||||
|
||||
setTimeout(() => {
|
||||
element.style.background = "unset";
|
||||
}, QUOTED_MESSAGE_CONTEXTUAL_HIGHLIGHTING_DURATION);
|
||||
|
||||
const [appContent] = Array.from(
|
||||
document.getElementsByClassName("App-content")
|
||||
);
|
||||
|
||||
if (appContent) {
|
||||
appContent.scrollTop -= SCROLL_TO_QUOTED_OVERFLOW;
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
Replying to @{messageLookup[quotes]?.username}:{" "}
|
||||
<em>
|
||||
"
|
||||
{messageLookup[quotes]?.text.slice(
|
||||
0,
|
||||
QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH
|
||||
)}
|
||||
{messageLookup[quotes]?.text.length >=
|
||||
QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH
|
||||
? "..."
|
||||
: ""}
|
||||
"
|
||||
</em>
|
||||
</a>
|
||||
)}
|
||||
{quotes && quotedMessage && <QuotedMessageLink message={quotedMessage} />}
|
||||
<div className="ChatMessage-bottom">
|
||||
<div>
|
||||
<span
|
||||
|
@ -170,7 +128,7 @@ export function ChatMessageList() {
|
|||
{messages.map((message, index) => (
|
||||
<ChatMessage
|
||||
key={key(message)}
|
||||
{...message}
|
||||
message={message}
|
||||
timestampUpdates={timestampUpdates}
|
||||
showUser={message.username !== messages[index - 1]?.username}
|
||||
/>
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from "react";
|
|||
import { useChat, useRootContext } from "../../hooks";
|
||||
import { Username } from "./Username";
|
||||
import "./QuotedMessage.css";
|
||||
import { QuotedMessageLink } from "./QuotedMessageLink";
|
||||
|
||||
export function QuotedMessage() {
|
||||
const { quote, quoteMessage } = useChat();
|
||||
|
@ -9,20 +10,8 @@ export function QuotedMessage() {
|
|||
|
||||
return (
|
||||
<div className="QuotedMessage">
|
||||
<div>
|
||||
<Username
|
||||
avatar={quote.avatar}
|
||||
color={quote.namecolor}
|
||||
name={quote.username}
|
||||
hat={quote.hat}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="QuotedMessage-content"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: censored ? quote.text_censored : quote.text_html,
|
||||
}}
|
||||
/>
|
||||
<QuotedMessageLink message={quote} />
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary"
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import React, { useCallback } from "react";
|
||||
import { useRootContext } from "../../hooks";
|
||||
|
||||
const SCROLL_TO_QUOTED_OVERFLOW = 250;
|
||||
const QUOTED_MESSAGE_CONTEXTUAL_HIGHLIGHTING_DURATION = 2500;
|
||||
const QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH = 30;
|
||||
|
||||
export function QuotedMessageLink({ message }: { message: IChatMessage }) {
|
||||
const { themeColor } = useRootContext();
|
||||
const handleLinkClick = useCallback(() => {
|
||||
const element = document.getElementById(message.id);
|
||||
|
||||
if (element) {
|
||||
element.scrollIntoView();
|
||||
element.style.background = `#${themeColor}33`;
|
||||
|
||||
setTimeout(() => {
|
||||
element.style.background = "unset";
|
||||
}, QUOTED_MESSAGE_CONTEXTUAL_HIGHLIGHTING_DURATION);
|
||||
|
||||
const [appContent] = Array.from(
|
||||
document.getElementsByClassName("App-content")
|
||||
);
|
||||
|
||||
if (appContent) {
|
||||
appContent.scrollTop -= SCROLL_TO_QUOTED_OVERFLOW;
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<a href="#" onClick={handleLinkClick}>
|
||||
Replying to @{message.username}:{" "}
|
||||
<em>
|
||||
"{message.text.slice(0, QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH)}
|
||||
{message.text.length >= QUOTED_MESSAGE_CONTEXTUAL_SNIPPET_LENGTH
|
||||
? "..."
|
||||
: ""}
|
||||
"
|
||||
</em>
|
||||
</a>
|
||||
);
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
.UserList {
|
||||
padding: 1rem;
|
||||
border-left: 1px dotted var(--primary);
|
||||
flex: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
export * from "./ChatHeading";
|
||||
export * from "./ChatMessage";
|
||||
export * from "./QuotedMessage";
|
||||
export * from "./UserInput";
|
||||
export * from "./UserList";
|
||||
export * from "./Username";
|
||||
export * from "./UsersTyping";
|
||||
export * from "./QuotedMessage";
|
||||
export * from "./QuotedMessageLink";
|
||||
|
|
Loading…
Reference in New Issue