File size: 7,018 Bytes
f4ce85b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41cae12
f4ce85b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import { useState, useRef, useEffect } from 'react';
import { Send, Lock, MoreVertical, Phone, ArrowLeft, ShieldCheck } from 'lucide-react';
import { cryptoUtils } from './EncryptionHelper';

export default function ChatWindow({ chat, onBack, onSendMessage }) {
  const [messageText, setMessageText] = useState('');
  const [isEncrypting, setIsEncrypting] = useState(false);
  const messagesEndRef = useRef(null);
  const [localMessages, setLocalMessages] = useState(chat ? chat.messages : []);

  // Scroll to bottom on new message
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [localMessages]);

  useEffect(() => {
    if(chat) setLocalMessages(chat.messages);
  }, [chat]);

  if (!chat) {
    return (
      <div className="hidden md:flex flex-1 flex-col items-center justify-center bg-telegram-bg text-telegram-secondary">
        <div className="bg-telegram-sidebar p-6 rounded-full mb-4">
          <ShieldCheck size={48} className="text-telegram-accent" />
        </div>
        <h2 className="text-xl font-medium text-white mb-2">SecureChat</h2>
        <p className="text-sm max-w-md text-center">
          Select a chat to start messaging. <br/>
          Messages are protected with end-to-end encryption.
        </p>
      </div>
    );
  }

  const handleSend = async () => {
    if (!messageText.trim()) return;

    setIsEncrypting(true);
    
    // Simulate encryption delay
    setTimeout(async () => {
      // In a real app, we encrypt with the recipient's public key
      // Here we use a mock shared secret for the demo
      const encryptedContent = await cryptoUtils.encrypt(messageText, "secure-chat-demo-key");
      
      const newMessage = {
        id: Date.now(),
        text: messageText, // Storing plain text locally for UI demo, but conceptually this is encrypted payload
        encryptedPayload: encryptedContent,
        sender: 'me',
        timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
        status: 'sent'
      };

      setLocalMessages(prev => [...prev, newMessage]);
      onSendMessage(chat.id, newMessage);
      setMessageText('');
      setIsEncrypting(false);
    }, 600);
  };

  const handleKeyDown = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      handleSend();
    }
  };

  return (
    <div className="flex-1 flex flex-col bg-[#0e1621] relative h-full w-full">
      {/* Chat Header */}
      <div className="h-16 bg-telegram-sidebar flex items-center justify-between px-4 border-b border-gray-800 shrink-0">
        <div className="flex items-center gap-3">
          <button onClick={onBack} className="md:hidden text-telegram-secondary hover:text-white">
            <ArrowLeft size={24} />
          </button>
          <div className={`w-10 h-10 rounded-full flex items-center justify-center text-white font-bold ${chat.isGroup ? 'bg-purple-600' : 'bg-gradient-to-br from-blue-500 to-cyan-400'}`}>
            {chat.isGroup ? <span className="text-sm">Grp</span> : chat.name.charAt(0)}
          </div>
          <div>
            <h3 className="font-bold text-white text-sm md:text-base">{chat.name}</h3>
            <div className="flex items-center gap-1 text-xs text-telegram-accent">
              <Lock size={10} />
              <span>Encrypted</span>
            </div>
          </div>
        </div>
        <div className="flex items-center gap-4 text-telegram-secondary">
          <Phone size={20} className="hover:text-white cursor-pointer hidden sm:block" />
          <MoreVertical size={20} className="hover:text-white cursor-pointer" />
        </div>
      </div>

      {/* Messages Area */}
      <div className="flex-1 overflow-y-auto p-4 space-y-2 bg-telegram-bg bg-opacity-95">
        {/* Encryption Notice */}
        <div className="flex justify-center my-4">
          <div className="bg-telegram-message/50 text-telegram-secondary text-xs px-3 py-1.5 rounded-lg text-center max-w-xs border border-white/5">
            <Lock size={10} className="inline mr-1 mb-0.5" />
            Messages are end-to-end encrypted. No one outside of this chat, not even SecureChat, can read or listen to them.
          </div>
        </div>

        {localMessages.map((msg) => (
          <div 
            key={msg.id} 
            className={`flex ${msg.sender === 'me' ? 'justify-end' : 'justify-start'} animate-fade-in`}
          >
            <div 
              className={`message-bubble p-3 rounded-xl text-sm shadow-sm relative ${
                msg.sender === 'me' 
                  ? 'bg-telegram-outgoing text-white rounded-br-none' 
                  : 'bg-telegram-incoming text-white rounded-bl-none'
              }`}
            >
              <p className="leading-relaxed">{msg.text}</p>
              <div className={`flex items-center justify-end gap-1 mt-1 text-[10px] ${msg.sender === 'me' ? 'text-blue-200' : 'text-gray-400'}`}>
                <span>{msg.timestamp}</span>
                {msg.sender === 'me' && (
                  <span className={msg.status === 'read' ? 'text-blue-400' : 'text-gray-300'}>
                    {msg.status === 'read' ? '✓✓' : '✓'}
                  </span>
                )}
              </div>
            </div>
          </div>
        ))}
        <div ref={messagesEndRef} />
      </div>

      {/* Input Area */}
      <div className="p-3 bg-telegram-sidebar border-t border-gray-800 shrink-0">
        <div className="flex items-end gap-2 max-w-4xl mx-auto">
          <button className="p-2 text-telegram-secondary hover:text-white transition-colors">
            <MoreVertical size={24} className="rotate-90" />
          </button>
          <div className="flex-1 bg-telegram-bg rounded-2xl flex items-center border border-transparent focus-within:border-telegram-accent/50 transition-colors">
            <textarea
              value={messageText}
              onChange={(e) => setMessageText(e.target.value)}
              onKeyDown={handleKeyDown}
              placeholder="Message"
              className="w-full bg-transparent text-white px-4 py-3 min-h-[44px] max-h-32 focus:outline-none resize-none text-sm"
              rows={1}
            />
          </div>
          <button 
            onClick={handleSend}
            disabled={!messageText.trim() || isEncrypting}
            className={`p-3 rounded-full transition-all duration-200 flex items-center justify-center ${
              messageText.trim() 
                ? 'bg-telegram-accent text-white hover:bg-blue-600 shadow-lg shadow-blue-900/20' 
                : 'bg-telegram-bg text-telegram-secondary'
            }`}
          >
            {isEncrypting ? (
              <div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
            ) : (
              <Send size={20} className={messageText.trim() ? 'ml-0.5' : ''} />
            )}
          </button>
        </div>
      </div>
    </div>
  );
}