From e19105568293fe192439aee99b488ca13f7d21ef Mon Sep 17 00:00:00 2001 From: Bivekich Date: Thu, 17 Jul 2025 13:06:40 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D1=8B=20=D1=81=D1=82=D0=B8=D0=BB=D0=B8=20=D0=B8=20=D1=84=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=BE=D0=B2=20=D0=BC=D0=B5=D1=81=D1=81=D0=B5?= =?UTF-8?q?=D0=BD=D0=B4=D0=B6=D0=B5=D1=80=D0=B0,=20=D0=B2=D0=BA=D0=BB?= =?UTF-8?q?=D1=8E=D1=87=D0=B0=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=BA=D1=83=20=D0=BC=D0=BD=D0=BE=D0=B3=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D1=87=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B2=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4=D0=B0=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D1=82=D0=B8=D0=BB=D0=B5=D0=B9=20?= =?UTF-8?q?=D0=BA=D0=BD=D0=BE=D0=BF=D0=BE=D0=BA.=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9?= =?UTF-8?q?=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D1=81=D0=BA=D0=B0=D1=87?= =?UTF-8?q?=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20API=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B8=D0=B7=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9=20=D0=B8=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=BE=D0=B2=20=D1=81=20=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=BE=D0=B9=20=D0=BE=D1=88=D0=B8?= =?UTF-8?q?=D0=B1=D0=BE=D0=BA.=20=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8?= =?UTF-8?q?=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D1=8B=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=D1=8B=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2=20=D0=B8=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D0=B8=D1=81=D0=B8=20=D0=B3=D0=BE=D0=BB=D0=BE=D1=81=D0=B0?= =?UTF-8?q?,=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=20=D0=B8=D0=BD?= =?UTF-8?q?=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=20=D0=B2=D1=8B=D0=B1?= =?UTF-8?q?=D0=BE=D1=80=D0=B0=20=D1=8D=D0=BC=D0=BE=D0=B4=D0=B7=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/download-file/route.ts | 64 ++++++ src/app/globals.css | 12 +- src/components/messenger/messenger-chat.tsx | 46 +++-- src/components/ui/emoji-picker.tsx | 3 +- src/components/ui/file-message.tsx | 44 ++++- src/components/ui/file-uploader.tsx | 10 +- src/components/ui/image-lightbox.tsx | 205 ++++++++++++++++++++ src/components/ui/image-message.tsx | 99 ++++++---- src/components/ui/voice-recorder.tsx | 7 +- 9 files changed, 412 insertions(+), 78 deletions(-) create mode 100644 src/app/api/download-file/route.ts create mode 100644 src/components/ui/image-lightbox.tsx diff --git a/src/app/api/download-file/route.ts b/src/app/api/download-file/route.ts new file mode 100644 index 0000000..bb1fb78 --- /dev/null +++ b/src/app/api/download-file/route.ts @@ -0,0 +1,64 @@ +import { NextRequest, NextResponse } from 'next/server' + +export async function GET(request: NextRequest) { + try { + const searchParams = request.nextUrl.searchParams + const fileUrl = searchParams.get('url') + const fileName = searchParams.get('filename') + + if (!fileUrl) { + return NextResponse.json( + { error: 'File URL is required' }, + { status: 400 } + ) + } + + // Проверяем, что URL принадлежит нашему S3 хранилищу + if (!fileUrl.includes('s3.twcstorage.ru/617774af-sfera/')) { + return NextResponse.json( + { error: 'Invalid file URL' }, + { status: 400 } + ) + } + + console.log('🔽 Проксируем скачивание файла:', fileUrl) + + // Загружаем файл с S3 + const response = await fetch(fileUrl, { + method: 'GET', + headers: { + 'User-Agent': 'Mozilla/5.0 (compatible; SferaApp/1.0)', + } + }) + + if (!response.ok) { + console.error('❌ Ошибка загрузки с S3:', response.status, response.statusText) + return NextResponse.json( + { error: `Failed to fetch file: ${response.status}` }, + { status: response.status } + ) + } + + // Получаем содержимое файла + const buffer = await response.arrayBuffer() + + console.log('✅ Файл успешно загружен с S3, размер:', buffer.byteLength) + + // Возвращаем файл с правильными заголовками для скачивания + return new NextResponse(buffer, { + headers: { + 'Content-Type': 'application/octet-stream', // Принудительное скачивание + 'Content-Disposition': `attachment; filename="${fileName || 'file'}"`, + 'Content-Length': buffer.byteLength.toString(), + 'Cache-Control': 'no-cache', + }, + }) + + } catch (error) { + console.error('❌ Ошибка в download-file API:', error) + return NextResponse.json( + { error: 'Failed to download file' }, + { status: 500 } + ) + } +} \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index bacc02d..ae0c3bb 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -192,14 +192,18 @@ backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.15); transition: all 0.3s ease; + outline: none; } - .glass-input:focus { + .glass-input:focus, + .glass-input:focus-visible { background: rgba(255, 255, 255, 0.12); - border: 1px solid rgba(168, 85, 247, 0.5); + border: 1px solid rgba(168, 85, 247, 0.6); box-shadow: - 0 0 0 3px rgba(168, 85, 247, 0.15), - 0 4px 16px rgba(147, 51, 234, 0.25); + 0 0 0 3px rgba(168, 85, 247, 0.2), + 0 4px 20px rgba(147, 51, 234, 0.3), + 0 0 20px rgba(168, 85, 247, 0.15); + outline: none; } .glass-button { diff --git a/src/components/messenger/messenger-chat.tsx b/src/components/messenger/messenger-chat.tsx index ea33060..d1fd178 100644 --- a/src/components/messenger/messenger-chat.tsx +++ b/src/components/messenger/messenger-chat.tsx @@ -360,7 +360,7 @@ export function MessengerChat({ counterparty }: MessengerChatProps) { )}
-
+
{/* Имя отправителя */} {!isCurrentUser && (
@@ -409,12 +409,12 @@ export function MessengerChat({ counterparty }: MessengerChatProps) { isCurrentUser={isCurrentUser} /> ) : msg.content ? ( -
-

{msg.content}

+

{msg.content}

) : null} @@ -434,28 +434,42 @@ export function MessengerChat({ counterparty }: MessengerChatProps) {
{/* Поле ввода сообщения */} -
-
-
- +
+
+