File size: 4,449 Bytes
a0d0340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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

import { useState } from "react";
import html2canvas from "html2canvas";

const voiceIdMap = {
  Rachel: "21m00Tcm4TlvDq8ikWAM",
  Adam: "pNInz6obpgDQGcFmaJgB",
  Bella: "EXAVITQu4vr4xnSDxMaL"
};

const apiKey = "sk_4e67c39c0e9cbc87462cd2643e1f4d1d9959d7d81203adc2";

export default function App() {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState("");
  const [style, setStyle] = useState("whatsapp");
  const [voice, setVoice] = useState("Rachel");

  const generateVoice = async (text) => {
    const voiceId = voiceIdMap[voice];
    const response = await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "xi-api-key": apiKey
      },
      body: JSON.stringify({
        text,
        model_id: "eleven_monolingual_v1",
        voice_settings: {
          stability: 0.5,
          similarity_boost: 0.75
        }
      })
    });
    const blob = await response.blob();
    const audioUrl = URL.createObjectURL(blob);
    const audio = new Audio(audioUrl);
    audio.play();
  };

  const addMessage = (sender) => {
    if (!input.trim()) return;
    const newMsg = { sender, text: input.trim() };
    setMessages([...messages, newMsg]);
    setInput("");
    generateVoice(newMsg.text);
  };

  const updateMessage = (index, newText) => {
    const newMsgs = [...messages];
    newMsgs[index].text = newText;
    setMessages(newMsgs);
  };

  const exportChatAsImage = () => {
    const chat = document.getElementById("chat-container");
    html2canvas(chat).then((canvas) => {
      const link = document.createElement("a");
      link.download = "chat_export.png";
      link.href = canvas.toDataURL();
      link.click();
    });
  };

  return (
    <div style={{ padding: 20, fontFamily: "sans-serif", background: "#f0f2f5", minHeight: "100vh" }}>
      <select value={style} onChange={(e) => setStyle(e.target.value)} style={{ margin: "0 auto", display: "block" }}>
        <option value="whatsapp">WhatsApp</option>
        <option value="imessage">iMessage</option>
        <option value="instagram">Instagram</option>
      </select>
      <select value={voice} onChange={(e) => setVoice(e.target.value)} style={{ margin: "10px auto", display: "block" }}>
        <option value="Rachel">Rachel</option>
        <option value="Adam">Adam</option>
        <option value="Bella">Bella</option>
      </select>

      <div id="chat-container" style={{
        margin: "10px auto",
        width: 360,
        background: style === "whatsapp" ? "#e5ddd5" : style === "imessage" ? "#d1e7ff" : "#fff0f5",
        padding: 16,
        borderRadius: 16,
        boxShadow: "0 0 10px rgba(0,0,0,0.1)",
        height: 520,
        overflowY: "auto"
      }}>
        {messages.map((msg, i) => (
          <div key={i} style={{
            display: "flex",
            justifyContent: msg.sender === "user" ? "flex-end" : "flex-start",
            marginBottom: 10
          }}>
            {msg.sender === "bot" && <img src="https://i.pravatar.cc/30?img=7" style={{ borderRadius: "50%", marginRight: 8 }} />}
            <input
              value={msg.text}
              onChange={(e) => updateMessage(i, e.target.value)}
              style={{
                padding: "8px 12px",
                borderRadius: 20,
                backgroundColor: msg.sender === "user" ? "#dcf8c6" : "#fff",
                maxWidth: "70%"
              }}
            />
            {msg.sender === "user" && <img src="https://i.pravatar.cc/30?img=3" style={{ borderRadius: "50%", marginLeft: 8 }} />}
          </div>
        ))}
      </div>

      <div style={{ width: 360, margin: "10px auto", display: "flex", gap: 8 }}>
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Type message..."
          style={{ flex: 1, padding: 8, borderRadius: 8, border: "1px solid #ccc" }}
        />
        <button onClick={() => addMessage("user")} style={{ padding: "8px 12px" }}>User</button>
        <button onClick={() => addMessage("bot")} style={{ padding: "8px 12px" }}>Bot</button>
      </div>

      <button onClick={exportChatAsImage} style={{ display: "block", margin: "10px auto", padding: "8px 14px", background: "#25d366", color: "#fff", border: "none", borderRadius: 8 }}>
        Export Chat as Image
      </button>
    </div>
  );
}