File size: 4,102 Bytes
8b1e853
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a6626cb
8b1e853
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import React, { useState, useEffect, useCallback } from 'react';
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { establishPeerConnection } from '../webrtc';
import { clearMessages } from '../api'


interface ChatProps {
  token: string;
  onLogout: () => void;
}

type ObjectMessage = {
  id?: number;
  content: string;
};

type Message = string | ObjectMessage;

const Chat: React.FC<ChatProps> = ({ token, onLogout }) => {
  const [message, setMessage] = useState('');
  const [messages, setMessages] = useState<Message[]>([]);
  const [peerConnection, setPeerConnection] = useState<RTCPeerConnection | null>(null);
  const [dataChannel, setDataChannel] = useState<RTCDataChannel | null>(null);

  const setupPeerConnection = useCallback(async () => {
    try {
      const { pc, dc } = await establishPeerConnection(token);
      setPeerConnection(pc);
      setDataChannel(dc);
      peerConnection;

      dc.onmessage = (event) => {
        setMessages((prevMessages) => {
          let lastMessage = prevMessages[prevMessages.length - 1];
          if (!lastMessage || typeof lastMessage == 'string') {
            let aiMessage: Message = { content: event.data }
            return [...prevMessages, aiMessage]; 
          } else {
            const updatedMessage = {...lastMessage}
            updatedMessage.content += event.data;
            return [...prevMessages.slice(0, -1), updatedMessage];
          }
        });
      
      };
    } catch (error) {
      console.error('Failed to establish peer connection:', error);
      onLogout(); // Logout if connection fails
    }
  }, [token, onLogout]);

  useEffect(() => {
    setupPeerConnection();
  }, [setupPeerConnection]);

  const sendMessage = () => {
    if (dataChannel && dataChannel.readyState === 'open') {
      dataChannel.send(message);
      setMessages((prevMessages) => [...prevMessages, `You: ${message}`]);
      setMessage('');
    } else {
      console.error('Data channel is not open');
    }
  };

  const renderMessage = (message: any, index: number) => {
    const dateOptions: Intl.DateTimeFormatOptions = {
      hour: "2-digit",
      minute: "2-digit",
    };
    const date = new Date().toLocaleTimeString(
      undefined,
      dateOptions
    );
    if (typeof message === 'string') {
      return (
        <div key={index} className="flex items-start space-x-2">
          <div className="flex-1 border rounded-lg p-2">
            <div dangerouslySetInnerHTML={{ __html: message.replace(/\n/g, '<br/>') }} />
          </div>
          <small className="text-xs text-gray-500">{date}</small>
        </div>
      );
    } else {
      return (
        <div key={index} className="flex items-start space-x-2">
          <div className="flex-1 border rounded-lg p-2">
            <div dangerouslySetInnerHTML={{ __html: message.content.replace(/\n/g, '<br/>') }} />
          </div>
          <small className="text-xs text-gray-500">{date}</small>
        </div>
      );
    }
  };

  return (

    <div className="min-h-screen bg-gray-100 dark:bg-gray-900 flex flex-col">
      <div className="flex-1 overflow-auto p-6">
        <div className="space-y-4">
          {messages.map((message, index) => renderMessage(message, index))}
        </div>
      </div>
      <div className="border-t p-4 bg-white dark:bg-gray-800">
        <div className="flex items-center space-x-2">
          <Input
            autoFocus
            className="flex-1"
            id="message-input"
            placeholder="Type a message"
            value={message}
            onChange={(e) => setMessage(e.target.value)}
            onKeyUp={(e) => {
              if (e.key === "Enter") {
                sendMessage();
              }
            }}
          />
          <Button onClick={sendMessage} type="submit" disabled={!message}>
            Send
          </Button>
          <Button onClick={() => clearMessages(token)} type="submit">
            Reset
          </Button>
        </div>
      </div>
    </div>

  );
};

export default Chat;