aigorithm commited on
Commit
a0d0340
·
verified ·
1 Parent(s): bb0417a

Upload 4 files

Browse files
Files changed (4) hide show
  1. package.json +10 -0
  2. public/index.html +12 -0
  3. src/App.js +127 -0
  4. src/index.js +6 -0
package.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "chat-animator",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "dependencies": {
6
+ "react": "^18.2.0",
7
+ "react-dom": "^18.2.0",
8
+ "html2canvas": "^1.4.1"
9
+ }
10
+ }
public/index.html ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Chat Animator</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/index.js"></script>
11
+ </body>
12
+ </html>
src/App.js ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import { useState } from "react";
3
+ import html2canvas from "html2canvas";
4
+
5
+ const voiceIdMap = {
6
+ Rachel: "21m00Tcm4TlvDq8ikWAM",
7
+ Adam: "pNInz6obpgDQGcFmaJgB",
8
+ Bella: "EXAVITQu4vr4xnSDxMaL"
9
+ };
10
+
11
+ const apiKey = "sk_4e67c39c0e9cbc87462cd2643e1f4d1d9959d7d81203adc2";
12
+
13
+ export default function App() {
14
+ const [messages, setMessages] = useState([]);
15
+ const [input, setInput] = useState("");
16
+ const [style, setStyle] = useState("whatsapp");
17
+ const [voice, setVoice] = useState("Rachel");
18
+
19
+ const generateVoice = async (text) => {
20
+ const voiceId = voiceIdMap[voice];
21
+ const response = await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`, {
22
+ method: "POST",
23
+ headers: {
24
+ "Content-Type": "application/json",
25
+ "xi-api-key": apiKey
26
+ },
27
+ body: JSON.stringify({
28
+ text,
29
+ model_id: "eleven_monolingual_v1",
30
+ voice_settings: {
31
+ stability: 0.5,
32
+ similarity_boost: 0.75
33
+ }
34
+ })
35
+ });
36
+ const blob = await response.blob();
37
+ const audioUrl = URL.createObjectURL(blob);
38
+ const audio = new Audio(audioUrl);
39
+ audio.play();
40
+ };
41
+
42
+ const addMessage = (sender) => {
43
+ if (!input.trim()) return;
44
+ const newMsg = { sender, text: input.trim() };
45
+ setMessages([...messages, newMsg]);
46
+ setInput("");
47
+ generateVoice(newMsg.text);
48
+ };
49
+
50
+ const updateMessage = (index, newText) => {
51
+ const newMsgs = [...messages];
52
+ newMsgs[index].text = newText;
53
+ setMessages(newMsgs);
54
+ };
55
+
56
+ const exportChatAsImage = () => {
57
+ const chat = document.getElementById("chat-container");
58
+ html2canvas(chat).then((canvas) => {
59
+ const link = document.createElement("a");
60
+ link.download = "chat_export.png";
61
+ link.href = canvas.toDataURL();
62
+ link.click();
63
+ });
64
+ };
65
+
66
+ return (
67
+ <div style={{ padding: 20, fontFamily: "sans-serif", background: "#f0f2f5", minHeight: "100vh" }}>
68
+ <select value={style} onChange={(e) => setStyle(e.target.value)} style={{ margin: "0 auto", display: "block" }}>
69
+ <option value="whatsapp">WhatsApp</option>
70
+ <option value="imessage">iMessage</option>
71
+ <option value="instagram">Instagram</option>
72
+ </select>
73
+ <select value={voice} onChange={(e) => setVoice(e.target.value)} style={{ margin: "10px auto", display: "block" }}>
74
+ <option value="Rachel">Rachel</option>
75
+ <option value="Adam">Adam</option>
76
+ <option value="Bella">Bella</option>
77
+ </select>
78
+
79
+ <div id="chat-container" style={{
80
+ margin: "10px auto",
81
+ width: 360,
82
+ background: style === "whatsapp" ? "#e5ddd5" : style === "imessage" ? "#d1e7ff" : "#fff0f5",
83
+ padding: 16,
84
+ borderRadius: 16,
85
+ boxShadow: "0 0 10px rgba(0,0,0,0.1)",
86
+ height: 520,
87
+ overflowY: "auto"
88
+ }}>
89
+ {messages.map((msg, i) => (
90
+ <div key={i} style={{
91
+ display: "flex",
92
+ justifyContent: msg.sender === "user" ? "flex-end" : "flex-start",
93
+ marginBottom: 10
94
+ }}>
95
+ {msg.sender === "bot" && <img src="https://i.pravatar.cc/30?img=7" style={{ borderRadius: "50%", marginRight: 8 }} />}
96
+ <input
97
+ value={msg.text}
98
+ onChange={(e) => updateMessage(i, e.target.value)}
99
+ style={{
100
+ padding: "8px 12px",
101
+ borderRadius: 20,
102
+ backgroundColor: msg.sender === "user" ? "#dcf8c6" : "#fff",
103
+ maxWidth: "70%"
104
+ }}
105
+ />
106
+ {msg.sender === "user" && <img src="https://i.pravatar.cc/30?img=3" style={{ borderRadius: "50%", marginLeft: 8 }} />}
107
+ </div>
108
+ ))}
109
+ </div>
110
+
111
+ <div style={{ width: 360, margin: "10px auto", display: "flex", gap: 8 }}>
112
+ <input
113
+ value={input}
114
+ onChange={(e) => setInput(e.target.value)}
115
+ placeholder="Type message..."
116
+ style={{ flex: 1, padding: 8, borderRadius: 8, border: "1px solid #ccc" }}
117
+ />
118
+ <button onClick={() => addMessage("user")} style={{ padding: "8px 12px" }}>User</button>
119
+ <button onClick={() => addMessage("bot")} style={{ padding: "8px 12px" }}>Bot</button>
120
+ </div>
121
+
122
+ <button onClick={exportChatAsImage} style={{ display: "block", margin: "10px auto", padding: "8px 14px", background: "#25d366", color: "#fff", border: "none", borderRadius: 8 }}>
123
+ Export Chat as Image
124
+ </button>
125
+ </div>
126
+ );
127
+ }
src/index.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App.js";
4
+
5
+ const root = ReactDOM.createRoot(document.getElementById("root"));
6
+ root.render(<App />);