This commit is contained in:
2026-07-02 23:13:24 +07:00
parent 31f354d9ca
commit c04194bb85
36 changed files with 1005 additions and 41 deletions
+15
View File
@@ -12,6 +12,18 @@ import {
import { pb } from "@/lib/pb";
import { Dictionary } from "@/lib/IDict";
/**
* Полноэкранная версия гостевой книги (аналог TerminalGuestbook на главной, но
* без ограничения в 50 последних сообщений — здесь есть постраничная подгрузка
* истории вверх при скролле). Источники и защита от спама те же:
* - realtime через `pb.collection("comments").subscribe("*", ...)` для новых сообщений;
* - отправка идёт через Rust-шлюз `/api/proxy/api/comments`, а не напрямую в PocketBase,
* т.к. там сообщения проходят модерацию (ИИ-фильтр на мат/спам/токсичность);
* - 406 от прокси — отдельный кейс ("отклонено фильтром"), отличный от обычной
* сетевой ошибки ("сервер недоступен");
* - клиентский кулдаун 60 секунд между сообщениями через localStorage, синхронизирован
* с сервером тем же ключом last_comment_time, что и в TerminalGuestbook.
*/
export function TerminalClient({ dict }: { dict: Dictionary["terminal"] }) {
const [messages, setMessages] = useState<any[]>([]);
const [nickname, setNickname] = useState("");
@@ -64,6 +76,9 @@ export function TerminalClient({ dict }: { dict: Dictionary["terminal"] }) {
}
}, [messages]);
// Подгрузка истории постранично (30 сообщений за раз). При скролле наверх (см.
// handleScroll) запрашивается следующая страница, и новые сообщения добавляются
// в начало массива с сохранением позиции скролла (см. эффект с prevScrollHeight).
const fetchHistory = async (pageToLoad: number, isInitial = false) => {
try {
if (isInitial) setIsLoading(true);