/* eslint-disable react-hooks/rules-of-hooks */ import { X } from "@styled-icons/boxicons-regular"; import isEqual from "lodash.isequal"; import { observer } from "mobx-react-lite"; import { Masquerade } from "revolt-api/types/Channels"; import { RelationshipStatus } from "revolt-api/types/Users"; import { Message as MessageI } from "revolt.js/dist/maps/Messages"; import { Nullable } from "revolt.js/dist/util/null"; import styled from "styled-components"; import { decodeTime } from "ulid"; import { Text } from "preact-i18n"; import { useEffect, useState } from "preact/hooks"; import { internalSubscribe, internalEmit } from "../../../lib/eventEmitter"; import { ChannelRenderer } from "../../../lib/renderer/Singleton"; import { useApplicationState } from "../../../mobx/State"; 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 { last_id?: string; highlight?: string; renderer: ChannelRenderer; } const BlockedMessage = styled.div` font-size: 0.8em; margin-top: 6px; padding: 4px 64px; color: var(--tertiary-foreground); &:hover { background: var(--hover); } `; export default observer(({ last_id, renderer, highlight }: Props) => { const client = useClient(); const userId = client.user!._id; const queue = useApplicationState().queue; const [editing, setEditing] = useState(undefined); const stopEditing = () => { setEditing(undefined); internalEmit("TextArea", "focus", "message"); }; useEffect(() => { function editLast() { if (renderer.state !== "RENDER") return; for (let i = renderer.messages.length - 1; i >= 0; i--) { if (renderer.messages[i].author_id === userId) { setEditing(renderer.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()); }, [renderer.messages, renderer.state, userId]); const render: Children[] = []; let previous: MessageI | undefined; if (renderer.atTop) { render.push(); } else { render.push( , ); } let head = true; let divided = false; function compare( current: string, curAuthor: string, currentMasq: Nullable, previous: string, prevAuthor: string, previousMasq: Nullable, ) { const atime = decodeTime(current), adate = new Date(atime), btime = decodeTime(previous), bdate = new Date(btime); let unread = false; if (!divided && last_id && previous >= last_id) { unread = true; divided = true; } head = false; if ( unread || adate.getFullYear() !== bdate.getFullYear() || adate.getMonth() !== bdate.getMonth() || adate.getDate() !== bdate.getDate() ) { render.push(); head = true; } head = head || curAuthor !== prevAuthor || Math.abs(btime - atime) >= 420000 || !isEqual(currentMasq, previousMasq); } let blocked = 0; function pushBlocked() { render.push( {" "} , ); blocked = 0; } for (const message of renderer.messages) { if (previous) { compare( message._id, message.author_id, message.masquerade, previous._id, previous.author_id, previous.masquerade, ); } if (message.author_id === "00000000000000000000000000") { 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 = renderer.messages.map((x) => x.nonce); if (renderer.atBottom) { for (const msg of queue.get(renderer.channel._id)) { if (nonces.includes(msg.id)) continue; if (previous) { compare( msg.id, userId!, null, previous._id, previous.author_id, previous.masquerade, ); 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}; });