spdgamerz commited on
Commit
879510a
·
verified ·
1 Parent(s): af9cc97

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +1362 -19
  3. prompts.txt +0 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Mesagging App
3
- emoji: 📚
4
- colorFrom: purple
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: mesagging-app
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1362 @@
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
+ <!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>NeonChat - 3D Messaging App</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
13
+
14
+ :root {
15
+ --primary: #6c5ce7;
16
+ --secondary: #a29bfe;
17
+ --dark: #2d3436;
18
+ --light: #f5f6fa;
19
+ --accent: #fd79a8;
20
+ }
21
+
22
+ body {
23
+ font-family: 'Poppins', sans-serif;
24
+ background-color: #0f0f1a;
25
+ color: var(--light);
26
+ overflow-x: hidden;
27
+ }
28
+
29
+ .message-bubble {
30
+ transition: all 0.3s ease;
31
+ transform-origin: left bottom;
32
+ }
33
+
34
+ .message-bubble:hover {
35
+ transform: scale(1.02) translateY(-2px);
36
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
37
+ }
38
+
39
+ .user-card:hover {
40
+ transform: translateY(-5px) scale(1.02);
41
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
42
+ }
43
+
44
+ .neon-text {
45
+ text-shadow: 0 0 5px var(--primary), 0 0 10px var(--primary), 0 0 15px var(--primary);
46
+ }
47
+
48
+ .neon-border {
49
+ box-shadow: 0 0 5px var(--primary), 0 0 10px var(--primary), inset 0 0 5px var(--primary);
50
+ }
51
+
52
+ .typing-indicator span {
53
+ display: inline-block;
54
+ width: 8px;
55
+ height: 8px;
56
+ background-color: var(--secondary);
57
+ border-radius: 50%;
58
+ margin: 0 2px;
59
+ animation: bounce 1.5s infinite ease-in-out;
60
+ }
61
+
62
+ .typing-indicator span:nth-child(2) {
63
+ animation-delay: 0.2s;
64
+ }
65
+
66
+ .typing-indicator span:nth-child(3) {
67
+ animation-delay: 0.4s;
68
+ }
69
+
70
+ @keyframes bounce {
71
+ 0%, 100% { transform: translateY(0); }
72
+ 50% { transform: translateY(-5px); }
73
+ }
74
+
75
+ .floating {
76
+ animation: float 6s ease-in-out infinite;
77
+ }
78
+
79
+ @keyframes float {
80
+ 0%, 100% { transform: translateY(0); }
81
+ 50% { transform: translateY(-20px); }
82
+ }
83
+
84
+ .pulse {
85
+ animation: pulse 2s infinite;
86
+ }
87
+
88
+ @keyframes pulse {
89
+ 0% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0.7); }
90
+ 70% { box-shadow: 0 0 0 10px rgba(108, 92, 231, 0); }
91
+ 100% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0); }
92
+ }
93
+
94
+ .message-input:focus {
95
+ box-shadow: 0 0 10px var(--primary);
96
+ }
97
+
98
+ /* 3D Message Effect */
99
+ .message-3d {
100
+ transform-style: preserve-3d;
101
+ perspective: 1000px;
102
+ }
103
+
104
+ .message-3d:hover {
105
+ transform: rotateY(10deg) rotateX(5deg);
106
+ }
107
+
108
+ /* Responsive adjustments */
109
+ @media (max-width: 768px) {
110
+ .sidebar {
111
+ transform: translateX(-100%);
112
+ position: absolute;
113
+ z-index: 10;
114
+ width: 80%;
115
+ }
116
+
117
+ .sidebar.active {
118
+ transform: translateX(0);
119
+ }
120
+
121
+ .main-content {
122
+ margin-left: 0 !important;
123
+ }
124
+
125
+ .menu-toggle {
126
+ display: block !important;
127
+ }
128
+ }
129
+
130
+ /* Custom scrollbar */
131
+ ::-webkit-scrollbar {
132
+ width: 8px;
133
+ }
134
+
135
+ ::-webkit-scrollbar-track {
136
+ background: rgba(255, 255, 255, 0.05);
137
+ }
138
+
139
+ ::-webkit-scrollbar-thumb {
140
+ background: var(--primary);
141
+ border-radius: 4px;
142
+ }
143
+
144
+ ::-webkit-scrollbar-thumb:hover {
145
+ background: var(--secondary);
146
+ }
147
+
148
+ /* 3D Background */
149
+ #threejs-background {
150
+ position: fixed;
151
+ top: 0;
152
+ left: 0;
153
+ width: 100%;
154
+ height: 100%;
155
+ z-index: -1;
156
+ opacity: 0.2;
157
+ }
158
+ </style>
159
+ </head>
160
+ <body>
161
+ <!-- 3D Background -->
162
+ <div id="threejs-background"></div>
163
+
164
+ <!-- App Container -->
165
+ <div class="flex h-screen overflow-hidden">
166
+ <!-- Sidebar Toggle Button (Mobile) -->
167
+ <button id="menuToggle" class="menu-toggle fixed top-4 left-4 z-50 bg-purple-600 text-white p-3 rounded-full shadow-lg hover:bg-purple-700 transition-all md:hidden">
168
+ <i class="fas fa-bars"></i>
169
+ </button>
170
+
171
+ <!-- Sidebar -->
172
+ <div id="sidebar" class="sidebar w-80 bg-gray-900 border-r border-gray-800 flex flex-col transition-all duration-300 ease-in-out">
173
+ <!-- App Header -->
174
+ <div class="p-4 border-b border-gray-800 flex items-center justify-between">
175
+ <div class="flex items-center space-x-3">
176
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white font-bold text-xl pulse">
177
+ N
178
+ </div>
179
+ <h1 class="text-xl font-bold neon-text">NeonChat</h1>
180
+ </div>
181
+ <button id="newChatBtn" class="w-8 h-8 rounded-full bg-purple-600 text-white flex items-center justify-center hover:bg-purple-700 transition-all">
182
+ <i class="fas fa-plus"></i>
183
+ </button>
184
+ </div>
185
+
186
+ <!-- Search Bar -->
187
+ <div class="p-4 border-b border-gray-800">
188
+ <div class="relative">
189
+ <input type="text" placeholder="Search conversations..." class="w-full bg-gray-800 text-white px-4 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-600">
190
+ <i class="fas fa-search absolute right-3 top-3 text-gray-500"></i>
191
+ </div>
192
+ </div>
193
+
194
+ <!-- Conversations List -->
195
+ <div class="flex-1 overflow-y-auto">
196
+ <div class="p-2">
197
+ <h3 class="text-xs uppercase text-gray-500 font-semibold mb-2 px-2">Recent Chats</h3>
198
+ <div id="conversationsList" class="space-y-1">
199
+ <!-- Conversations will be loaded here -->
200
+ </div>
201
+ </div>
202
+
203
+ <div class="p-2">
204
+ <h3 class="text-xs uppercase text-gray-500 font-semibold mb-2 px-2">Contacts</h3>
205
+ <div id="contactsList" class="space-y-1">
206
+ <!-- Contacts will be loaded here -->
207
+ </div>
208
+ </div>
209
+ </div>
210
+
211
+ <!-- User Profile -->
212
+ <div class="p-4 border-t border-gray-800 flex items-center space-x-3">
213
+ <div id="userAvatar" class="w-10 h-10 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white font-bold cursor-pointer hover:opacity-80 transition-all">
214
+ <i class="fas fa-user"></i>
215
+ </div>
216
+ <div class="flex-1">
217
+ <div id="userName" class="font-medium">Guest User</div>
218
+ <div class="text-xs text-gray-500">Online</div>
219
+ </div>
220
+ <button id="settingsBtn" class="w-8 h-8 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
221
+ <i class="fas fa-cog"></i>
222
+ </button>
223
+ </div>
224
+ </div>
225
+
226
+ <!-- Main Content -->
227
+ <div id="mainContent" class="main-content flex-1 flex flex-col bg-gray-900 ml-0 md:ml-80 transition-all duration-300 ease-in-out">
228
+ <!-- Chat Header -->
229
+ <div class="p-4 border-b border-gray-800 flex items-center justify-between">
230
+ <div class="flex items-center space-x-3">
231
+ <div id="currentChatAvatar" class="w-10 h-10 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white font-bold">
232
+ <i class="fas fa-user-friends"></i>
233
+ </div>
234
+ <div>
235
+ <h2 id="currentChatName" class="font-bold">Select a conversation</h2>
236
+ <div id="typingIndicator" class="typing-indicator text-xs text-gray-500 hidden">
237
+ <span></span>
238
+ <span></span>
239
+ <span></span>
240
+ </div>
241
+ <div id="onlineStatus" class="text-xs text-gray-500 hidden">Online</div>
242
+ </div>
243
+ </div>
244
+ <div class="flex items-center space-x-2">
245
+ <button class="w-8 h-8 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
246
+ <i class="fas fa-phone"></i>
247
+ </button>
248
+ <button class="w-8 h-8 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
249
+ <i class="fas fa-video"></i>
250
+ </button>
251
+ <button id="chatInfoBtn" class="w-8 h-8 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
252
+ <i class="fas fa-info-circle"></i>
253
+ </button>
254
+ </div>
255
+ </div>
256
+
257
+ <!-- Messages Area -->
258
+ <div id="messagesContainer" class="flex-1 overflow-y-auto p-4 space-y-4">
259
+ <div class="text-center py-10 text-gray-500">
260
+ <div class="w-16 h-16 mx-auto mb-4 rounded-full bg-gray-800 flex items-center justify-center text-gray-600">
261
+ <i class="fas fa-comments text-2xl"></i>
262
+ </div>
263
+ <h3 class="text-lg font-medium">No conversation selected</h3>
264
+ <p class="text-sm">Select a conversation or start a new one</p>
265
+ </div>
266
+ </div>
267
+
268
+ <!-- Message Input -->
269
+ <div class="p-4 border-t border-gray-800">
270
+ <div class="flex items-center space-x-2">
271
+ <button class="w-10 h-10 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
272
+ <i class="fas fa-paperclip"></i>
273
+ </button>
274
+ <div class="flex-1 relative">
275
+ <input id="messageInput" type="text" placeholder="Type a message..." class="w-full bg-gray-800 text-white px-4 py-3 rounded-full focus:outline-none focus:ring-2 focus:ring-purple-600 message-input">
276
+ <button class="absolute right-3 top-3 text-gray-500 hover:text-purple-500 transition-all">
277
+ <i class="far fa-smile"></i>
278
+ </button>
279
+ </div>
280
+ <button id="sendMessageBtn" class="w-10 h-10 rounded-full bg-purple-600 text-white flex items-center justify-center hover:bg-purple-700 transition-all">
281
+ <i class="fas fa-paper-plane"></i>
282
+ </button>
283
+ </div>
284
+ </div>
285
+ </div>
286
+
287
+ <!-- Chat Info Panel -->
288
+ <div id="chatInfoPanel" class="hidden md:block w-80 bg-gray-900 border-l border-gray-800 overflow-y-auto">
289
+ <div class="p-4 border-b border-gray-800 flex items-center justify-between">
290
+ <h3 class="font-bold">Chat Info</h3>
291
+ <button id="closeChatInfoBtn" class="w-8 h-8 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
292
+ <i class="fas fa-times"></i>
293
+ </button>
294
+ </div>
295
+
296
+ <div class="p-4">
297
+ <div class="flex flex-col items-center text-center mb-6">
298
+ <div id="infoChatAvatar" class="w-20 h-20 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white text-3xl font-bold mb-3">
299
+ <i class="fas fa-user-friends"></i>
300
+ </div>
301
+ <h3 id="infoChatName" class="text-xl font-bold">Group Chat</h3>
302
+ <p id="infoChatStatus" class="text-sm text-gray-500">Online</p>
303
+ </div>
304
+
305
+ <div class="mb-6">
306
+ <h4 class="text-sm font-semibold text-gray-400 mb-2">MEMBERS</h4>
307
+ <div id="chatMembersList" class="space-y-2">
308
+ <!-- Members will be listed here -->
309
+ </div>
310
+ </div>
311
+
312
+ <div class="mb-6">
313
+ <h4 class="text-sm font-semibold text-gray-400 mb-2">MEDIA, FILES & LINKS</h4>
314
+ <div class="grid grid-cols-3 gap-2">
315
+ <div class="bg-gray-800 rounded-lg aspect-square flex items-center justify-center text-gray-400">
316
+ <i class="fas fa-image"></i>
317
+ </div>
318
+ <div class="bg-gray-800 rounded-lg aspect-square flex items-center justify-center text-gray-400">
319
+ <i class="fas fa-file"></i>
320
+ </div>
321
+ <div class="bg-gray-800 rounded-lg aspect-square flex items-center justify-center text-gray-400">
322
+ <i class="fas fa-link"></i>
323
+ </div>
324
+ </div>
325
+ </div>
326
+
327
+ <div>
328
+ <button class="w-full py-2 bg-red-900/30 text-red-500 rounded-lg hover:bg-red-900/50 transition-all">
329
+ <i class="fas fa-trash-alt mr-2"></i> Delete Chat
330
+ </button>
331
+ </div>
332
+ </div>
333
+ </div>
334
+ </div>
335
+
336
+ <!-- New Chat Modal -->
337
+ <div id="newChatModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 opacity-0 pointer-events-none transition-opacity duration-300">
338
+ <div class="bg-gray-900 rounded-lg w-full max-w-md border border-gray-800 transform scale-95 transition-all duration-300">
339
+ <div class="p-4 border-b border-gray-800 flex items-center justify-between">
340
+ <h3 class="font-bold">New Conversation</h3>
341
+ <button id="closeNewChatModal" class="w-8 h-8 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
342
+ <i class="fas fa-times"></i>
343
+ </button>
344
+ </div>
345
+
346
+ <div class="p-4">
347
+ <div class="mb-4">
348
+ <label class="block text-sm font-medium text-gray-400 mb-1">Recipient</label>
349
+ <select id="newChatRecipient" class="w-full bg-gray-800 text-white px-4 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-600">
350
+ <!-- Contacts will be populated here -->
351
+ </select>
352
+ </div>
353
+
354
+ <div class="mb-4">
355
+ <label class="block text-sm font-medium text-gray-400 mb-1">First Message</label>
356
+ <textarea id="newChatMessage" class="w-full bg-gray-800 text-white px-4 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-600" rows="3" placeholder="Type your first message..."></textarea>
357
+ </div>
358
+
359
+ <button id="confirmNewChat" class="w-full py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-all">
360
+ Start Conversation
361
+ </button>
362
+ </div>
363
+ </div>
364
+ </div>
365
+
366
+ <!-- User Profile Modal -->
367
+ <div id="profileModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 opacity-0 pointer-events-none transition-opacity duration-300">
368
+ <div class="bg-gray-900 rounded-lg w-full max-w-md border border-gray-800 transform scale-95 transition-all duration-300">
369
+ <div class="p-4 border-b border-gray-800 flex items-center justify-between">
370
+ <h3 class="font-bold">Your Profile</h3>
371
+ <button id="closeProfileModal" class="w-8 h-8 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
372
+ <i class="fas fa-times"></i>
373
+ </button>
374
+ </div>
375
+
376
+ <div class="p-4">
377
+ <div class="flex flex-col items-center mb-6">
378
+ <div id="profileAvatar" class="w-20 h-20 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white text-3xl font-bold mb-3 cursor-pointer hover:opacity-80 transition-all">
379
+ <i class="fas fa-user"></i>
380
+ </div>
381
+ <input id="profileName" type="text" class="bg-gray-800 text-white text-center px-4 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-600" value="Guest User">
382
+ </div>
383
+
384
+ <div class="mb-4">
385
+ <label class="block text-sm font-medium text-gray-400 mb-1">Status</label>
386
+ <input id="profileStatus" type="text" class="w-full bg-gray-800 text-white px-4 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-600" placeholder="Set your status...">
387
+ </div>
388
+
389
+ <div class="mb-6">
390
+ <label class="block text-sm font-medium text-gray-400 mb-1">Theme</label>
391
+ <div class="grid grid-cols-3 gap-2 mt-2">
392
+ <div class="h-10 rounded-lg bg-gradient-to-br from-purple-600 to-blue-500 cursor-pointer border-2 border-transparent hover:border-white transition-all"></div>
393
+ <div class="h-10 rounded-lg bg-gradient-to-br from-green-600 to-teal-500 cursor-pointer border-2 border-transparent hover:border-white transition-all"></div>
394
+ <div class="h-10 rounded-lg bg-gradient-to-br from-red-600 to-pink-500 cursor-pointer border-2 border-transparent hover:border-white transition-all"></div>
395
+ </div>
396
+ </div>
397
+
398
+ <button id="saveProfile" class="w-full py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-all">
399
+ Save Changes
400
+ </button>
401
+ </div>
402
+ </div>
403
+ </div>
404
+
405
+ <!-- Settings Modal -->
406
+ <div id="settingsModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 opacity-0 pointer-events-none transition-opacity duration-300">
407
+ <div class="bg-gray-900 rounded-lg w-full max-w-md border border-gray-800 transform scale-95 transition-all duration-300">
408
+ <div class="p-4 border-b border-gray-800 flex items-center justify-between">
409
+ <h3 class="font-bold">Settings</h3>
410
+ <button id="closeSettingsModal" class="w-8 h-8 rounded-full bg-gray-800 text-gray-400 flex items-center justify-center hover:bg-gray-700 hover:text-white transition-all">
411
+ <i class="fas fa-times"></i>
412
+ </button>
413
+ </div>
414
+
415
+ <div class="p-4">
416
+ <div class="mb-6">
417
+ <h4 class="text-sm font-semibold text-gray-400 mb-3">NOTIFICATIONS</h4>
418
+ <div class="space-y-3">
419
+ <div class="flex items-center justify-between">
420
+ <div>
421
+ <div class="font-medium">Message Notifications</div>
422
+ <div class="text-xs text-gray-500">Play sound for new messages</div>
423
+ </div>
424
+ <label class="relative inline-flex items-center cursor-pointer">
425
+ <input type="checkbox" class="sr-only peer" checked>
426
+ <div class="w-11 h-6 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
427
+ </label>
428
+ </div>
429
+
430
+ <div class="flex items-center justify-between">
431
+ <div>
432
+ <div class="font-medium">Popup Notifications</div>
433
+ <div class="text-xs text-gray-500">Show popup for new messages</div>
434
+ </div>
435
+ <label class="relative inline-flex items-center cursor-pointer">
436
+ <input type="checkbox" class="sr-only peer" checked>
437
+ <div class="w-11 h-6 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
438
+ </label>
439
+ </div>
440
+ </div>
441
+ </div>
442
+
443
+ <div class="mb-6">
444
+ <h4 class="text-sm font-semibold text-gray-400 mb-3">APPEARANCE</h4>
445
+ <div class="space-y-3">
446
+ <div class="flex items-center justify-between">
447
+ <div>
448
+ <div class="font-medium">Dark Mode</div>
449
+ <div class="text-xs text-gray-500">Switch between dark and light mode</div>
450
+ </div>
451
+ <label class="relative inline-flex items-center cursor-pointer">
452
+ <input type="checkbox" class="sr-only peer" checked>
453
+ <div class="w-11 h-6 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
454
+ </label>
455
+ </div>
456
+
457
+ <div class="flex items-center justify-between">
458
+ <div>
459
+ <div class="font-medium">Message Animations</div>
460
+ <div class="text-xs text-gray-500">Enable 3D message effects</div>
461
+ </div>
462
+ <label class="relative inline-flex items-center cursor-pointer">
463
+ <input type="checkbox" class="sr-only peer" checked>
464
+ <div class="w-11 h-6 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
465
+ </label>
466
+ </div>
467
+ </div>
468
+ </div>
469
+
470
+ <div>
471
+ <button class="w-full py-2 bg-red-900/30 text-red-500 rounded-lg hover:bg-red-900/50 transition-all">
472
+ <i class="fas fa-sign-out-alt mr-2"></i> Logout
473
+ </button>
474
+ </div>
475
+ </div>
476
+ </div>
477
+ </div>
478
+
479
+ <script>
480
+ // Database simulation using localStorage
481
+ class Database {
482
+ constructor() {
483
+ this.users = [
484
+ { id: 1, name: 'Alex Johnson', avatar: 'AJ', status: 'Online', lastSeen: null },
485
+ { id: 2, name: 'Sarah Smith', avatar: 'SS', status: 'Last seen 5 min ago', lastSeen: new Date(Date.now() - 5 * 60 * 1000) },
486
+ { id: 3, name: 'Michael Brown', avatar: 'MB', status: 'Last seen 1 hour ago', lastSeen: new Date(Date.now() - 60 * 60 * 1000) },
487
+ { id: 4, name: 'Emily Davis', avatar: 'ED', status: 'Online', lastSeen: null },
488
+ { id: 5, name: 'David Wilson', avatar: 'DW', status: 'Last seen yesterday', lastSeen: new Date(Date.now() - 24 * 60 * 60 * 1000) }
489
+ ];
490
+
491
+ this.conversations = [
492
+ {
493
+ id: 1,
494
+ name: 'Team Meeting',
495
+ avatar: 'TM',
496
+ isGroup: true,
497
+ members: [1, 2, 3],
498
+ lastMessage: {
499
+ text: 'Let me check the schedule and get back to you.',
500
+ sender: 2,
501
+ timestamp: new Date(Date.now() - 30 * 60 * 1000)
502
+ }
503
+ },
504
+ {
505
+ id: 2,
506
+ name: 'Alex Johnson',
507
+ avatar: 'AJ',
508
+ isGroup: false,
509
+ members: [1],
510
+ lastMessage: {
511
+ text: 'Thanks for the update!',
512
+ sender: 1,
513
+ timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000)
514
+ }
515
+ },
516
+ {
517
+ id: 3,
518
+ name: 'Project Discussion',
519
+ avatar: 'PD',
520
+ isGroup: true,
521
+ members: [1, 3, 4],
522
+ lastMessage: {
523
+ text: 'I think we should prioritize the backend first.',
524
+ sender: 3,
525
+ timestamp: new Date(Date.now() - 12 * 60 * 60 * 1000)
526
+ }
527
+ }
528
+ ];
529
+
530
+ this.messages = {
531
+ 1: [
532
+ { id: 1, text: 'Hi team, how is the project going?', sender: 1, timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000) },
533
+ { id: 2, text: 'Going well! We should have the first prototype ready by Friday.', sender: 2, timestamp: new Date(Date.now() - 1.5 * 60 * 60 * 1000) },
534
+ { id: 3, text: 'That sounds great. Do we have a meeting scheduled to review it?', sender: 1, timestamp: new Date(Date.now() - 60 * 60 * 1000) },
535
+ { id: 4, text: 'Not yet, but I can set one up.', sender: 3, timestamp: new Date(Date.now() - 45 * 60 * 1000) },
536
+ { id: 5, text: 'Let me check the schedule and get back to you.', sender: 2, timestamp: new Date(Date.now() - 30 * 60 * 1000) }
537
+ ],
538
+ 2: [
539
+ { id: 1, text: 'Hey Alex, do you have those files I asked for?', sender: 0, timestamp: new Date(Date.now() - 3 * 60 * 60 * 1000) },
540
+ { id: 2, text: 'Yes, I just sent them to your email.', sender: 1, timestamp: new Date(Date.now() - 2.5 * 60 * 60 * 1000) },
541
+ { id: 3, text: 'Got them, thanks!', sender: 0, timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000) },
542
+ { id: 4, text: 'No problem. Let me know if you need anything else.', sender: 1, timestamp: new Date(Date.now() - 1.5 * 60 * 60 * 1000) },
543
+ { id: 5, text: 'Thanks for the update!', sender: 0, timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000) }
544
+ ],
545
+ 3: [
546
+ { id: 1, text: 'What should we focus on first for the new project?', sender: 0, timestamp: new Date(Date.now() - 24 * 60 * 60 * 1000) },
547
+ { id: 2, text: 'I think we should prioritize the backend first.', sender: 3, timestamp: new Date(Date.now() - 12 * 60 * 60 * 1000) },
548
+ { id: 3, text: 'Agreed. The frontend can wait until we have the API ready.', sender: 4, timestamp: new Date(Date.now() - 10 * 60 * 60 * 1000) }
549
+ ]
550
+ };
551
+
552
+ // Current user (simulated login)
553
+ this.currentUser = {
554
+ id: 0,
555
+ name: 'Guest User',
556
+ avatar: 'GU',
557
+ status: 'Online'
558
+ };
559
+
560
+ this.loadFromLocalStorage();
561
+ }
562
+
563
+ saveToLocalStorage() {
564
+ localStorage.setItem('neonChatUsers', JSON.stringify(this.users));
565
+ localStorage.setItem('neonChatConversations', JSON.stringify(this.conversations));
566
+ localStorage.setItem('neonChatMessages', JSON.stringify(this.messages));
567
+ localStorage.setItem('neonChatCurrentUser', JSON.stringify(this.currentUser));
568
+ }
569
+
570
+ loadFromLocalStorage() {
571
+ const users = localStorage.getItem('neonChatUsers');
572
+ const conversations = localStorage.getItem('neonChatConversations');
573
+ const messages = localStorage.getItem('neonChatMessages');
574
+ const currentUser = localStorage.getItem('neonChatCurrentUser');
575
+
576
+ if (users) this.users = JSON.parse(users);
577
+ if (conversations) this.conversations = JSON.parse(conversations);
578
+ if (messages) this.messages = JSON.parse(messages);
579
+ if (currentUser) this.currentUser = JSON.parse(currentUser);
580
+ }
581
+
582
+ getUserById(id) {
583
+ if (id === this.currentUser.id) return this.currentUser;
584
+ return this.users.find(user => user.id === id);
585
+ }
586
+
587
+ getConversationById(id) {
588
+ return this.conversations.find(conv => conv.id === id);
589
+ }
590
+
591
+ getMessagesByConversationId(id) {
592
+ return this.messages[id] || [];
593
+ }
594
+
595
+ addMessage(conversationId, text) {
596
+ if (!this.messages[conversationId]) {
597
+ this.messages[conversationId] = [];
598
+ }
599
+
600
+ const newMessage = {
601
+ id: this.messages[conversationId].length + 1,
602
+ text: text,
603
+ sender: this.currentUser.id,
604
+ timestamp: new Date()
605
+ };
606
+
607
+ this.messages[conversationId].push(newMessage);
608
+
609
+ // Update conversation last message
610
+ const conversation = this.getConversationById(conversationId);
611
+ if (conversation) {
612
+ conversation.lastMessage = {
613
+ text: text,
614
+ sender: this.currentUser.id,
615
+ timestamp: new Date()
616
+ };
617
+ }
618
+
619
+ this.saveToLocalStorage();
620
+ return newMessage;
621
+ }
622
+
623
+ createConversation(recipientId, firstMessage) {
624
+ const recipient = this.getUserById(recipientId);
625
+ if (!recipient) return null;
626
+
627
+ const newConversation = {
628
+ id: this.conversations.length + 1,
629
+ name: recipient.name,
630
+ avatar: recipient.avatar,
631
+ isGroup: false,
632
+ members: [this.currentUser.id, recipient.id],
633
+ lastMessage: {
634
+ text: firstMessage,
635
+ sender: this.currentUser.id,
636
+ timestamp: new Date()
637
+ }
638
+ };
639
+
640
+ this.conversations.push(newConversation);
641
+ this.messages[newConversation.id] = [{
642
+ id: 1,
643
+ text: firstMessage,
644
+ sender: this.currentUser.id,
645
+ timestamp: new Date()
646
+ }];
647
+
648
+ this.saveToLocalStorage();
649
+ return newConversation;
650
+ }
651
+
652
+ updateUserProfile(name, status) {
653
+ this.currentUser.name = name;
654
+ this.currentUser.status = status;
655
+ this.saveToLocalStorage();
656
+ }
657
+ }
658
+
659
+ // Initialize database
660
+ const db = new Database();
661
+
662
+ // DOM Elements
663
+ const sidebar = document.getElementById('sidebar');
664
+ const mainContent = document.getElementById('mainContent');
665
+ const chatInfoPanel = document.getElementById('chatInfoPanel');
666
+ const messagesContainer = document.getElementById('messagesContainer');
667
+ const messageInput = document.getElementById('messageInput');
668
+ const sendMessageBtn = document.getElementById('sendMessageBtn');
669
+ const conversationsList = document.getElementById('conversationsList');
670
+ const contactsList = document.getElementById('contactsList');
671
+ const currentChatName = document.getElementById('currentChatName');
672
+ const currentChatAvatar = document.getElementById('currentChatAvatar');
673
+ const typingIndicator = document.getElementById('typingIndicator');
674
+ const onlineStatus = document.getElementById('onlineStatus');
675
+ const chatInfoBtn = document.getElementById('chatInfoBtn');
676
+ const closeChatInfoBtn = document.getElementById('closeChatInfoBtn');
677
+ const infoChatName = document.getElementById('infoChatName');
678
+ const infoChatAvatar = document.getElementById('infoChatAvatar');
679
+ const infoChatStatus = document.getElementById('infoChatStatus');
680
+ const chatMembersList = document.getElementById('chatMembersList');
681
+ const newChatBtn = document.getElementById('newChatBtn');
682
+ const newChatModal = document.getElementById('newChatModal');
683
+ const closeNewChatModal = document.getElementById('closeNewChatModal');
684
+ const newChatRecipient = document.getElementById('newChatRecipient');
685
+ const newChatMessage = document.getElementById('newChatMessage');
686
+ const confirmNewChat = document.getElementById('confirmNewChat');
687
+ const userAvatar = document.getElementById('userAvatar');
688
+ const userName = document.getElementById('userName');
689
+ const profileModal = document.getElementById('profileModal');
690
+ const closeProfileModal = document.getElementById('closeProfileModal');
691
+ const profileName = document.getElementById('profileName');
692
+ const profileStatus = document.getElementById('profileStatus');
693
+ const saveProfile = document.getElementById('saveProfile');
694
+ const settingsBtn = document.getElementById('settingsBtn');
695
+ const settingsModal = document.getElementById('settingsModal');
696
+ const closeSettingsModal = document.getElementById('closeSettingsModal');
697
+ const menuToggle = document.getElementById('menuToggle');
698
+
699
+ // Current state
700
+ let currentConversationId = null;
701
+ let isTyping = false;
702
+ let typingTimeout = null;
703
+
704
+ // Initialize the app
705
+ function init() {
706
+ renderConversations();
707
+ renderContacts();
708
+ updateUserProfileUI();
709
+ setupEventListeners();
710
+ init3DBackground();
711
+
712
+ // Simulate someone typing in the first conversation
713
+ setTimeout(() => {
714
+ simulateTyping(1);
715
+ }, 3000);
716
+ }
717
+
718
+ // Set up event listeners
719
+ function setupEventListeners() {
720
+ // Send message on Enter key or button click
721
+ messageInput.addEventListener('keypress', (e) => {
722
+ if (e.key === 'Enter' && messageInput.value.trim() !== '') {
723
+ sendMessage();
724
+ }
725
+ });
726
+
727
+ sendMessageBtn.addEventListener('click', sendMessage);
728
+
729
+ // Typing indicator
730
+ messageInput.addEventListener('input', () => {
731
+ if (!isTyping && currentConversationId) {
732
+ isTyping = true;
733
+ // In a real app, we'd send a "user is typing" event to the server
734
+ }
735
+
736
+ clearTimeout(typingTimeout);
737
+ typingTimeout = setTimeout(() => {
738
+ isTyping = false;
739
+ // In a real app, we'd send a "user stopped typing" event to the server
740
+ }, 2000);
741
+ });
742
+
743
+ // Toggle chat info panel
744
+ chatInfoBtn.addEventListener('click', () => {
745
+ chatInfoPanel.classList.toggle('hidden');
746
+ if (!chatInfoPanel.classList.contains('hidden')) {
747
+ updateChatInfoPanel();
748
+ }
749
+ });
750
+
751
+ closeChatInfoBtn.addEventListener('click', () => {
752
+ chatInfoPanel.classList.add('hidden');
753
+ });
754
+
755
+ // New conversation
756
+ newChatBtn.addEventListener('click', openNewChatModal);
757
+ closeNewChatModal.addEventListener('click', closeNewChatModalFunc);
758
+ confirmNewChat.addEventListener('click', createNewConversation);
759
+
760
+ // Profile
761
+ userAvatar.addEventListener('click', openProfileModal);
762
+ closeProfileModal.addEventListener('click', closeProfileModalFunc);
763
+ saveProfile.addEventListener('click', saveProfileChanges);
764
+
765
+ // Settings
766
+ settingsBtn.addEventListener('click', openSettingsModal);
767
+ closeSettingsModal.addEventListener('click', closeSettingsModalFunc);
768
+
769
+ // Mobile menu toggle
770
+ menuToggle.addEventListener('click', () => {
771
+ sidebar.classList.toggle('active');
772
+ });
773
+
774
+ // Close sidebar when clicking outside on mobile
775
+ document.addEventListener('click', (e) => {
776
+ if (window.innerWidth <= 768 &&
777
+ !sidebar.contains(e.target) &&
778
+ e.target !== menuToggle) {
779
+ sidebar.classList.remove('active');
780
+ }
781
+ });
782
+ }
783
+
784
+ // Render conversations list
785
+ function renderConversations() {
786
+ conversationsList.innerHTML = '';
787
+
788
+ db.conversations.forEach(conversation => {
789
+ const lastMessage = conversation.lastMessage;
790
+ const sender = db.getUserById(lastMessage.sender);
791
+ const isCurrentUser = lastMessage.sender === db.currentUser.id;
792
+ const timestamp = formatTime(lastMessage.timestamp);
793
+
794
+ const conversationElement = document.createElement('div');
795
+ conversationElement.className = `p-3 rounded-lg cursor-pointer transition-all ${currentConversationId === conversation.id ? 'bg-purple-900/30' : 'hover:bg-gray-800'}`;
796
+ conversationElement.innerHTML = `
797
+ <div class="flex items-center space-x-3">
798
+ <div class="w-12 h-12 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white font-bold">
799
+ ${conversation.avatar}
800
+ </div>
801
+ <div class="flex-1 min-w-0">
802
+ <div class="flex justify-between items-center">
803
+ <h4 class="font-medium truncate">${conversation.name}</h4>
804
+ <span class="text-xs text-gray-500">${timestamp}</span>
805
+ </div>
806
+ <p class="text-sm text-gray-400 truncate">
807
+ ${isCurrentUser ? 'You: ' : (sender ? `${sender.name.split(' ')[0]}: ` : '')}${lastMessage.text}
808
+ </p>
809
+ </div>
810
+ </div>
811
+ `;
812
+
813
+ conversationElement.addEventListener('click', () => {
814
+ loadConversation(conversation.id);
815
+ });
816
+
817
+ conversationsList.appendChild(conversationElement);
818
+ });
819
+ }
820
+
821
+ // Render contacts list
822
+ function renderContacts() {
823
+ contactsList.innerHTML = '';
824
+
825
+ db.users.forEach(user => {
826
+ const isOnline = !user.lastSeen || (new Date() - new Date(user.lastSeen)) < 5 * 60 * 1000;
827
+
828
+ const contactElement = document.createElement('div');
829
+ contactElement.className = 'p-3 rounded-lg cursor-pointer hover:bg-gray-800 transition-all user-card';
830
+ contactElement.innerHTML = `
831
+ <div class="flex items-center space-x-3">
832
+ <div class="relative">
833
+ <div class="w-12 h-12 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white font-bold">
834
+ ${user.avatar}
835
+ </div>
836
+ <div class="absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-gray-900 ${isOnline ? 'bg-green-500' : 'bg-gray-500'}"></div>
837
+ </div>
838
+ <div class="flex-1 min-w-0">
839
+ <h4 class="font-medium truncate">${user.name}</h4>
840
+ <p class="text-sm text-gray-400 truncate">${user.status}</p>
841
+ </div>
842
+ </div>
843
+ `;
844
+
845
+ contactElement.addEventListener('click', () => {
846
+ // In a real app, this would open a conversation with this user
847
+ console.log('Open conversation with', user.name);
848
+ });
849
+
850
+ contactsList.appendChild(contactElement);
851
+ });
852
+ }
853
+
854
+ // Load a conversation
855
+ function loadConversation(conversationId) {
856
+ currentConversationId = conversationId;
857
+ const conversation = db.getConversationById(conversationId);
858
+ const messages = db.getMessagesByConversationId(conversationId);
859
+
860
+ // Update header
861
+ currentChatName.textContent = conversation.name;
862
+ currentChatAvatar.textContent = conversation.avatar;
863
+
864
+ // Show online status if it's a 1:1 chat
865
+ if (!conversation.isGroup) {
866
+ const otherUserId = conversation.members.find(id => id !== db.currentUser.id);
867
+ const otherUser = db.getUserById(otherUserId);
868
+ onlineStatus.textContent = otherUser.lastSeen ? `Last seen ${formatLastSeen(otherUser.lastSeen)}` : 'Online';
869
+ onlineStatus.classList.remove('hidden');
870
+ } else {
871
+ onlineStatus.classList.add('hidden');
872
+ }
873
+
874
+ // Render messages
875
+ renderMessages(messages);
876
+
877
+ // Highlight active conversation in sidebar
878
+ renderConversations();
879
+
880
+ // Close sidebar on mobile
881
+ if (window.innerWidth <= 768) {
882
+ sidebar.classList.remove('active');
883
+ }
884
+
885
+ // Scroll to bottom of messages
886
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
887
+ }
888
+
889
+ // Render messages
890
+ function renderMessages(messages) {
891
+ messagesContainer.innerHTML = '';
892
+
893
+ if (messages.length === 0) {
894
+ messagesContainer.innerHTML = `
895
+ <div class="text-center py-10 text-gray-500">
896
+ <div class="w-16 h-16 mx-auto mb-4 rounded-full bg-gray-800 flex items-center justify-center text-gray-600">
897
+ <i class="fas fa-comments text-2xl"></i>
898
+ </div>
899
+ <h3 class="text-lg font-medium">No messages yet</h3>
900
+ <p class="text-sm">Send the first message to start the conversation</p>
901
+ </div>
902
+ `;
903
+ return;
904
+ }
905
+
906
+ let lastDate = null;
907
+
908
+ messages.forEach(message => {
909
+ const messageDate = new Date(message.timestamp).toDateString();
910
+ if (messageDate !== lastDate) {
911
+ const dateElement = document.createElement('div');
912
+ dateElement.className = 'text-center text-xs text-gray-500 my-4';
913
+ dateElement.textContent = formatDate(message.timestamp);
914
+ messagesContainer.appendChild(dateElement);
915
+ lastDate = messageDate;
916
+ }
917
+
918
+ const isCurrentUser = message.sender === db.currentUser.id;
919
+ const sender = db.getUserById(message.sender);
920
+
921
+ const messageElement = document.createElement('div');
922
+ messageElement.className = `flex ${isCurrentUser ? 'justify-end' : 'justify-start'} mb-4 message-3d`;
923
+
924
+ if (!isCurrentUser) {
925
+ messageElement.innerHTML = `
926
+ <div class="flex items-end space-x-2">
927
+ <div class="w-8 h-8 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white text-xs font-bold">
928
+ ${sender ? sender.avatar : '?'}
929
+ </div>
930
+ <div class="max-w-xs md:max-w-md bg-gray-800 rounded-lg p-3 message-bubble">
931
+ <p>${message.text}</p>
932
+ <div class="text-right mt-1">
933
+ <span class="text-xs text-gray-500">${formatTime(message.timestamp)}</span>
934
+ </div>
935
+ </div>
936
+ </div>
937
+ `;
938
+ } else {
939
+ messageElement.innerHTML = `
940
+ <div class="max-w-xs md:max-w-md bg-purple-600 rounded-lg p-3 message-bubble">
941
+ <p>${message.text}</p>
942
+ <div class="text-right mt-1">
943
+ <span class="text-xs text-purple-300">${formatTime(message.timestamp)}</span>
944
+ </div>
945
+ </div>
946
+ `;
947
+ }
948
+
949
+ messagesContainer.appendChild(messageElement);
950
+ });
951
+
952
+ // Add floating animation to the last few messages
953
+ const allMessages = messagesContainer.querySelectorAll('.message-bubble');
954
+ const lastMessages = Array.from(allMessages).slice(-5);
955
+
956
+ lastMessages.forEach((msg, index) => {
957
+ gsap.from(msg, {
958
+ y: 20,
959
+ opacity: 0,
960
+ duration: 0.3,
961
+ delay: index * 0.1,
962
+ ease: "power2.out"
963
+ });
964
+ });
965
+ }
966
+
967
+ // Send a message
968
+ function sendMessage() {
969
+ const text = messageInput.value.trim();
970
+ if (text === '' || !currentConversationId) return;
971
+
972
+ // Add message to database
973
+ const message = db.addMessage(currentConversationId, text);
974
+
975
+ // Clear input
976
+ messageInput.value = '';
977
+
978
+ // Render new message
979
+ const messages = db.getMessagesByConversationId(currentConversationId);
980
+ renderMessages(messages);
981
+
982
+ // Scroll to bottom
983
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
984
+
985
+ // Update conversation list
986
+ renderConversations();
987
+
988
+ // In a real app, we'd send the message to the server here
989
+ }
990
+
991
+ // Simulate someone typing
992
+ function simulateTyping(conversationId) {
993
+ if (currentConversationId !== conversationId) return;
994
+
995
+ typingIndicator.classList.remove('hidden');
996
+ onlineStatus.classList.add('hidden');
997
+
998
+ setTimeout(() => {
999
+ typingIndicator.classList.add('hidden');
1000
+ const conversation = db.getConversationById(conversationId);
1001
+ if (!conversation.isGroup) {
1002
+ const otherUserId = conversation.members.find(id => id !== db.currentUser.id);
1003
+ const otherUser = db.getUserById(otherUserId);
1004
+ onlineStatus.textContent = otherUser.lastSeen ? `Last seen ${formatLastSeen(otherUser.lastSeen)}` : 'Online';
1005
+ onlineStatus.classList.remove('hidden');
1006
+ }
1007
+
1008
+ // Simulate receiving a message
1009
+ setTimeout(() => {
1010
+ if (Math.random() > 0.3) { // 70% chance to send a reply
1011
+ const replies = [
1012
+ "Hey, how are you doing?",
1013
+ "I'll get back to you on that.",
1014
+ "Sounds good!",
1015
+ "Can we talk about this later?",
1016
+ "Thanks for letting me know.",
1017
+ "I'm busy right now, can we chat later?",
1018
+ "That's interesting, tell me more."
1019
+ ];
1020
+
1021
+ const randomReply = replies[Math.floor(Math.random() * replies.length)];
1022
+ const message = db.addMessage(conversationId, randomReply);
1023
+
1024
+ if (currentConversationId === conversationId) {
1025
+ const messages = db.getMessagesByConversationId(conversationId);
1026
+ renderMessages(messages);
1027
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
1028
+ renderConversations();
1029
+ }
1030
+ }
1031
+ }, 1000);
1032
+ }, 2000 + Math.random() * 3000);
1033
+ }
1034
+
1035
+ // Update chat info panel
1036
+ function updateChatInfoPanel() {
1037
+ if (!currentConversationId) return;
1038
+
1039
+ const conversation = db.getConversationById(currentConversationId);
1040
+ infoChatName.textContent = conversation.name;
1041
+ infoChatAvatar.textContent = conversation.avatar;
1042
+
1043
+ if (conversation.isGroup) {
1044
+ infoChatStatus.textContent = `${conversation.members.length} members`;
1045
+ } else {
1046
+ const otherUserId = conversation.members.find(id => id !== db.currentUser.id);
1047
+ const otherUser = db.getUserById(otherUserId);
1048
+ infoChatStatus.textContent = otherUser.lastSeen ? `Last seen ${formatLastSeen(otherUser.lastSeen)}` : 'Online';
1049
+ }
1050
+
1051
+ // Update members list
1052
+ chatMembersList.innerHTML = '';
1053
+ conversation.members.forEach(memberId => {
1054
+ if (memberId === db.currentUser.id) return;
1055
+
1056
+ const member = db.getUserById(memberId);
1057
+ if (!member) return;
1058
+
1059
+ const isOnline = !member.lastSeen || (new Date() - new Date(member.lastSeen)) < 5 * 60 * 1000;
1060
+
1061
+ const memberElement = document.createElement('div');
1062
+ memberElement.className = 'flex items-center justify-between p-2 rounded-lg hover:bg-gray-800 cursor-pointer';
1063
+ memberElement.innerHTML = `
1064
+ <div class="flex items-center space-x-3">
1065
+ <div class="relative">
1066
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-purple-600 to-blue-500 flex items-center justify-center text-white text-xs font-bold">
1067
+ ${member.avatar}
1068
+ </div>
1069
+ <div class="absolute bottom-0 right-0 w-2 h-2 rounded-full border-2 border-gray-900 ${isOnline ? 'bg-green-500' : 'bg-gray-500'}"></div>
1070
+ </div>
1071
+ <div>
1072
+ <h4 class="font-medium">${member.name}</h4>
1073
+ <p class="text-xs text-gray-500">${isOnline ? 'Online' : 'Offline'}</p>
1074
+ </div>
1075
+ </div>
1076
+ <button class="w-8 h-8 rounded-full text-gray-500 hover:bg-gray-700 hover:text-white flex items-center justify-center transition-all">
1077
+ <i class="fas fa-ellipsis-h"></i>
1078
+ </button>
1079
+ `;
1080
+
1081
+ chatMembersList.appendChild(memberElement);
1082
+ });
1083
+ }
1084
+
1085
+ // New conversation modal
1086
+ function openNewChatModal() {
1087
+ // Populate recipient dropdown
1088
+ newChatRecipient.innerHTML = '';
1089
+ db.users.forEach(user => {
1090
+ const option = document.createElement('option');
1091
+ option.value = user.id;
1092
+ option.textContent = user.name;
1093
+ newChatRecipient.appendChild(option);
1094
+ });
1095
+
1096
+ // Show modal
1097
+ gsap.to(newChatModal, {
1098
+ opacity: 1,
1099
+ pointerEvents: 'auto',
1100
+ duration: 0.3
1101
+ });
1102
+
1103
+ gsap.to(newChatModal.querySelector('div'), {
1104
+ scale: 1,
1105
+ duration: 0.3,
1106
+ ease: "back.out(1.7)"
1107
+ });
1108
+ }
1109
+
1110
+ function closeNewChatModalFunc() {
1111
+ gsap.to(newChatModal, {
1112
+ opacity: 0,
1113
+ pointerEvents: 'none',
1114
+ duration: 0.3
1115
+ });
1116
+
1117
+ gsap.to(newChatModal.querySelector('div'), {
1118
+ scale: 0.95,
1119
+ duration: 0.3
1120
+ });
1121
+ }
1122
+
1123
+ function createNewConversation() {
1124
+ const recipientId = parseInt(newChatRecipient.value);
1125
+ const message = newChatMessage.value.trim();
1126
+
1127
+ if (recipientId && message) {
1128
+ const conversation = db.createConversation(recipientId, message);
1129
+ if (conversation) {
1130
+ renderConversations();
1131
+ loadConversation(conversation.id);
1132
+ closeNewChatModalFunc();
1133
+ newChatMessage.value = '';
1134
+ }
1135
+ }
1136
+ }
1137
+
1138
+ // Profile modal
1139
+ function openProfileModal() {
1140
+ profileName.value = db.currentUser.name;
1141
+ profileStatus.value = db.currentUser.status || '';
1142
+
1143
+ gsap.to(profileModal, {
1144
+ opacity: 1,
1145
+ pointerEvents: 'auto',
1146
+ duration: 0.3
1147
+ });
1148
+
1149
+ gsap.to(profileModal.querySelector('div'), {
1150
+ scale: 1,
1151
+ duration: 0.3,
1152
+ ease: "back.out(1.7)"
1153
+ });
1154
+ }
1155
+
1156
+ function closeProfileModalFunc() {
1157
+ gsap.to(profileModal, {
1158
+ opacity: 0,
1159
+ pointerEvents: 'none',
1160
+ duration: 0.3
1161
+ });
1162
+
1163
+ gsap.to(profileModal.querySelector('div'), {
1164
+ scale: 0.95,
1165
+ duration: 0.3
1166
+ });
1167
+ }
1168
+
1169
+ function saveProfileChanges() {
1170
+ const name = profileName.value.trim();
1171
+ const status = profileStatus.value.trim();
1172
+
1173
+ if (name) {
1174
+ db.updateUserProfile(name, status);
1175
+ updateUserProfileUI();
1176
+ closeProfileModalFunc();
1177
+
1178
+ // If we're in a conversation, update the header
1179
+ if (currentConversationId) {
1180
+ const conversation = db.getConversationById(currentConversationId);
1181
+ if (!conversation.isGroup && conversation.members.includes(db.currentUser.id)) {
1182
+ currentChatName.textContent = name;
1183
+ }
1184
+ }
1185
+ }
1186
+ }
1187
+
1188
+ function updateUserProfileUI() {
1189
+ userName.textContent = db.currentUser.name;
1190
+ userAvatar.textContent = db.currentUser.avatar.charAt(0);
1191
+ }
1192
+
1193
+ // Settings modal
1194
+ function openSettingsModal() {
1195
+ gsap.to(settingsModal, {
1196
+ opacity: 1,
1197
+ pointerEvents: 'auto',
1198
+ duration: 0.3
1199
+ });
1200
+
1201
+ gsap.to(settingsModal.querySelector('div'), {
1202
+ scale: 1,
1203
+ duration: 0.3,
1204
+ ease: "back.out(1.7)"
1205
+ });
1206
+ }
1207
+
1208
+ function closeSettingsModalFunc() {
1209
+ gsap.to(settingsModal, {
1210
+ opacity: 0,
1211
+ pointerEvents: 'none',
1212
+ duration: 0.3
1213
+ });
1214
+
1215
+ gsap.to(settingsModal.querySelector('div'), {
1216
+ scale: 0.95,
1217
+ duration: 0.3
1218
+ });
1219
+ }
1220
+
1221
+ // Formatting helpers
1222
+ function formatTime(date) {
1223
+ if (typeof date === 'string') date = new Date(date);
1224
+ return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
1225
+ }
1226
+
1227
+ function formatDate(date) {
1228
+ if (typeof date === 'string') date = new Date(date);
1229
+ const today = new Date();
1230
+ const yesterday = new Date(today);
1231
+ yesterday.setDate(yesterday.getDate() - 1);
1232
+
1233
+ if (date.toDateString() === today.toDateString()) {
1234
+ return 'Today';
1235
+ } else if (date.toDateString() === yesterday.toDateString()) {
1236
+ return 'Yesterday';
1237
+ } else {
1238
+ return date.toLocaleDateString([], { month: 'short', day: 'numeric' });
1239
+ }
1240
+ }
1241
+
1242
+ function formatLastSeen(date) {
1243
+ if (typeof date === 'string') date = new Date(date);
1244
+ const now = new Date();
1245
+ const diff = (now - date) / 1000; // difference in seconds
1246
+
1247
+ if (diff < 60) return 'just now';
1248
+ if (diff < 3600) return `${Math.floor(diff / 60)} minutes ago`;
1249
+ if (diff < 86400) return `${Math.floor(diff / 3600)} hours ago`;
1250
+ return `${Math.floor(diff / 86400)} days ago`;
1251
+ }
1252
+
1253
+ // 3D Background with Three.js
1254
+ function init3DBackground() {
1255
+ const container = document.getElementById('threejs-background');
1256
+ if (!container) return;
1257
+
1258
+ // Set up Three.js scene
1259
+ const scene = new THREE.Scene();
1260
+ const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
1261
+ const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
1262
+ renderer.setSize(window.innerWidth, window.innerHeight);
1263
+ container.appendChild(renderer.domElement);
1264
+
1265
+ // Create floating particles
1266
+ const particlesGeometry = new THREE.BufferGeometry();
1267
+ const particleCount = 100;
1268
+
1269
+ const posArray = new Float32Array(particleCount * 3);
1270
+ for (let i = 0; i < particleCount * 3; i++) {
1271
+ posArray[i] = (Math.random() - 0.5) * 10;
1272
+ }
1273
+
1274
+ particlesGeometry.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
1275
+
1276
+ const particlesMaterial = new THREE.PointsMaterial({
1277
+ size: 0.02,
1278
+ color: 0x6c5ce7,
1279
+ transparent: true,
1280
+ opacity: 0.8
1281
+ });
1282
+
1283
+ const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial);
1284
+ scene.add(particlesMesh);
1285
+
1286
+ // Create floating shapes
1287
+ const shapes = [];
1288
+ const colors = [0x6c5ce7, 0xa29bfe, 0xfd79a8];
1289
+ const geometries = [
1290
+ new THREE.IcosahedronGeometry(0.2, 0),
1291
+ new THREE.TorusGeometry(0.2, 0.05, 16, 32),
1292
+ new THREE.OctahedronGeometry(0.2, 0)
1293
+ ];
1294
+
1295
+ for (let i = 0; i < 5; i++) {
1296
+ const geometry = geometries[Math.floor(Math.random() * geometries.length)];
1297
+ const material = new THREE.MeshBasicMaterial({
1298
+ color: colors[Math.floor(Math.random() * colors.length)],
1299
+ wireframe: true,
1300
+ transparent: true,
1301
+ opacity: 0.5
1302
+ });
1303
+
1304
+ const mesh = new THREE.Mesh(geometry, material);
1305
+ mesh.position.x = (Math.random() - 0.5) * 5;
1306
+ mesh.position.y = (Math.random() - 0.5) * 5;
1307
+ mesh.position.z = (Math.random() - 0.5) * 5;
1308
+
1309
+ mesh.userData = {
1310
+ speed: 0.01 + Math.random() * 0.02,
1311
+ rotationSpeed: new THREE.Vector3(
1312
+ Math.random() * 0.01,
1313
+ Math.random() * 0.01,
1314
+ Math.random() * 0.01
1315
+ )
1316
+ };
1317
+
1318
+ scene.add(mesh);
1319
+ shapes.push(mesh);
1320
+ }
1321
+
1322
+ // Position camera
1323
+ camera.position.z = 3;
1324
+
1325
+ // Animation loop
1326
+ function animate() {
1327
+ requestAnimationFrame(animate);
1328
+
1329
+ // Rotate particles
1330
+ particlesMesh.rotation.x += 0.0005;
1331
+ particlesMesh.rotation.y += 0.0005;
1332
+
1333
+ // Animate shapes
1334
+ shapes.forEach(shape => {
1335
+ shape.position.y += shape.userData.speed;
1336
+ shape.rotation.x += shape.userData.rotationSpeed.x;
1337
+ shape.rotation.y += shape.userData.rotationSpeed.y;
1338
+ shape.rotation.z += shape.userData.rotationSpeed.z;
1339
+
1340
+ if (shape.position.y > 3) {
1341
+ shape.position.y = -3;
1342
+ }
1343
+ });
1344
+
1345
+ renderer.render(scene, camera);
1346
+ }
1347
+
1348
+ animate();
1349
+
1350
+ // Handle window resize
1351
+ window.addEventListener('resize', () => {
1352
+ camera.aspect = window.innerWidth / window.innerHeight;
1353
+ camera.updateProjectionMatrix();
1354
+ renderer.setSize(window.innerWidth, window.innerHeight);
1355
+ });
1356
+ }
1357
+
1358
+ // Initialize the app when DOM is loaded
1359
+ document.addEventListener('DOMContentLoaded', init);
1360
+ </script>
1361
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=spdgamerz/mesagging-app" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1362
+ </html>
prompts.txt ADDED
File without changes