global fix and add tauri app

This commit is contained in:
lendry
2026-06-26 13:56:54 +03:00
parent aa228d84eb
commit 3b05b7e4d4
50 changed files with 3947 additions and 80 deletions

View File

@@ -1,9 +1,10 @@
'use client';
import { useCallback, useEffect, useRef, useState } from 'react';
import { LayoutGrid, Loader2, Pin, Send, X } from 'lucide-react';
import { LayoutGrid, Loader2, Send, X } from 'lucide-react';
import { BotMessageKeyboard } from '@/components/chat/bot-message-keyboard';
import { BotChatMessageContextMenu } from '@/components/chat/bot-chat-message-context-menu';
import { ChatPinnedMessageBanner } from '@/components/chat/chat-pinned-message-banner';
import { useRealtime } from '@/components/notifications/realtime-provider';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
@@ -69,6 +70,18 @@ export function FamilyBotChat({
const [botMeta, setBotMeta] = useState<BotChatMeta | null>(null);
const { subscribe } = useRealtime();
const { showToast } = useToast();
const pinnedMessage = messages
.filter((message) => message.isPinned)
.sort((left, right) => new Date(right.pinnedAt ?? right.createdAt).getTime() - new Date(left.pinnedAt ?? left.createdAt).getTime())[0] ?? null;
function scrollToBotMessage(messageId: string) {
const element = document.getElementById(`bot-msg-${messageId}`);
if (!element) return false;
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
element.classList.add('blink-highlight');
window.setTimeout(() => element.classList.remove('blink-highlight'), 2000);
return true;
}
const openMiniApp = useCallback(
(url: string) => {
@@ -236,6 +249,17 @@ export function FamilyBotChat({
return (
<div className={cn('flex min-h-0 flex-1 flex-col', className)}>
{pinnedMessage ? (
<ChatPinnedMessageBanner
senderName={pinnedMessage.direction === 'out' ? botName : 'Вы'}
preview={pinnedMessage.text}
onClick={() => {
if (!scrollToBotMessage(pinnedMessage.id)) {
showToast('Закреплённое сообщение пока не загружено в ленте');
}
}}
/>
) : null}
<div className="flex-1 space-y-2 overflow-y-auto px-4 py-4">
{loading ? (
<div className="flex items-center justify-center gap-2 py-8 text-sm text-[#667085]">
@@ -247,15 +271,9 @@ export function FamilyBotChat({
const mine = message.direction === 'in';
const hasKeyboard = Boolean(message.replyMarkupJson?.trim());
return (
<div key={message.id} className={cn('flex', mine ? 'justify-end' : 'justify-start')}>
<div key={message.id} id={`bot-msg-${message.id}`} className={cn('flex', mine ? 'justify-end' : 'justify-start')}>
<BotChatMessageContextMenu text={message.text} onCopy={() => showToast('Текст скопирован')}>
<div className={cn('max-w-[78%] rounded-[18px] px-3 py-2 shadow-sm', mine ? 'rounded-br-md bg-[#effdde]' : 'rounded-bl-md bg-white')}>
{message.isPinned ? (
<div className={cn('mb-1 flex items-center gap-1 text-[11px] font-medium', mine ? 'text-[#6c8f56]' : 'text-[#3390ec]')}>
<Pin className="h-3 w-3" />
Закреплено
</div>
) : null}
{!mine ? <p className="mb-0.5 text-[11px] font-semibold text-[#3390ec]">{botName}</p> : null}
<p className="whitespace-pre-wrap text-sm">{message.text || '…'}</p>
{!mine && hasKeyboard && message.messageId > 0 ? (