Дизайн

This commit is contained in:
Халимов Рустам
2026-04-02 14:57:32 +03:00
parent 9df7d7aaf1
commit a42007df2d
6 changed files with 82 additions and 56 deletions

View File

@@ -381,7 +381,7 @@ export default function ChatPage() {
{/* Selected Chat View (Main Area) */}
<div
className={`${activeChat ? 'block' : 'hidden lg:block'} flex-1 h-full min-w-0 bg-surface-container-lowest m-4 rounded-3xl overflow-hidden relative group slide-on-ice`}
className={`${activeChat ? 'block' : 'hidden lg:block'} flex-1 h-full min-w-0 bg-surface-container-lowest relative group slide-on-ice`}
>
<ChatView onStartCall={handleStartCall} onStartGroupCall={handleStartGroupCall} />
</div>
@@ -394,7 +394,7 @@ export default function ChatPage() {
</div>
{/* Right side placeholder / Profile detail */}
<div className="hidden lg:flex flex-1 items-center justify-center bg-surface-base m-4 rounded-3xl overflow-hidden border border-white/5 relative slide-on-ice">
<div className="hidden lg:flex flex-1 items-center justify-center bg-surface-base h-full relative slide-on-ice">
<div className="flex flex-col items-center gap-6 max-w-sm text-center">
<div className="w-24 h-24 rounded-3xl bg-primary/10 flex items-center justify-center text-primary shadow-inner">
<Users size={48} className="knot-logo-spin opacity-50" />

View File

@@ -17,7 +17,8 @@ import {
Forward,
Bookmark,
ArrowLeft,
MessageSquare,
MessagesSquare,
Pencil,
} from 'lucide-react';
import { useChatStore } from '../../application/chatStore';
import { useAuthStore } from '../../../auth/application/authStore';
@@ -25,7 +26,7 @@ import { ChatApi } from '../../infrastructure/chatApi';
import { getSocket } from '../../../../core/infrastructure/socket';
import { isChatMuted, toggleMuteChat } from '../../../../core/utils/sounds';
import { useLang } from '../../../../core/infrastructure/i18n';
import { formatLastSeen } from '../../../../core/utils/utils';
import { formatLastSeen, getInitials, generateAvatarColor } from '../../../../core/utils/utils';
import type { UserBasic, Message } from '../../../../core/domain/types';
import MessageBubble from './MessageBubble';
import MessageInput from './MessageInput';
@@ -391,43 +392,72 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
if (!activeChat || !chat) {
return (
<div className="flex-1 h-full flex items-center justify-center bg-surface-secondary/50 rounded-[2rem] overflow-hidden border border-white/5 shadow-2xl relative z-0 backdrop-blur-3xl group">
<div className="text-center relative z-10 w-full max-w-sm px-6 mx-auto">
<section className="flex-1 h-full flex flex-col items-center justify-center bg-[#010101] relative overflow-hidden">
{/* Background Knot Texture - Correct Horizontal Unclosed Infinity SVG */}
<div className="absolute inset-0 opacity-[0.04] pointer-events-none flex items-center justify-center">
<svg
width="1000"
height="500"
viewBox="0 0 600 300"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="w-[120vw] h-auto text-white select-none"
>
{/* Left part of the infinity loop */}
<path
d="M300 150 C 240 230 150 230 150 150 C 150 70 240 70 300 150"
stroke="currentColor"
strokeWidth="45"
strokeLinecap="round"
/>
{/* Right part of the infinity loop with a small gap at the crossing */}
<path
d="M315 170 C 375 250 465 250 465 170 C 465 90 375 90 315 170"
stroke="currentColor"
strokeWidth="45"
strokeLinecap="round"
transform="translate(-15, -20)"
/>
</svg>
</div>
{/* Chat Empty State View */}
<div className="flex-1 flex flex-col items-center justify-center z-10 p-12 text-center relative">
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
className="w-24 h-24 mx-auto mb-6 rounded-full bg-surface-hover flex items-center justify-center border border-border/40 backdrop-blur-md relative"
transition={{ duration: 0.8, ease: [0.16, 1, 0.3, 1] }}
className="w-24 h-24 mb-6 rounded-full bg-[#1c1c1c] flex items-center justify-center shadow-[0_0_80px_rgba(48,150,229,0.15)] border border-white/5"
>
<MessageSquare className="w-10 h-10 text-zinc-500 transform hover:scale-105 transition-transform" />
<span className="material-symbols-outlined text-[#3096e5] text-5xl select-none" style={{ fontVariationSettings: "'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 48" }}>
forum
</span>
</motion.div>
<motion.h2
<h2 className="text-3xl font-black text-[#e5e2e1] tracking-tight mb-2 leading-tight">
{t('selectChatTitle')}
</h2>
<p className="text-sm font-medium text-[#c1c6d7] max-w-sm leading-relaxed opacity-40 px-4">
{t('selectChatSubtext')}
</p>
<motion.button
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.6, delay: 0.1, ease: [0.16, 1, 0.3, 1] }}
className="text-2xl font-semibold text-white mb-2 tracking-tight"
transition={{ delay: 0.2 }}
onClick={() => window.dispatchEvent(new CustomEvent('OPEN_NEW_CHAT'))}
className="mt-10 px-9 py-3.5 bg-gradient-to-tr from-[#3096e5] to-[#9acbff] text-black font-extrabold text-base rounded-full shadow-[0_15px_40px_rgba(48,150,229,0.2)] hover:scale-105 active:scale-95 transition-all flex items-center gap-2.5"
>
Knot Messenger
</motion.h2>
<motion.p
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.6, delay: 0.2, ease: [0.16, 1, 0.3, 1] }}
className="text-sm text-zinc-400 bg-surface-hover backdrop-blur-lg py-2 px-4 rounded-full inline-flex border border-border/50"
>
{t('selectChat')}
</motion.p>
<span className="material-symbols-outlined text-black font-bold text-xl">edit</span>
{t('newMessage')}
</motion.button>
</div>
</div>
</section>
);
}
const initials = (chatName || '??')
.split(' ')
.map((w: string) => w[0])
.join('')
.slice(0, 2)
.toUpperCase();
const initials = getInitials(chatName || '??');
const handleToggleSelect = (msgId: string) => {
const newMap = new Set(selectedMessages);
@@ -445,6 +475,8 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
setSelectedMessages(new Set([msgId]));
};
const handleForward = (targetChatId: string) => {
const socket = getSocket();
if (!socket || !activeChat) return;

View File

@@ -885,7 +885,7 @@ export default function MessageInput({ chatId }: MessageInputProps) {
onClick={() => handleSend()}
onContextMenu={(e) => { e.preventDefault(); setScheduleStep('presets'); setShowSchedule(true); }}
disabled={isSending}
className="w-11 h-11 flex items-center justify-center rounded-2xl bg-primary text-white hover:brightness-110 active:scale-95 transition-all shadow-[0_4px_15px_rgba(48,150,229,0.3)] disabled:opacity-50"
className="w-11 h-11 flex items-center justify-center rounded-2xl bg-primary text-black hover:brightness-110 active:scale-95 transition-all shadow-[0_4px_15px_rgba(48,150,229,0.3)] disabled:opacity-50"
>
<Send size={20} strokeWidth={2.5} className="translate-x-[1px]" />
</button>
@@ -985,7 +985,7 @@ export default function MessageInput({ chatId }: MessageInputProps) {
) : (
<button
onClick={startRecording}
className="w-11 h-11 flex items-center justify-center rounded-2xl bg-primary text-white hover:brightness-110 active:scale-95 transition-all shadow-[0_4px_15px_rgba(48,150,229,0.3)]"
className="w-11 h-11 flex items-center justify-center rounded-2xl bg-primary text-black hover:brightness-110 active:scale-95 transition-all shadow-[0_4px_15px_rgba(48,150,229,0.3)]"
>
<Mic size={22} strokeWidth={1.5} />
</button>