forked from rDrama/rDrama
1
0
Fork 0

Replace QuotedMessage with QuotedMessageLink

master
Outrun Colors 2022-09-24 19:07:57 -05:00
parent aea590dda1
commit fe1d97a517
No known key found for this signature in database
GPG Key ID: 0426976DCEFE6073
7 changed files with 83 additions and 89 deletions

View File

@ -21,7 +21,6 @@ body {
.App-heading { .App-heading {
flex-basis: 3rem; flex-basis: 3rem;
border-bottom: 1px dashed var(--primary);
display: flex; display: flex;
align-items: center; align-items: center;
} }
@ -47,7 +46,6 @@ body {
scrollbar-width: none; scrollbar-width: none;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-bottom: 1px dashed var(--primary);
} }
.App-content::-webkit-scrollbar { .App-content::-webkit-scrollbar {
@ -81,8 +79,13 @@ body {
} }
.App-bottom-extra { .App-bottom-extra {
padding: 1rem; padding: .25rem;
height: 64px; }
@media screen and (max-width: 1000px) {
.App-content {
height: 50vh;
}
} }
/* On mobile, hide the sidebar and make the input full-width. */ /* On mobile, hide the sidebar and make the input full-width. */
@ -104,3 +107,7 @@ body {
lite-youtube { lite-youtube {
min-width: min(80vw, 500px); min-width: min(80vw, 500px);
} }
.btn-secondary {
border: none !important;
}

View File

@ -80,14 +80,11 @@ function AppInner() {
</div> </div>
<div className="App-bottom-wrapper"> <div className="App-bottom-wrapper">
<div className="App-bottom"> <div className="App-bottom">
<div {quote && (
className="App-bottom-extra" <div className="App-bottom-extra">
style={{
visibility: quote ? "visible" : "hidden",
}}
>
{quote && <QuotedMessage />} {quote && <QuotedMessage />}
</div> </div>
)}
<UserInput /> <UserInput />
<UsersTyping /> <UsersTyping />
</div> </div>

View File

@ -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 cx from "classnames";
import key from "weak-key"; import key from "weak-key";
import humanizeDuration from "humanize-duration"; import humanizeDuration from "humanize-duration";
import { Username } from "./Username"; import { Username } from "./Username";
import { useChat, useRootContext } from "../../hooks"; import { useChat, useRootContext } from "../../hooks";
import { QuotedMessageLink } from "./QuotedMessageLink";
import "./ChatMessage.css"; import "./ChatMessage.css";
interface ChatMessageProps extends IChatMessage { interface ChatMessageProps {
message: IChatMessage;
timestampUpdates: number; timestampUpdates: number;
showUser?: boolean; showUser?: boolean;
} }
const TIMESTAMP_UPDATE_INTERVAL = 20000; 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({ export function ChatMessage({
id, message,
avatar,
showUser = true, showUser = true,
namecolor,
username,
hat,
text,
text_html,
text_censored,
time,
quotes,
timestampUpdates, timestampUpdates,
}: ChatMessageProps) { }: ChatMessageProps) {
const message = { const {
id, id,
avatar, avatar,
namecolor, namecolor,
@ -41,7 +36,7 @@ export function ChatMessage({
text_censored, text_censored,
time, time,
quotes, quotes,
}; } = message;
const { const {
username: loggedInUsername, username: loggedInUsername,
admin, admin,
@ -49,6 +44,7 @@ export function ChatMessage({
themeColor, themeColor,
} = useRootContext(); } = useRootContext();
const { messageLookup, deleteMessage, quoteMessage } = useChat(); const { messageLookup, deleteMessage, quoteMessage } = useChat();
const quotedMessage = messageLookup[quotes];
const content = censored ? text_censored : text_html; const content = censored ? text_censored : text_html;
const hasMention = content.includes(loggedInUsername); const hasMention = content.includes(loggedInUsername);
const mentionStyle = hasMention const mentionStyle = hasMention
@ -62,10 +58,10 @@ export function ChatMessage({
setConfirmedDelete(true); setConfirmedDelete(true);
} }
}, [text, confirmedDelete]); }, [text, confirmedDelete]);
const timestamp = useMemo(() => formatTimeAgo(time), [ const timestamp = useMemo(
time, () => formatTimeAgo(time),
timestampUpdates, [time, timestampUpdates]
]); );
return ( return (
<div className="ChatMessage" style={mentionStyle} id={id}> <div className="ChatMessage" style={mentionStyle} id={id}>
@ -80,45 +76,7 @@ export function ChatMessage({
<div className="ChatMessage-timestamp">{timestamp}</div> <div className="ChatMessage-timestamp">{timestamp}</div>
</div> </div>
)} )}
{quotes && ( {quotes && quotedMessage && <QuotedMessageLink message={quotedMessage} />}
<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>
)}
<div className="ChatMessage-bottom"> <div className="ChatMessage-bottom">
<div> <div>
<span <span
@ -170,7 +128,7 @@ export function ChatMessageList() {
{messages.map((message, index) => ( {messages.map((message, index) => (
<ChatMessage <ChatMessage
key={key(message)} key={key(message)}
{...message} message={message}
timestampUpdates={timestampUpdates} timestampUpdates={timestampUpdates}
showUser={message.username !== messages[index - 1]?.username} showUser={message.username !== messages[index - 1]?.username}
/> />

View File

@ -2,6 +2,7 @@ import React from "react";
import { useChat, useRootContext } from "../../hooks"; import { useChat, useRootContext } from "../../hooks";
import { Username } from "./Username"; import { Username } from "./Username";
import "./QuotedMessage.css"; import "./QuotedMessage.css";
import { QuotedMessageLink } from "./QuotedMessageLink";
export function QuotedMessage() { export function QuotedMessage() {
const { quote, quoteMessage } = useChat(); const { quote, quoteMessage } = useChat();
@ -9,20 +10,8 @@ export function QuotedMessage() {
return ( return (
<div className="QuotedMessage"> <div className="QuotedMessage">
<div> <QuotedMessageLink message={quote} />
<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,
}}
/>
<button <button
type="button" type="button"
className="btn btn-secondary" className="btn btn-secondary"

View File

@ -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>
);
}

View File

@ -1,6 +1,5 @@
.UserList { .UserList {
padding: 1rem; padding: 1rem;
border-left: 1px dotted var(--primary);
flex: 1; flex: 1;
position: absolute; position: absolute;
top: 0; top: 0;

View File

@ -1,7 +1,8 @@
export * from "./ChatHeading"; export * from "./ChatHeading";
export * from "./ChatMessage"; export * from "./ChatMessage";
export * from "./QuotedMessage";
export * from "./UserInput"; export * from "./UserInput";
export * from "./UserList"; export * from "./UserList";
export * from "./Username"; export * from "./Username";
export * from "./UsersTyping"; export * from "./UsersTyping";
export * from "./QuotedMessage";
export * from "./QuotedMessageLink";