/* eslint-disable react-hooks/rules-of-hooks */ import { X } from "@styled-icons/boxicons-regular"; import { RelationshipStatus } from "revolt-api/types/Users"; import { SYSTEM_USER_ID } from "revolt.js"; import { Message as MessageI } from "revolt.js/dist/maps/Messages"; import styled from "styled-components"; import { decodeTime } from "ulid"; import { Text } from "preact-i18n"; import { memo } from "preact/compat"; import { useEffect, useState } from "preact/hooks"; import { internalSubscribe, internalEmit } from "../../../lib/eventEmitter"; import { RenderState } from "../../../lib/renderer/types"; import { connectState } from "../../../redux/connector"; import { QueuedMessage } from "../../../redux/reducers/queue"; import RequiresOnline from "../../../context/revoltjs/RequiresOnline"; import { useClient } from "../../../context/revoltjs/RevoltClient"; import Message from "../../../components/common/messaging/Message"; import { SystemMessage } from "../../../components/common/messaging/SystemMessage"; import DateDivider from "../../../components/ui/DateDivider"; import Preloader from "../../../components/ui/Preloader"; import { Children } from "../../../types/Preact"; import ConversationStart from "./ConversationStart"; import MessageEditor from "./MessageEditor"; interface Props { id: string; state: RenderState; highlight?: string; queue: QueuedMessage[]; } const BlockedMessage = styled.div` font-size: 0.8em; margin-top: 6px; padding: 4px 64px; color: var(--tertiary-foreground); &:hover { background: var(--hover); } `; function MessageRenderer({ id, state, queue, highlight }: Props) { if (state.type !== "RENDER") return null; const client = useClient(); const userId = client.user!._id; const [editing, setEditing] = useState(undefined); const stopEditing = () => { setEditing(undefined); internalEmit("TextArea", "focus", "message"); }; useEffect(() => { function editLast() { if (state.type !== "RENDER") return; for (let i = state.messages.length - 1; i >= 0; i--) { if (state.messages[i].author_id === userId) { setEditing(state.messages[i]._id); internalEmit("MessageArea", "jump_to_bottom"); return; } } } const subs = [ internalSubscribe("MessageRenderer", "edit_last", editLast), internalSubscribe( "MessageRenderer", "edit_message", setEditing as (...args: unknown[]) => void, ), ]; return () => subs.forEach((unsub) => unsub()); }, [state.messages, state.type, userId]); const render: Children[] = []; let previous: MessageI | undefined; if (state.atTop) { render.push(); } else { render.push( , ); } let head = true; function compare( current: string, curAuthor: string, previous: string, prevAuthor: string, ) { const atime = decodeTime(current), adate = new Date(atime), btime = decodeTime(previous), bdate = new Date(btime); if ( adate.getFullYear() !== bdate.getFullYear() || adate.getMonth() !== bdate.getMonth() || adate.getDate() !== bdate.getDate() ) { render.push(); head = true; } head = curAuthor !== prevAuthor || Math.abs(btime - atime) >= 420000; } let blocked = 0; function pushBlocked() { render.push( {" "} , ); blocked = 0; } for (const message of state.messages) { if (previous) { compare( message._id, message.author_id, previous._id, previous.author_id, ); } if (message.author_id === SYSTEM_USER_ID) { render.push( , ); } else if ( message.author?.relationship === RelationshipStatus.Blocked ) { blocked++; } else { if (blocked > 0) pushBlocked(); render.push( ) : undefined } attachContext highlight={highlight === message._id} />, ); } previous = message; } if (blocked > 0) pushBlocked(); const nonces = state.messages.map((x) => x.nonce); if (state.atBottom) { for (const msg of queue) { if (msg.channel !== id) continue; if (nonces.includes(msg.id)) continue; if (previous) { compare(msg.id, userId!, previous._id, previous.author_id); previous = { _id: msg.id, author_id: userId!, } as MessageI; } render.push( x.id), }) } key={msg.id} queued={msg} head={head} attachContext />, ); } } else { render.push( , ); } return <>{render}; } export default memo( connectState>(MessageRenderer, (state) => { return { queue: state.queue, }; }), );