aigorithm commited on
Commit
7d41d24
·
verified ·
1 Parent(s): 2409344

Upload 2 files

Browse files
Files changed (2) hide show
  1. index.html +22 -18
  2. main.js +84 -0
index.html CHANGED
@@ -1,19 +1,23 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
19
  </html>
 
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7
+ <title>Chat Animator</title>
8
+ <style>
9
+ body { font-family: sans-serif; margin: 0; background: #f0f2f5; }
10
+ .app { padding: 20px; max-width: 400px; margin: auto; }
11
+ .bubble { border-radius: 20px; padding: 10px; margin: 8px 0; display: inline-block; max-width: 70%; }
12
+ .user { background: #dcf8c6; align-self: flex-end; }
13
+ .bot { background: #fff; align-self: flex-start; }
14
+ .message { display: flex; align-items: center; gap: 8px; }
15
+ .avatar { border-radius: 50%; width: 30px; height: 30px; }
16
+ select, input, button { margin: 6px 0; padding: 8px; }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <div id="root"></div>
21
+ <script type="module" src="main.js"></script>
22
+ </body>
23
  </html>
main.js ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import { createElement as h, useState } from "https://esm.sh/react";
3
+ import { createRoot } from "https://esm.sh/react-dom/client";
4
+ import html2canvas from "https://esm.sh/html2canvas";
5
+
6
+ const App = () => {
7
+ const [messages, setMessages] = useState([]);
8
+ const [input, setInput] = useState("");
9
+ const [style, setStyle] = useState("whatsapp");
10
+ const [voice, setVoice] = useState("Rachel");
11
+
12
+ const voiceIdMap = {
13
+ Rachel: "21m00Tcm4TlvDq8ikWAM",
14
+ Adam: "pNInz6obpgDQGcFmaJgB",
15
+ Bella: "EXAVITQu4vr4xnSDxMaL"
16
+ };
17
+ const apiKey = "sk_4e67c39c0e9cbc87462cd2643e1f4d1d9959d7d81203adc2";
18
+
19
+ const generateVoice = async (text) => {
20
+ const response = await fetch("https://api.elevenlabs.io/v1/text-to-speech/" + voiceIdMap[voice], {
21
+ method: "POST",
22
+ headers: { "Content-Type": "application/json", "xi-api-key": apiKey },
23
+ body: JSON.stringify({
24
+ text,
25
+ model_id: "eleven_monolingual_v1",
26
+ voice_settings: { stability: 0.5, similarity_boost: 0.75 }
27
+ })
28
+ });
29
+ const blob = await response.blob();
30
+ new Audio(URL.createObjectURL(blob)).play();
31
+ };
32
+
33
+ const addMessage = (sender) => {
34
+ if (!input.trim()) return;
35
+ const msg = { sender, text: input };
36
+ setMessages([...messages, msg]);
37
+ setInput("");
38
+ generateVoice(input);
39
+ };
40
+
41
+ const exportImage = () => {
42
+ html2canvas(document.getElementById("chat")).then((canvas) => {
43
+ const link = document.createElement("a");
44
+ link.href = canvas.toDataURL();
45
+ link.download = "chat_export.png";
46
+ link.click();
47
+ });
48
+ };
49
+
50
+ return h("div", { className: "app" }, [
51
+ h("select", { value: style, onChange: (e) => setStyle(e.target.value) }, [
52
+ h("option", { value: "whatsapp" }, "WhatsApp"),
53
+ h("option", { value: "imessage" }, "iMessage"),
54
+ h("option", { value: "instagram" }, "Instagram")
55
+ ]),
56
+ h("select", { value: voice, onChange: (e) => setVoice(e.target.value) }, [
57
+ h("option", { value: "Rachel" }, "Rachel"),
58
+ h("option", { value: "Adam" }, "Adam"),
59
+ h("option", { value: "Bella" }, "Bella")
60
+ ]),
61
+ h("div", { id: "chat", style: { display: "flex", flexDirection: "column", gap: "8px", marginTop: "10px" } },
62
+ messages.map((msg, i) =>
63
+ h("div", { key: i, className: "message", style: { justifyContent: msg.sender === "user" ? "flex-end" : "flex-start" } }, [
64
+ msg.sender === "bot" && h("img", { src: "https://i.pravatar.cc/30?img=7", className: "avatar" }),
65
+ h("div", { className: `bubble ${msg.sender}` }, msg.text),
66
+ msg.sender === "user" && h("img", { src: "https://i.pravatar.cc/30?img=3", className: "avatar" })
67
+ ])
68
+ )
69
+ ),
70
+ h("input", {
71
+ value: input,
72
+ onChange: (e) => setInput(e.target.value),
73
+ placeholder: "Type message...",
74
+ style: { width: "100%", marginTop: "10px" }
75
+ }),
76
+ h("div", { style: { display: "flex", gap: "8px" } }, [
77
+ h("button", { onClick: () => addMessage("user") }, "User"),
78
+ h("button", { onClick: () => addMessage("bot") }, "Bot"),
79
+ h("button", { onClick: exportImage }, "Export Image")
80
+ ])
81
+ ]);
82
+ };
83
+
84
+ createRoot(document.getElementById("root")).render(h(App));