(feat): add custom lint rules
(qol): update todo (chore): update licenses
This commit is contained in:
parent
bf8f449f03
commit
17db895203
28 changed files with 585 additions and 513 deletions
|
|
@ -1,8 +1,7 @@
|
|||
import * as React from "react";
|
||||
import type { RawMessage } from "../values";
|
||||
import Text from "@tensamin/markdown/text";
|
||||
import { AlertTriangle, Check, Ellipse, RefreshCw } from "lucide-react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { memo, useCallback, useEffect, useState } from "react";
|
||||
import type { User } from "@tensamin/user/context";
|
||||
|
||||
import {
|
||||
|
|
@ -384,7 +383,7 @@ function MessageComponent({
|
|||
);
|
||||
}
|
||||
|
||||
export default React.memo(MessageComponent, (prev, next) => {
|
||||
export default memo(MessageComponent, (prev, next) => {
|
||||
return (
|
||||
prev.message.SendTime === next.message.SendTime &&
|
||||
prev.message.Content === next.message.Content &&
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
import * as React from "react";
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { useInfiniteQuery } from "@tanstack/react-query";
|
||||
import { useVirtualizer } from "@tanstack/react-virtual";
|
||||
|
||||
|
|
@ -82,21 +89,21 @@ export default function Screen() {
|
|||
error,
|
||||
errorDescription,
|
||||
} = useChat();
|
||||
const scrollRef = React.useRef<HTMLDivElement | null>(null);
|
||||
const topSentinelRef = React.useRef<HTMLDivElement | null>(null);
|
||||
const didInitialScrollRef = React.useRef(false);
|
||||
const userScrolledUpRef = React.useRef(false);
|
||||
const isAtBottomRef = React.useRef(true);
|
||||
const smoothScrollFrameRef = React.useRef<number | null>(null);
|
||||
const smoothScrollTargetRef = React.useRef(0);
|
||||
const hasNextPageRef = React.useRef(false);
|
||||
const isFetchingNextPageRef = React.useRef(false);
|
||||
const fetchNextPageRef = React.useRef<(() => void) | null>(null);
|
||||
const scrollRef = useRef<HTMLDivElement | null>(null);
|
||||
const topSentinelRef = useRef<HTMLDivElement | null>(null);
|
||||
const didInitialScrollRef = useRef(false);
|
||||
const userScrolledUpRef = useRef(false);
|
||||
const isAtBottomRef = useRef(true);
|
||||
const smoothScrollFrameRef = useRef<number | null>(null);
|
||||
const smoothScrollTargetRef = useRef(0);
|
||||
const hasNextPageRef = useRef(false);
|
||||
const isFetchingNextPageRef = useRef(false);
|
||||
const fetchNextPageRef = useRef<(() => void) | null>(null);
|
||||
|
||||
const [lastLiveMessageCount, setLastLiveMessageCount] = React.useState(0);
|
||||
const [didInitialScroll, setDidInitialScroll] = React.useState(false);
|
||||
const [viewportHeight, setViewportHeight] = React.useState(0);
|
||||
const [value, setValue] = React.useState("");
|
||||
const [lastLiveMessageCount, setLastLiveMessageCount] = useState(0);
|
||||
const [didInitialScroll, setDidInitialScroll] = useState(false);
|
||||
const [viewportHeight, setViewportHeight] = useState(0);
|
||||
const [value, setValue] = useState("");
|
||||
|
||||
const hasValidChatUser = Number.isSafeInteger(userId) && userId > 0;
|
||||
const hasChatSecret = chatSecret !== null;
|
||||
|
|
@ -120,7 +127,7 @@ export default function Screen() {
|
|||
isFetchingNextPage: isFetchingMessagesNextPage,
|
||||
} = messagesQuery;
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
hasNextPageRef.current = hasMessagesNextPage;
|
||||
isFetchingNextPageRef.current = isFetchingMessagesNextPage;
|
||||
fetchNextPageRef.current = () => {
|
||||
|
|
@ -128,7 +135,7 @@ export default function Screen() {
|
|||
};
|
||||
}, [fetchMessagesNextPage, hasMessagesNextPage, isFetchingMessagesNextPage]);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
clearLiveMessages();
|
||||
didInitialScrollRef.current = false;
|
||||
userScrolledUpRef.current = false;
|
||||
|
|
@ -137,7 +144,7 @@ export default function Screen() {
|
|||
setLastLiveMessageCount(0);
|
||||
}, [clearLiveMessages, userId]);
|
||||
|
||||
const historicalMessages = React.useMemo(() => {
|
||||
const historicalMessages = useMemo(() => {
|
||||
const pages = messagesQuery.data?.pages ?? [];
|
||||
const seenSendTimes = new Set<number>();
|
||||
const dedupedMessages: RawMessage[] = [];
|
||||
|
|
@ -156,7 +163,7 @@ export default function Screen() {
|
|||
|
||||
const liveMessagesSnapshot = liveMessages();
|
||||
|
||||
const liveWithoutDuplicates = React.useMemo(() => {
|
||||
const liveWithoutDuplicates = useMemo(() => {
|
||||
const historicalSendTimes = new Set(
|
||||
historicalMessages.map((message) => message.SendTime),
|
||||
);
|
||||
|
|
@ -166,15 +173,15 @@ export default function Screen() {
|
|||
);
|
||||
}, [historicalMessages, liveMessagesSnapshot]);
|
||||
|
||||
const messages = React.useMemo(() => {
|
||||
const messages = useMemo(() => {
|
||||
return [...historicalMessages, ...liveWithoutDuplicates];
|
||||
}, [historicalMessages, liveWithoutDuplicates]);
|
||||
|
||||
const historicalMessageChunks = React.useMemo(() => {
|
||||
const historicalMessageChunks = useMemo(() => {
|
||||
return buildMessageChunks(historicalMessages, "history");
|
||||
}, [historicalMessages]);
|
||||
|
||||
const liveMessageChunks = React.useMemo(() => {
|
||||
const liveMessageChunks = useMemo(() => {
|
||||
return buildMessageChunks(
|
||||
liveWithoutDuplicates,
|
||||
"live",
|
||||
|
|
@ -182,18 +189,18 @@ export default function Screen() {
|
|||
);
|
||||
}, [historicalMessages.length, liveWithoutDuplicates]);
|
||||
|
||||
const messageChunks = React.useMemo(() => {
|
||||
const messageChunks = useMemo(() => {
|
||||
return [...liveMessageChunks, ...historicalMessageChunks];
|
||||
}, [historicalMessageChunks, liveMessageChunks]);
|
||||
|
||||
const virtualRowCount = messageChunks.length;
|
||||
|
||||
const getItemKey = React.useCallback(
|
||||
const getItemKey = useCallback(
|
||||
(index: number) => messageChunks[index]?.key ?? index,
|
||||
[messageChunks],
|
||||
);
|
||||
|
||||
const estimateSize = React.useCallback(() => FALLBACK_MESSAGE_HEIGHT, []);
|
||||
const estimateSize = useCallback(() => FALLBACK_MESSAGE_HEIGHT, []);
|
||||
|
||||
// eslint-disable-next-line react-hooks/incompatible-library
|
||||
const virtualizer = useVirtualizer({
|
||||
|
|
@ -207,7 +214,7 @@ export default function Screen() {
|
|||
const contentHeight = Math.max(totalSize, viewportHeight);
|
||||
const verticalOffset = Math.max(0, viewportHeight - totalSize);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
const element = scrollRef.current;
|
||||
if (!element || typeof ResizeObserver === "undefined") {
|
||||
return;
|
||||
|
|
@ -227,7 +234,7 @@ export default function Screen() {
|
|||
};
|
||||
}, []);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
if (didInitialScrollRef.current || virtualRowCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -244,7 +251,7 @@ export default function Screen() {
|
|||
});
|
||||
}, [virtualizer, virtualRowCount]);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
const count = liveMessagesSnapshot.length;
|
||||
|
||||
if (count > lastLiveMessageCount && isAtBottomRef.current) {
|
||||
|
|
@ -263,7 +270,7 @@ export default function Screen() {
|
|||
virtualizer,
|
||||
]);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (
|
||||
viewportHeight === 0 ||
|
||||
totalSize > viewportHeight ||
|
||||
|
|
@ -276,7 +283,7 @@ export default function Screen() {
|
|||
void messagesQuery.fetchNextPage();
|
||||
}, [didInitialScroll, messagesQuery, totalSize, viewportHeight]);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
if (
|
||||
!didInitialScroll ||
|
||||
userScrolledUpRef.current ||
|
||||
|
|
@ -292,7 +299,7 @@ export default function Screen() {
|
|||
});
|
||||
}, [didInitialScroll, virtualRowCount]);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const root = scrollRef.current;
|
||||
const sentinel = topSentinelRef.current;
|
||||
|
||||
|
|
@ -324,7 +331,7 @@ export default function Screen() {
|
|||
};
|
||||
}, [didInitialScroll, messagesQuery, virtualRowCount]);
|
||||
|
||||
const handleContainerScroll = React.useCallback(() => {
|
||||
const handleContainerScroll = useCallback(() => {
|
||||
if (!scrollRef.current) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -336,7 +343,7 @@ export default function Screen() {
|
|||
}
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const element = scrollRef.current;
|
||||
if (!element) {
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in a new issue