al00sakkaf commited on
Commit
069779f
·
verified ·
1 Parent(s): 5b62d22

قم بدمج الاكواد كلها في كواد واحد كامل للتطبيق

Browse files
Files changed (1) hide show
  1. index.html +1124 -18
index.html CHANGED
@@ -1,3 +1,4 @@
 
1
  <!DOCTYPE html>
2
  <html lang="ar" dir="rtl">
3
  <head>
@@ -78,6 +79,12 @@
78
  overflow-x: auto;
79
  margin: 1rem 0;
80
  }
 
 
 
 
 
 
81
  </style>
82
  </head>
83
  <body class="bg-gray-50 min-h-screen">
@@ -90,23 +97,27 @@
90
  <h1 class="text-xl font-bold text-gray-800">GeminiPersona</h1>
91
  </div>
92
  <div class="flex items-center space-x-4 space-x-reverse">
93
- <a href="settings.html" class="text-gray-600 hover:text-primary transition-colors">
94
  <i data-feather="settings"></i>
95
- </a>
96
- <a href="characters.html" class="text-gray-600 hover:text-primary transition-colors">
97
  <i data-feather="users"></i>
98
- </a>
99
- <a href="conversations.html" class="text-gray-600 hover:text-primary transition-colors">
100
  <i data-feather="message-square"></i>
101
- </a>
102
- <a href="voice-chat.html" class="text-gray-600 hover:text-primary transition-colors">
103
  <i data-feather="mic"></i>
104
- </a>
 
 
 
105
  </div>
106
  </div>
107
  </div>
108
  </nav>
109
- <!-- Main Content -->
 
110
  <div class="max-w-4xl mx-auto py-8 px-4">
111
  <!-- Welcome Section -->
112
  <div class="text-center mb-12">
@@ -115,37 +126,37 @@
115
  </div>
116
  <!-- Quick Actions -->
117
  <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-12">
118
- <a href="chat.html" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow group">
119
  <div class="text-center">
120
  <i data-feather="message-square" class="w-12 h-12 text-primary mx-auto mb-4 group-hover:scale-110 transition-transform"></i>
121
  <h3 class="text-xl font-semibold text-gray-800 mb-2">بدء محادثة جديدة</h3>
122
  <p class="text-gray-600">ابدأ محادثة مع الذكاء الاصطناعي</p>
123
  </div>
124
- </a>
125
 
126
- <a href="voice-chat.html" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow group">
127
  <div class="text-center">
128
  <i data-feather="mic" class="w-12 h-12 text-green-500 mx-auto mb-4 group-hover:scale-110 transition-transform"></i>
129
  <h3 class="text-xl font-semibold text-gray-800 mb-2">المحادثة الصوتية</h3>
130
  <p class="text-gray-600">تحدث مع الذكاء الاصطناعي صوتياً</p>
131
  </div>
132
- </a>
133
 
134
- <a href="characters.html" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow group">
135
  <div class="text-center">
136
  <i data-feather="users" class="w-12 h-12 text-secondary mx-auto mb-4 group-hover:scale-110 transition-transform"></i>
137
  <h3 class="text-xl font-semibold text-gray-800 mb-2">إدارة الشخصيات</h3>
138
  <p class="text-gray-600">أنشئ وعدّل الشخصيات الافتراضية</p>
139
  </div>
140
- </a>
141
 
142
- <a href="conversations.html" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow group">
143
  <div class="text-center">
144
  <i data-feather="archive" class="w-12 h-12 text-accent mx-auto mb-4 group-hover:scale-110 transition-transform"></i>
145
  <h3 class="text-xl font-semibold text-gray-800 mb-2">المحادثات السابقة</h3>
146
  <p class="text-gray-600">راجع محادثاتك المحفوظة</p>
147
  </div>
148
- </a>
149
  </div>
150
  <!-- Features Section -->
151
  <div class="bg-white rounded-xl shadow-md p-8 mb-8">
@@ -214,9 +225,357 @@
214
  </div>
215
  </div>
216
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  </div>
218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  <script>
 
 
 
 
 
 
 
 
 
 
220
  // Initialize database
221
  function initDB() {
222
  if (!window.indexedDB) {
@@ -252,11 +611,42 @@
252
  }
253
  };
254
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  // Initialize app
256
  document.addEventListener('DOMContentLoaded', function() {
257
  initDB();
258
  feather.replace();
259
  loadStatistics();
 
260
  });
261
 
262
  // Load statistics
@@ -288,6 +678,722 @@
288
  };
289
  };
290
  }
291
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  </body>
293
  </html>
 
1
+
2
  <!DOCTYPE html>
3
  <html lang="ar" dir="rtl">
4
  <head>
 
79
  overflow-x: auto;
80
  margin: 1rem 0;
81
  }
82
+ .page-container {
83
+ display: none;
84
+ }
85
+ .active-page {
86
+ display: block;
87
+ }
88
  </style>
89
  </head>
90
  <body class="bg-gray-50 min-h-screen">
 
97
  <h1 class="text-xl font-bold text-gray-800">GeminiPersona</h1>
98
  </div>
99
  <div class="flex items-center space-x-4 space-x-reverse">
100
+ <button onclick="showPage('settings')" class="text-gray-600 hover:text-primary transition-colors">
101
  <i data-feather="settings"></i>
102
+ </button>
103
+ <button onclick="showPage('characters')" class="text-gray-600 hover:text-primary transition-colors">
104
  <i data-feather="users"></i>
105
+ </button>
106
+ <button onclick="showPage('conversations')" class="text-gray-600 hover:text-primary transition-colors">
107
  <i data-feather="message-square"></i>
108
+ </button>
109
+ <button onclick="showPage('voice-chat')" class="text-gray-600 hover:text-primary transition-colors">
110
  <i data-feather="mic"></i>
111
+ </button>
112
+ <button onclick="showPage('chat')" class="text-gray-600 hover:text-primary transition-colors">
113
+ <i data-feather="message-circle"></i>
114
+ </button>
115
  </div>
116
  </div>
117
  </div>
118
  </nav>
119
+ <!-- Home Page -->
120
+ <div id="home" class="page-container active-page">
121
  <div class="max-w-4xl mx-auto py-8 px-4">
122
  <!-- Welcome Section -->
123
  <div class="text-center mb-12">
 
126
  </div>
127
  <!-- Quick Actions -->
128
  <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-12">
129
+ <button onclick="showPage('chat')" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow group">
130
  <div class="text-center">
131
  <i data-feather="message-square" class="w-12 h-12 text-primary mx-auto mb-4 group-hover:scale-110 transition-transform"></i>
132
  <h3 class="text-xl font-semibold text-gray-800 mb-2">بدء محادثة جديدة</h3>
133
  <p class="text-gray-600">ابدأ محادثة مع الذكاء الاصطناعي</p>
134
  </div>
135
+ </button>
136
 
137
+ <button onclick="showPage('voice-chat')" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow group">
138
  <div class="text-center">
139
  <i data-feather="mic" class="w-12 h-12 text-green-500 mx-auto mb-4 group-hover:scale-110 transition-transform"></i>
140
  <h3 class="text-xl font-semibold text-gray-800 mb-2">المحادثة الصوتية</h3>
141
  <p class="text-gray-600">تحدث مع الذكاء الاصطناعي صوتياً</p>
142
  </div>
143
+ </button>
144
 
145
+ <button onclick="showPage('characters')" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow group">
146
  <div class="text-center">
147
  <i data-feather="users" class="w-12 h-12 text-secondary mx-auto mb-4 group-hover:scale-110 transition-transform"></i>
148
  <h3 class="text-xl font-semibold text-gray-800 mb-2">إدارة الشخصيات</h3>
149
  <p class="text-gray-600">أنشئ وعدّل الشخصيات الافتراضية</p>
150
  </div>
151
+ </button>
152
 
153
+ <button onclick="showPage('conversations')" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow group">
154
  <div class="text-center">
155
  <i data-feather="archive" class="w-12 h-12 text-accent mx-auto mb-4 group-hover:scale-110 transition-transform"></i>
156
  <h3 class="text-xl font-semibold text-gray-800 mb-2">المحادثات السابقة</h3>
157
  <p class="text-gray-600">راجع محادثاتك المحفوظة</p>
158
  </div>
159
+ </button>
160
  </div>
161
  <!-- Features Section -->
162
  <div class="bg-white rounded-xl shadow-md p-8 mb-8">
 
225
  </div>
226
  </div>
227
  </div>
228
+ </div>
229
+ </div>
230
+
231
+ <!-- Characters Page -->
232
+ <div id="characters" class="page-container">
233
+ <div class="max-w-6xl mx-auto py-8 px-4">
234
+ <!-- Header with Add Button -->
235
+ <div class="flex justify-between items-center mb-8">
236
+ <div>
237
+ <h2 class="text-2xl font-bold text-gray-800">شخصياتك الافتراضية</h2>
238
+ <p class="text-gray-600 mt-1">إدارة وتعديل الشخصيات الافتراضية التي يمكنك الدردشة معها</p>
239
+ </div>
240
+ <button onclick="openAddCharacterModal()" class="bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors flex items-center space-x-2 space-x-reverse">
241
+ <i data-feather="plus" class="w-4 h-4"></i>
242
+ <span>إضافة شخصية جديدة</span>
243
+ </button>
244
+ </div>
245
+
246
+ <!-- Search and Filter -->
247
+ <div class="bg-white rounded-lg shadow-sm border border-gray-200 p-4 mb-6">
248
+ <div class="flex flex-col md:flex-row gap-4">
249
+ <div class="flex-1">
250
+ <input type="text" id="searchInput" placeholder="ابحث عن شخصية..."
251
+ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
252
+ </div>
253
+ <div class="flex gap-2">
254
+ <select id="sortSelect" class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
255
+ <option value="name">الاسم (أ-ي)</option>
256
+ <option value="nameDesc">الاسم (ي-أ)</option>
257
+ <option value="recent">الأحدث</option>
258
+ <option value="oldest">الأقدم</option>
259
+ </select>
260
+ <button onclick="exportCharacters()" class="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors flex items-center space-x-2 space-x-reverse">
261
+ <i data-feather="download" class="w-4 h-4"></i>
262
+ <span>تصدير</span>
263
+ </button>
264
+ </div>
265
+ </div>
266
+ </div>
267
+ <!-- Characters Grid -->
268
+ <div id="charactersGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
269
+ <!-- Characters will be loaded here -->
270
+ </div>
271
+
272
+ <!-- Load More Button -->
273
+ <div id="loadMoreContainer" class="text-center mt-8 hidden">
274
+ <button onclick="loadMoreCharacters()" class="bg-gray-200 text-gray-700 px-6 py-3 rounded-lg hover:bg-gray-300 transition-colors">
275
+ تحميل المزيد
276
+ </button>
277
+ </div>
278
+ <!-- Empty State -->
279
+ <div id="emptyState" class="text-center py-12 hidden">
280
+ <i data-feather="users" class="w-16 h-16 text-gray-300 mx-auto mb-4"></i>
281
+ <h3 class="text-xl font-semibold text-gray-600 mb-2">لا توجد شخصيات</h3>
282
+ <p class="text-gray-500 mb-6">ابدأ بإضافة أول شخصية افتراضية لك</p>
283
+ <button onclick="openAddCharacterModal()" class="bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors">
284
+ إضافة شخصية جديدة
285
+ </button>
286
+ </div>
287
+ </div>
288
+ </div>
289
+
290
+ <!-- Chat Page -->
291
+ <div id="chat" class="page-container">
292
+ <div class="max-w-4xl mx-auto h-[calc(100vh-4rem)] flex flex-col">
293
+ <!-- Chat Header -->
294
+ <div class="bg-white border-b p-4">
295
+ <div class="flex justify-between items-center">
296
+ <div>
297
+ <h2 class="text-xl font-bold text-gray-800" id="chatTitle">المحادثة الجديدة</h2>
298
+ <p class="text-gray-600 text-sm" id="characterInfo">اختر شخصية للبدء</p>
299
+ </div>
300
+ <div class="flex space-x-2 space-x-reverse">
301
+ <button onclick="saveConversation()" class="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors flex items-center space-x-2 space-x-reverse">
302
+ <i data-feather="save" class="w-4 h-4"></i>
303
+ <span>��فظ</span>
304
+ </button>
305
+ <button onclick="clearChat()" class="bg-red-600 text-white px-4 py-2 rounded-lg hover:bg-red-700 transition-colors flex items-center space-x-2 space-x-reverse">
306
+ <i data-feather="trash-2" class="w-4 h-4"></i>
307
+ <span>مسح</span>
308
+ </button>
309
+ <button onclick="exportChat()" class="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors flex items-center space-x-2 space-x-reverse">
310
+ <i data-feather="download" class="w-4 h-4"></i>
311
+ <span>تصدير</span>
312
+ </button>
313
+ </div>
314
+ </div>
315
+ </div>
316
+
317
+ <!-- Character Selection -->
318
+ <div id="characterSelection" class="bg-white border-b p-4">
319
+ <select id="characterSelect" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
320
+ <option value="">اختر شخصية...</option>
321
+ </select>
322
+ </div>
323
+
324
+ <!-- Messages Container -->
325
+ <div id="messagesContainer" class="flex-1 overflow-y-auto p-4 space-y-4">
326
+ <div class="text-center text-gray-500 py-8">
327
+ <i data-feather="message-circle" class="w-12 h-12 mx-auto mb-4"></i>
328
+ <p>ابدأ محادثة جديدة...</p>
329
+ </div>
330
+ </div>
331
+
332
+ <!-- Input Area -->
333
+ <div class="bg-white border-t p-4">
334
+ <div class="flex space-x-2 space-x-reverse">
335
+ <input type="text" id="messageInput" placeholder="اكتب رسالتك هنا..."
336
+ class="flex-1 px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"
337
+ disabled>
338
+ <button id="sendButton" onclick="sendMessage()" class="bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors" disabled>
339
+ <i data-feather="send" class="w-4 h-4"></i>
340
+ </button>
341
+ </div>
342
+ </div>
343
+ </div>
344
  </div>
345
 
346
+ <!-- Voice Chat Page -->
347
+ <div id="voice-chat" class="page-container">
348
+ <div class="max-w-4xl mx-auto h-[calc(100vh-4rem)] flex flex-col">
349
+ <!-- Voice Chat Header -->
350
+ <div class="bg-white border-b p-4">
351
+ <div class="flex justify-between items-center">
352
+ <div>
353
+ <h2 class="text-xl font-bold text-gray-800">المحادثة الصوتية</h2>
354
+ <p class="text-gray-600 text-sm">تحدث مع الذكاء الاصطناعي صوتياً</p>
355
+ </div>
356
+ <div class="flex space-x-2 space-x-reverse">
357
+ <button onclick="toggleListening()" id="listenButton" class="bg-red-600 text-white px-6 py-3 rounded-lg hover:bg-red-700 transition-colors flex items-center space-x-2 space-x-reverse">
358
+ <i data-feather="mic" class="w-4 h-4"></i>
359
+ <span>بدء الاستماع</span>
360
+ </button>
361
+ </div>
362
+ </div>
363
+ </div>
364
+
365
+ <!-- Character Selection -->
366
+ <div class="bg-white border-b p-4">
367
+ <select id="voiceCharacterSelect" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
368
+ <option value="">اختر شخصية...</option>
369
+ </select>
370
+ </div>
371
+
372
+ <!-- Messages Container -->
373
+ <div id="voiceMessagesContainer" class="flex-1 overflow-y-auto p-4 space-y-4">
374
+ <div class="text-center text-gray-500 py-8">
375
+ <i data-feather="mic" class="w-12 h-12 mx-auto mb-4"></i>
376
+ <p>انقر على "بدء الاستماع" للبدء...</p>
377
+ </div>
378
+ </div>
379
+
380
+ <!-- Status -->
381
+ <div class="bg-white border-t p-4">
382
+ <div id="voiceStatus" class="text-center text-gray-600">
383
+ جاهز للاستماع...
384
+ </div>
385
+ </div>
386
+ </div>
387
+ </div>
388
+
389
+ <!-- Conversations Page -->
390
+ <div id="conversations" class="page-container">
391
+ <div class="max-w-6xl mx-auto py-8 px-4">
392
+ <!-- Header -->
393
+ <div class="flex justify-between items-center mb-8">
394
+ <div>
395
+ <h2 class="text-2xl font-bold text-gray-800">المحادثات السابقة</h2>
396
+ <p class="text-gray-600 mt-1">راجع وأعد فتح المحادثات المحفوظة</p>
397
+ </div>
398
+ </div>
399
+
400
+ <!-- Search and Filter -->
401
+ <div class="bg-white rounded-lg shadow-sm border border-gray-200 p-4 mb-6">
402
+ <div class="flex flex-col md:flex-row gap-4">
403
+ <div class="flex-1">
404
+ <input type="text" id="conversationSearch" placeholder="ابحث في المحادثات..."
405
+ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
406
+ </div>
407
+ <div class="flex gap-2">
408
+ <select id="conversationSort" class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
409
+ <option value="recent">الأحدث</option>
410
+ <option value="oldest">الأقدم</option>
411
+ <option value="title">العنوان (أ-ي)</option>
412
+ </select>
413
+ <button onclick="exportAllConversations()" class="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors flex items-center space-x-2 space-x-reverse">
414
+ <i data-feather="download" class="w-4 h-4"></i>
415
+ <span>تصدير الكل</span>
416
+ </button>
417
+ </div>
418
+ </div>
419
+ </div>
420
+
421
+ <!-- Conversations List -->
422
+ <div id="conversationsList" class="space-y-4">
423
+ <!-- Conversations will be loaded here -->
424
+ </div>
425
+
426
+ <!-- Empty State -->
427
+ <div id="conversationsEmptyState" class="text-center py-12 hidden">
428
+ <i data-feather="message-square" class="w-16 h-16 text-gray-300 mx-auto mb-4"></i>
429
+ <h3 class="text-xl font-semibold text-gray-600 mb-2">لا توجد محادثات</h3>
430
+ <p class="text-gray-500">ابدأ محادثة جديدة لحفظها هنا</p>
431
+ </div>
432
+ </div>
433
+ </div>
434
+
435
+ <!-- Settings Page -->
436
+ <div id="settings" class="page-container">
437
+ <div class="max-w-4xl mx-auto py-8 px-4">
438
+ <!-- Header -->
439
+ <div class="mb-8">
440
+ <h2 class="text-2xl font-bold text-gray-800">الإعدادات</h2>
441
+ <p class="text-gray-600 mt-1">إعدادات التطبيق والمظهر</p>
442
+ </div>
443
+
444
+ <!-- Settings Sections -->
445
+ <div class="space-y-6">
446
+ <!-- API Settings -->
447
+ <div class="bg-white rounded-xl shadow-md p-6">
448
+ <h3 class="text-xl font-semibold text-gray-800 mb-4">إعدادات API</h3>
449
+ <div class="space-y-4">
450
+ <div>
451
+ <label for="apiKey" class="block text-sm font-medium text-gray-700 mb-2">مفتاح Gemini API</label>
452
+ <input type="password" id="apiKey"
453
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"
454
+ placeholder="أدخل مفتاح API الخاص بك">
455
+ <p class="text-sm text-gray-500 mt-1">يمكنك الحصول على مفتاح API من <a href="https://aistudio.google.com/" class="text-primary hover:underline" target="_blank">Google AI Studio</a></p>
456
+ </div>
457
+ <button onclick="saveApiKey()" class="bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors">
458
+ حفظ الإعدادات
459
+ </button>
460
+ </div>
461
+ </div>
462
+
463
+ <!-- Appearance Settings -->
464
+ <div class="bg-white rounded-xl shadow-md p-6">
465
+ <h3 class="text-xl font-semibold text-gray-800 mb-4">الإعدادات العامة</h3>
466
+ <div class="space-y-4">
467
+ <div>
468
+ <label for="language" class="block text-sm font-medium text-gray-700 mb-2">اللغة</label>
469
+ <select id="language" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
470
+ <option value="ar">العربية</option>
471
+ <option value="en">English</option>
472
+ </select>
473
+ </div>
474
+ <div>
475
+ <label for="theme" class="block text-sm font-medium text-gray-700 mb-2">المظهر</label>
476
+ <select id="theme" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
477
+ <option value="light">فاتح</option>
478
+ <option value="dark">داكن</option>
479
+ <option value="auto">تلقائي</option>
480
+ </select>
481
+ </div>
482
+ <button onclick="saveGeneralSettings()" class="bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors">
483
+ حفظ الإعدادات
484
+ </button>
485
+ </div>
486
+ </div>
487
+
488
+ <!-- Data Management -->
489
+ <div class="bg-white rounded-xl shadow-md p-6">
490
+ <h3 class="text-xl font-semibold text-gray-800 mb-4">إدارة البيانات</h3>
491
+ <div class="space-y-4">
492
+ <div class="flex justify-between items-center">
493
+ <div>
494
+ <h4 class="font-medium text-gray-800">مسح جميع البيانات</h4>
495
+ <p class="text-sm text-gray-600">سيتم حذف جميع المحادثات والشخصيات والإعدادات</p>
496
+ </div>
497
+ <button onclick="clearAllData()" class="bg-red-600 text-white px-6 py-3 rounded-lg hover:bg-red-700 transition-colors">
498
+ مسح الكل
499
+ </button>
500
+ </div>
501
+ <div class="flex justify-between items-center">
502
+ <div>
503
+ <h4 class="font-medium text-gray-800">تصدير البيانات</h4>
504
+ <p class="text-sm text-gray-600">تحميل نسخة احتياطية من جميع البيانات</p>
505
+ </div>
506
+ <button onclick="exportAllData()" class="bg-green-600 text-white px-6 py-3 rounded-lg hover:bg-green-700 transition-colors">
507
+ تصدير الكل
508
+ </button>
509
+ </div>
510
+ </div>
511
+ </div>
512
+ </div>
513
+ </div>
514
+ </div>
515
+
516
+ <!-- Add/Edit Character Modal -->
517
+ <div id="characterModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50 hidden">
518
+ <div class="bg-white rounded-xl shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto">
519
+ <div class="p-6">
520
+ <div class="flex justify-between items-center mb-6">
521
+ <h3 id="modalTitle" class="text-xl font-bold text-gray-800">إضافة شخصية جديدة</h3>
522
+ <button onclick="closeCharacterModal()" class="text-gray-400 hover:text-gray-600">
523
+ <i data-feather="x" class="w-6 h-6"></i>
524
+ </button>
525
+ </div>
526
+
527
+ <form id="characterForm" class="space-y-4">
528
+ <input type="hidden" id="characterId">
529
+
530
+ <div>
531
+ <label for="characterName" class="block text-sm font-medium text-gray-700 mb-2">اسم الشخصية</label>
532
+ <input type="text" id="characterName" required
533
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
534
+ </div>
535
+
536
+ <div>
537
+ <label for="characterRole" class="block text-sm font-medium text-gray-700 mb-2">الدور/المهنة</label>
538
+ <input type="text" id="characterRole"
539
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
540
+ </div>
541
+
542
+ <div>
543
+ <label for="characterDescription" class="block text-sm font-medium text-gray-700 mb-2">الوصف</label>
544
+ <textarea id="characterDescription" rows="4"
545
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"
546
+ placeholder="صف شخصية الذكاء الاصطناعي ودوره وطريقة تحدثه..."></textarea>
547
+ </div>
548
+
549
+ <div>
550
+ <label for="characterInstructions" class="block text-sm font-medium text-gray-700 mb-2">التعليمات الخاصة</label>
551
+ <textarea id="characterInstructions" rows="4"
552
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"
553
+ placeholder="أدخل التعليمات الخاصة بالشخصية..."></textarea>
554
+ </div>
555
+
556
+ <div class="flex justify-end space-x-3 space-x-reverse pt-4">
557
+ <button type="button" onclick="closeCharacterModal()" class="px-6 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors">
558
+ إلغاء
559
+ </button>
560
+ <button type="submit" class="px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors">
561
+ حفظ الشخصية
562
+ </button>
563
+ </div>
564
+ </form>
565
+ </div>
566
+ </div>
567
+ </div>
568
  <script>
569
+ // Global variables
570
+ let characters = [];
571
+ let filteredCharacters = [];
572
+ let currentPage = 1;
573
+ const charactersPerPage = 9;
574
+ let currentSort = 'recent';
575
+ let currentConversationId = null;
576
+ let isListening = false;
577
+ let recognition = null;
578
+
579
  // Initialize database
580
  function initDB() {
581
  if (!window.indexedDB) {
 
611
  }
612
  };
613
  }
614
+
615
+ // Page navigation
616
+ function showPage(pageName) {
617
+ // Hide all pages
618
+ document.querySelectorAll('.page-container').forEach(page => {
619
+ page.classList.remove('active-page');
620
+ });
621
+
622
+ // Show the selected page
623
+ document.getElementById(pageName).classList.add('active-page');
624
+
625
+ // Update page-specific content
626
+ if (pageName === 'characters') {
627
+ loadCharacters();
628
+ } else if (pageName === 'conversations') {
629
+ loadConversations();
630
+ } else if (pageName === 'chat') {
631
+ loadCharacterSelect();
632
+ } else if (pageName === 'voice-chat') {
633
+ loadVoiceCharacterSelect();
634
+ initSpeechRecognition();
635
+ } else if (pageName === 'settings') {
636
+ loadSettings();
637
+ } else if (pageName === 'home') {
638
+ loadStatistics();
639
+ }
640
+
641
+ feather.replace();
642
+ }
643
+
644
  // Initialize app
645
  document.addEventListener('DOMContentLoaded', function() {
646
  initDB();
647
  feather.replace();
648
  loadStatistics();
649
+ showPage('home');
650
  });
651
 
652
  // Load statistics
 
678
  };
679
  };
680
  }
681
+
682
+ // Characters functionality
683
+ // Load characters from IndexedDB
684
+ function loadCharacters() {
685
+ const request = indexedDB.open("GeminiPersonaDB", 1);
686
+
687
+ request.onsuccess = function(event) {
688
+ const db = event.target.result;
689
+ const transaction = db.transaction(['characters'], 'readonly');
690
+ const store = transaction.objectStore('characters');
691
+ const getAllRequest = store.getAll();
692
+
693
+ getAllRequest.onsuccess = function() {
694
+ characters = getAllRequest.result;
695
+ sortCharacters(currentSort);
696
+ filterCharacters();
697
+ renderCharacters();
698
+ };
699
+ };
700
+ }
701
+
702
+ // Sort characters
703
+ function sortCharacters(sortType) {
704
+ currentSort = sortType;
705
+ switch(sortType) {
706
+ case 'name':
707
+ characters.sort((a, b) => a.name.localeCompare(b.name));
708
+ break;
709
+ case 'nameDesc':
710
+ characters.sort((a, b) => b.name.localeCompare(a.name));
711
+ break;
712
+ case 'recent':
713
+ characters.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
714
+ break;
715
+ case 'oldest':
716
+ characters.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt));
717
+ break;
718
+ }
719
+ }
720
+
721
+ // Filter characters
722
+ function filterCharacters() {
723
+ const searchTerm = document.getElementById('searchInput').value.toLowerCase();
724
+ if (searchTerm) {
725
+ filteredCharacters = characters.filter(character =>
726
+ character.name.toLowerCase().includes(searchTerm) ||
727
+ (character.role && character.role.toLowerCase().includes(searchTerm)) ||
728
+ (character.description && character.description.toLowerCase().includes(searchTerm))
729
+ );
730
+ } else {
731
+ filteredCharacters = [...characters];
732
+ }
733
+ }
734
+
735
+ // Load more characters
736
+ function loadMoreCharacters() {
737
+ currentPage++;
738
+ renderCharacters();
739
+ }
740
+
741
+ // Render characters grid
742
+ function renderCharacters() {
743
+ const grid = document.getElementById('charactersGrid');
744
+ const emptyState = document.getElementById('emptyState');
745
+ const loadMoreContainer = document.getElementById('loadMoreContainer');
746
+
747
+ filterCharacters();
748
+
749
+ if (filteredCharacters.length === 0) {
750
+ grid.classList.add('hidden');
751
+ emptyState.classList.remove('hidden');
752
+ loadMoreContainer.classList.add('hidden');
753
+ return;
754
+ }
755
+
756
+ grid.classList.remove('hidden');
757
+ emptyState.classList.add('hidden');
758
+
759
+ const startIndex = 0;
760
+ const endIndex = currentPage * charactersPerPage;
761
+ const charactersToShow = filteredCharacters.slice(0, endIndex);
762
+
763
+ grid.innerHTML = charactersToShow.map(character => `
764
+ <div class="character-card bg-white rounded-xl shadow-md p-6">
765
+ <div class="flex justify-between items-start mb-4">
766
+ <div>
767
+ <h3 class="text-lg font-semibold text-gray-800">${character.name}</h3>
768
+ ${character.role ? `<p class="text-sm text-gray-600">${character.role}</p>` : ''}
769
+ </div>
770
+ <div class="flex space-x-2 space-x-reverse">
771
+ <button onclick="editCharacter(${character.id})" class="text-blue-600 hover:text-blue-800 transition-colors">
772
+ <i data-feather="edit-2" class="w-4 h-4"></i>
773
+ </button>
774
+ <button onclick="duplicateCharacter(${character.id})" class="text-green-600 hover:text-green-800 transition-colors">
775
+ <i data-feather="copy" class="w-4 h-4"></i>
776
+ </button>
777
+ <button onclick="deleteCharacter(${character.id})" class="text-red-600 hover:text-red-800 transition-colors">
778
+ <i data-feather="trash-2" class="w-4 h-4"></i>
779
+ </button>
780
+ </div>
781
+ </div>
782
+ ${character.description ? `<p class="text-gray-700 text-sm mb-4 line-clamp-3">${character.description}</p>` : ''}
783
+ <div class="flex space-x-2 space-x-reverse">
784
+ <button onclick="startChatWithCharacter(${character.id})" class="flex-1 bg-primary text-white py-2 px-4 rounded-lg hover:bg-primary/90 transition-colors text-sm">
785
+ بدء محادثة
786
+ </button>
787
+ <button onclick="startVoiceChatWithCharacter(${character.id})" class="bg-green-600 text-white p-2 rounded-lg hover:bg-green-700 transition-colors">
788
+ <i data-feather="mic" class="w-4 h-4"></i>
789
+ </button>
790
+ </div>
791
+ </div>
792
+ `).join('');
793
+
794
+ // Show/hide load more button
795
+ if (endIndex < filteredCharacters.length) {
796
+ loadMoreContainer.classList.remove('hidden');
797
+ } else {
798
+ loadMoreContainer.classList.add('hidden');
799
+ }
800
+
801
+ feather.replace();
802
+ }
803
+
804
+ // Open add character modal
805
+ function openAddCharacterModal() {
806
+ document.getElementById('characterModal').classList.remove('hidden');
807
+ document.getElementById('modalTitle').textContent = 'إضافة شخصية جديدة';
808
+ document.getElementById('characterForm').reset();
809
+ document.getElementById('characterId').value = '';
810
+ }
811
+
812
+ // Close character modal
813
+ function closeCharacterModal() {
814
+ document.getElementById('characterModal').classList.add('hidden');
815
+ }
816
+
817
+ // Edit character
818
+ function editCharacter(id) {
819
+ const character = characters.find(c => c.id === id);
820
+ if (!character) return;
821
+
822
+ document.getElementById('characterModal').classList.remove('hidden');
823
+ document.getElementById('modalTitle').textContent = 'تعديل الشخصية';
824
+ document.getElementById('characterId').value = character.id;
825
+ document.getElementById('characterName').value = character.name;
826
+ document.getElementById('characterRole').value = character.role || '';
827
+ document.getElementById('characterDescription').value = character.description || '';
828
+ document.getElementById('characterInstructions').value = character.instructions || '';
829
+ }
830
+
831
+ // Delete character
832
+ function deleteCharacter(id) {
833
+ if (!confirm('هل أنت متأكد من حذف هذه الشخصية؟')) return;
834
+
835
+ const request = indexedDB.open("GeminiPersonaDB", 1);
836
+
837
+ request.onsuccess = function(event) {
838
+ const db = event.target.result;
839
+ const transaction = db.transaction(['characters'], 'readwrite');
840
+ const store = transaction.objectStore('characters');
841
+ store.delete(id);
842
+
843
+ transaction.oncomplete = function() {
844
+ characters = characters.filter(c => c.id !== id);
845
+ renderCharacters();
846
+ };
847
+ };
848
+ }
849
+
850
+ // Start chat with character
851
+ function startChatWithCharacter(characterId) {
852
+ const character = characters.find(c => c.id === characterId);
853
+ if (character) {
854
+ localStorage.setItem('selectedCharacter', JSON.stringify(character));
855
+ showPage('chat');
856
+ loadCharacterSelect();
857
+ }
858
+ }
859
+
860
+ // Start voice chat with character
861
+ function startVoiceChatWithCharacter(characterId) {
862
+ const character = characters.find(c => c.id === characterId);
863
+ if (character) {
864
+ localStorage.setItem('selectedCharacter', JSON.stringify(character));
865
+ showPage('voice-chat');
866
+ loadVoiceCharacterSelect();
867
+ }
868
+ }
869
+
870
+ // Duplicate character
871
+ function duplicateCharacter(id) {
872
+ const character = characters.find(c => c.id === id);
873
+ if (!character) return;
874
+
875
+ const duplicatedCharacter = {
876
+ ...character,
877
+ name: `${character.name} (نسخة)`,
878
+ createdAt: new Date().toISOString()
879
+ };
880
+ delete duplicatedCharacter.id;
881
+
882
+ const request = indexedDB.open("GeminiPersonaDB", 1);
883
+
884
+ request.onsuccess = function(event) {
885
+ const db = event.target.result;
886
+ const transaction = db.transaction(['characters'], 'readwrite');
887
+ const store = transaction.objectStore('characters');
888
+ store.add(duplicatedCharacter);
889
+
890
+ transaction.oncomplete = function() {
891
+ loadCharacters();
892
+ };
893
+ };
894
+ }
895
+
896
+ // Export characters
897
+ function exportCharacters() {
898
+ const dataStr = JSON.stringify(characters, null, 2);
899
+ const dataBlob = new Blob([dataStr], {type: 'application/json'});
900
+ const url = URL.createObjectURL(dataBlob);
901
+ const link = document.createElement('a');
902
+ link.href = url;
903
+ link.download = `gemini-persona-characters-${new Date().toISOString().split('T')[0]}.json`;
904
+ document.body.appendChild(link);
905
+ link.click();
906
+ document.body.removeChild(link);
907
+ URL.revokeObjectURL(url);
908
+ }
909
+
910
+ // Handle form submission
911
+ document.getElementById('characterForm').addEventListener('submit', function(e) {
912
+ e.preventDefault();
913
+
914
+ const characterData = {
915
+ name: document.getElementById('characterName').value,
916
+ role: document.getElementById('characterRole').value,
917
+ description: document.getElementById('characterDescription').value,
918
+ instructions: document.getElementById('characterInstructions').value,
919
+ createdAt: new Date().toISOString()
920
+ };
921
+
922
+ const characterId = document.getElementById('characterId').value;
923
+
924
+ const request = indexedDB.open("GeminiPersonaDB", 1);
925
+
926
+ request.onsuccess = function(event) {
927
+ const db = event.target.result;
928
+ const transaction = db.transaction(['characters'], 'readwrite');
929
+ const store = transaction.objectStore('characters');
930
+
931
+ if (characterId) {
932
+ // Update existing character
933
+ characterData.id = parseInt(characterId);
934
+ store.put(characterData);
935
+ } else {
936
+ // Add new character
937
+ store.add(characterData);
938
+ }
939
+
940
+ transaction.oncomplete = function() {
941
+ closeCharacterModal();
942
+ loadCharacters();
943
+ };
944
+ };
945
+ });
946
+
947
+ // Chat functionality
948
+ function loadCharacterSelect() {
949
+ const select = document.getElementById('characterSelect');
950
+ const request = indexedDB.open("GeminiPersonaDB", 1);
951
+
952
+ request.onsuccess = function(event) {
953
+ const db = event.target.result;
954
+ const transaction = db.transaction(['characters'], 'readonly');
955
+ const store = transaction.objectStore('characters');
956
+ const getAllRequest = store.getAll();
957
+
958
+ getAllRequest.onsuccess = function() {
959
+ const characters = getAllRequest.result;
960
+ select.innerHTML = '<option value="">اختر شخصية...</option>';
961
+ characters.forEach(character => {
962
+ const option = document.createElement('option');
963
+ option.value = character.id;
964
+ option.textContent = character.name;
965
+ select.appendChild(option);
966
+ });
967
+
968
+ // Check if there's a selected character in localStorage
969
+ const selectedCharacter = localStorage.getItem('selectedCharacter');
970
+ if (selectedCharacter) {
971
+ const character = JSON.parse(selectedCharacter);
972
+ select.value = character.id;
973
+ updateChatUI(character);
974
+ }
975
+ };
976
+ };
977
+ }
978
+
979
+ function updateChatUI(character) {
980
+ document.getElementById('characterInfo').textContent = `تتحدث مع: ${character.name}`;
981
+ document.getElementById('messageInput').disabled = false;
982
+ document.getElementById('sendButton').disabled = false;
983
+ }
984
+
985
+ async function sendMessage() {
986
+ const messageInput = document.getElementById('messageInput');
987
+ const message = messageInput.value.trim();
988
+ if (!message) return;
989
+
990
+ const characterSelect = document.getElementById('characterSelect');
991
+ const characterId = characterSelect.value;
992
+ if (!characterId) {
993
+ alert('يرجى اختيار شخصية أولاً');
994
+ return;
995
+ }
996
+
997
+ // Add user message to chat
998
+ addMessageToChat('user', message);
999
+ messageInput.value = '';
1000
+
1001
+ // Get character info
1002
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1003
+ request.onsuccess = function(event) {
1004
+ const db = event.target.result;
1005
+ const transaction = db.transaction(['characters'], 'readonly');
1006
+ const store = transaction.objectStore('characters');
1007
+ const getRequest = store.get(parseInt(characterId));
1008
+
1009
+ getRequest.onsuccess = function() {
1010
+ const character = getRequest.result;
1011
+ // Simulate AI response (replace with actual API call)
1012
+ setTimeout(() => {
1013
+ addMessageToChat('ai', `هذه استجابة محاكاة من ${character.name}: ${message}`, character);
1014
+ }, 1000);
1015
+ };
1016
+ };
1017
+ }
1018
+
1019
+ function addMessageToChat(sender, content, character = null) {
1020
+ const messagesContainer = document.getElementById('messagesContainer');
1021
+ const messageDiv = document.createElement('div');
1022
+ messageDiv.className = `flex ${sender === 'user' ? 'justify-end' : 'justify-start'}`;
1023
+
1024
+ const bubbleClass = sender === 'user' ? 'chat-bubble-user' : 'chat-bubble-ai';
1025
+ const bubble = document.createElement('div');
1026
+ bubble.className = `${bubbleClass} max-w-xs md:max-w-md lg:max-w-lg px-4 py-2`;
1027
+
1028
+ if (sender === 'ai' && character) {
1029
+ const nameDiv = document.createElement('div');
1030
+ nameDiv.className = 'font-semibold text-sm mb-1';
1031
+ nameDiv.textContent = character.name;
1032
+ bubble.appendChild(nameDiv);
1033
+ }
1034
+
1035
+ const contentDiv = document.createElement('div');
1036
+ contentDiv.className = 'markdown-content';
1037
+ contentDiv.innerHTML = marked.parse(content);
1038
+ bubble.appendChild(contentDiv);
1039
+
1040
+ messageDiv.appendChild(bubble);
1041
+ messagesContainer.appendChild(messageDiv);
1042
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
1043
+ }
1044
+
1045
+ function saveConversation() {
1046
+ // Implementation for saving conversation
1047
+ alert('تم حفظ المحادثة');
1048
+ }
1049
+
1050
+ function clearChat() {
1051
+ document.getElementById('messagesContainer').innerHTML = `
1052
+ <div class="text-center text-gray-500 py-8">
1053
+ <i data-feather="message-circle" class="w-12 h-12 mx-auto mb-4"></i>
1054
+ <p>ابدأ محادثة جديدة...</p>
1055
+ </div>
1056
+ `;
1057
+ feather.replace();
1058
+ }
1059
+
1060
+ function exportChat() {
1061
+ // Implementation for exporting chat
1062
+ alert('تم تصدير المحادثة');
1063
+ }
1064
+
1065
+ // Voice chat functionality
1066
+ function loadVoiceCharacterSelect() {
1067
+ const select = document.getElementById('voiceCharacterSelect');
1068
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1069
+
1070
+ request.onsuccess = function(event) {
1071
+ const db = event.target.result;
1072
+ const transaction = db.transaction(['characters'], 'readonly');
1073
+ const store = transaction.objectStore('characters');
1074
+ const getAllRequest = store.getAll();
1075
+
1076
+ getAllRequest.onsuccess = function() {
1077
+ const characters = getAllRequest.result;
1078
+ select.innerHTML = '<option value="">اختر شخصية...</option>';
1079
+ characters.forEach(character => {
1080
+ const option = document.createElement('option');
1081
+ option.value = character.id;
1082
+ option.textContent = character.name;
1083
+ select.appendChild(option);
1084
+ });
1085
+
1086
+ // Check if there's a selected character in localStorage
1087
+ const selectedCharacter = localStorage.getItem('selectedCharacter');
1088
+ if (selectedCharacter) {
1089
+ const character = JSON.parse(selectedCharacter);
1090
+ select.value = character.id;
1091
+ }
1092
+ };
1093
+ };
1094
+ }
1095
+
1096
+ function initSpeechRecognition() {
1097
+ if ('webkitSpeechRecognition' in window) {
1098
+ recognition = new webkitSpeechRecognition();
1099
+ recognition.continuous = false;
1100
+ recognition.interimResults = false;
1101
+ recognition.lang = 'ar-SA';
1102
+
1103
+ recognition.onstart = function() {
1104
+ isListening = true;
1105
+ document.getElementById('listenButton').innerHTML = '<i data-feather="square" class="w-4 h-4"></i><span>إيقاف الاستماع</span>';
1106
+ document.getElementById('voiceStatus').textContent = 'جاري الاستماع...';
1107
+ feather.replace();
1108
+ };
1109
+
1110
+ recognition.onresult = function(event) {
1111
+ const transcript = event.results[0][0].transcript;
1112
+ addVoiceMessage('user', transcript);
1113
+
1114
+ // Simulate AI response
1115
+ setTimeout(() => {
1116
+ addVoiceMessage('ai', `تم استقبال رسالتك: "${transcript}"`);
1117
+ }, 1000);
1118
+ };
1119
+
1120
+ recognition.onerror = function(event) {
1121
+ console.error('Speech recognition error', event.error);
1122
+ document.getElementById('voiceStatus').textContent = 'خطأ في التعرف على الصوت';
1123
+ };
1124
+
1125
+ recognition.onend = function() {
1126
+ isListening = false;
1127
+ document.getElementById('listenButton').innerHTML = '<i data-feather="mic" class="w-4 h-4"></i><span>بدء الاستماع</span>';
1128
+ document.getElementById('voiceStatus').textContent = 'جاهز للاستماع...';
1129
+ feather.replace();
1130
+ };
1131
+ } else {
1132
+ alert('متصفحك لا يدعم التعرف على الصوت');
1133
+ }
1134
+ }
1135
+
1136
+ function toggleListening() {
1137
+ if (!recognition) return;
1138
+
1139
+ if (isListening) {
1140
+ recognition.stop();
1141
+ } else {
1142
+ const characterSelect = document.getElementById('voiceCharacterSelect');
1143
+ if (!characterSelect.value) {
1144
+ alert('يرجى اختيار شخصية أولاً');
1145
+ return;
1146
+ }
1147
+ recognition.start();
1148
+ }
1149
+ }
1150
+
1151
+ function addVoiceMessage(sender, content) {
1152
+ const messagesContainer = document.getElementById('voiceMessagesContainer');
1153
+ const messageDiv = document.createElement('div');
1154
+ messageDiv.className = `flex ${sender === 'user' ? 'justify-end' : 'justify-start'}`;
1155
+
1156
+ const bubbleClass = sender === 'user' ? 'chat-bubble-user' : 'chat-bubble-ai';
1157
+ const bubble = document.createElement('div');
1158
+ bubble.className = `${bubbleClass} max-w-xs md:max-w-md lg:max-w-lg px-4 py-2`;
1159
+ bubble.textContent = content;
1160
+
1161
+ messageDiv.appendChild(bubble);
1162
+ messagesContainer.appendChild(messageDiv);
1163
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
1164
+ }
1165
+
1166
+ // Conversations functionality
1167
+ function loadConversations() {
1168
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1169
+
1170
+ request.onsuccess = function(event) {
1171
+ const db = event.target.result;
1172
+ const transaction = db.transaction(['conversations'], 'readonly');
1173
+ const store = transaction.objectStore('conversations');
1174
+ const getAllRequest = store.getAll();
1175
+
1176
+ getAllRequest.onsuccess = function() {
1177
+ const conversations = getAllRequest.result;
1178
+ renderConversations(conversations);
1179
+ };
1180
+ };
1181
+ }
1182
+
1183
+ function renderConversations(conversations) {
1184
+ const container = document.getElementById('conversationsList');
1185
+ const emptyState = document.getElementById('conversationsEmptyState');
1186
+
1187
+ if (conversations.length === 0) {
1188
+ container.classList.add('hidden');
1189
+ emptyState.classList.remove('hidden');
1190
+ return;
1191
+ }
1192
+
1193
+ container.classList.remove('hidden');
1194
+ emptyState.classList.add('hidden');
1195
+
1196
+ container.innerHTML = conversations.map(conv => `
1197
+ <div class="bg-white rounded-lg shadow-sm border border-gray-200 p-4 hover:shadow-md transition-shadow">
1198
+ <div class="flex justify-between items-start">
1199
+ <div class="flex-1">
1200
+ <h3 class="text-lg font-semibold text-gray-800">${conv.title || 'محادثة بدون عنوان'}</h3>
1201
+ <p class="text-gray-600 text-sm mt-1">${new Date(conv.createdAt).toLocaleString('ar-SA')}</p>
1202
+ <p class="text-gray-500 text-sm mt-2">${conv.messages ? conv.messages.length + ' رسالة' : 'لا توجد رسائل'}</p>
1203
+ </div>
1204
+ <div class="flex space-x-2 space-x-reverse">
1205
+ <button onclick="loadConversation(${conv.id})" class="bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary/90 transition-colors text-sm">
1206
+ فتح
1207
+ </button>
1208
+ <button onclick="deleteConversation(${conv.id})" class="bg-red-600 text-white px-4 py-2 rounded-lg hover:bg-red-700 transition-colors text-sm">
1209
+ حذف
1210
+ </button>
1211
+ </div>
1212
+ </div>
1213
+ </div>
1214
+ `).join('');
1215
+ }
1216
+
1217
+ function deleteConversation(id) {
1218
+ if (!confirm('هل أنت متأكد من حذف هذه المحادثة؟')) return;
1219
+
1220
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1221
+
1222
+ request.onsuccess = function(event) {
1223
+ const db = event.target.result;
1224
+ const transaction = db.transaction(['conversations'], 'readwrite');
1225
+ const store = transaction.objectStore('conversations');
1226
+ store.delete(id);
1227
+
1228
+ transaction.oncomplete = function() {
1229
+ loadConversations();
1230
+ };
1231
+ };
1232
+ }
1233
+
1234
+ function exportAllConversations() {
1235
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1236
+
1237
+ request.onsuccess = function(event) {
1238
+ const db = event.target.result;
1239
+ const transaction = db.transaction(['conversations'], 'readonly');
1240
+ const store = transaction.objectStore('conversations');
1241
+ const getAllRequest = store.getAll();
1242
+
1243
+ getAllRequest.onsuccess = function() {
1244
+ const conversations = getAllRequest.result;
1245
+ const dataStr = JSON.stringify(conversations, null, 2);
1246
+ const dataBlob = new Blob([dataStr], {type: 'application/json'});
1247
+ const url = URL.createObjectURL(dataBlob);
1248
+ const link = document.createElement('a');
1249
+ link.href = url;
1250
+ link.download = `gemini-persona-conversations-${new Date().toISOString().split('T')[0]}.json`;
1251
+ document.body.appendChild(link);
1252
+ link.click();
1253
+ document.body.removeChild(link);
1254
+ URL.revokeObjectURL(url);
1255
+ };
1256
+ };
1257
+ }
1258
+
1259
+ // Settings functionality
1260
+ function loadSettings() {
1261
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1262
+
1263
+ request.onsuccess = function(event) {
1264
+ const db = event.target.result;
1265
+ const transaction = db.transaction(['settings'], 'readonly');
1266
+ const store = transaction.objectStore('settings');
1267
+ const getRequest = store.get('apiKey');
1268
+
1269
+ getRequest.onsuccess = function() {
1270
+ if (getRequest.result) {
1271
+ document.getElementById('apiKey').value = getRequest.result.value || '';
1272
+ }
1273
+ };
1274
+
1275
+ const getSettingsRequest = store.get('general');
1276
+ getSettingsRequest.onsuccess = function() {
1277
+ if (getSettingsRequest.result) {
1278
+ const settings = getSettingsRequest.result;
1279
+ document.getElementById('language').value = settings.language || 'ar';
1280
+ document.getElementById('theme').value = settings.theme || 'light';
1281
+ }
1282
+ };
1283
+ };
1284
+ }
1285
+
1286
+ function saveApiKey() {
1287
+ const apiKey = document.getElementById('apiKey').value;
1288
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1289
+
1290
+ request.onsuccess = function(event) {
1291
+ const db = event.target.result;
1292
+ const transaction = db.transaction(['settings'], 'readwrite');
1293
+ const store = transaction.objectStore('settings');
1294
+ store.put({ id: 'apiKey', value: apiKey });
1295
+
1296
+ transaction.oncomplete = function() {
1297
+ alert('تم حفظ مفتاح API');
1298
+ };
1299
+ };
1300
+ }
1301
+
1302
+ function saveGeneralSettings() {
1303
+ const language = document.getElementById('language').value;
1304
+ const theme = document.getElementById('theme').value;
1305
+
1306
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1307
+
1308
+ request.onsuccess = function(event) {
1309
+ const db = event.target.result;
1310
+ const transaction = db.transaction(['settings'], 'readwrite');
1311
+ const store = transaction.objectStore('settings');
1312
+ store.put({ id: 'general', language, theme });
1313
+
1314
+ transaction.oncomplete = function() {
1315
+ alert('تم حفظ الإعدادات');
1316
+ };
1317
+ };
1318
+ }
1319
+
1320
+ function clearAllData() {
1321
+ if (!confirm('هل أنت متأكد من مسح جميع البيانات؟ لا يمكن التراجع عن هذا الإجراء.')) return;
1322
+
1323
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1324
+
1325
+ request.onsuccess = function(event) {
1326
+ const db = event.target.result;
1327
+
1328
+ const transaction = db.transaction(['conversations', 'characters', 'settings'], 'readwrite');
1329
+
1330
+ transaction.objectStore('conversations').clear();
1331
+ transaction.objectStore('characters').clear();
1332
+ transaction.objectStore('settings').clear();
1333
+
1334
+ transaction.oncomplete = function() {
1335
+ alert('تم مسح جميع البيانات');
1336
+ location.reload();
1337
+ };
1338
+ };
1339
+ }
1340
+
1341
+ function exportAllData() {
1342
+ const request = indexedDB.open("GeminiPersonaDB", 1);
1343
+
1344
+ request.onsuccess = function(event) {
1345
+ const db = event.target.result;
1346
+ const transaction = db.transaction(['conversations', 'characters', 'settings'], 'readonly');
1347
+
1348
+ const conversationsStore = transaction.objectStore('conversations');
1349
+ const charactersStore = transaction.objectStore('characters');
1350
+ const settingsStore = transaction.objectStore('settings');
1351
+
1352
+ Promise.all([
1353
+ new Promise(resolve => conversationsStore.getAll().onsuccess = e => resolve(e.target.result)),
1354
+ new Promise(resolve => charactersStore.getAll().onsuccess = e => resolve(e.target.result)),
1355
+ new Promise(resolve => settingsStore.getAll().onsuccess = e => resolve(e.target.result))
1356
+ ]).then(([conversations, characters, settings]) => {
1357
+ const data = {
1358
+ conversations,
1359
+ characters,
1360
+ settings,
1361
+ exportDate: new Date().toISOString()
1362
+ };
1363
+
1364
+ const dataStr = JSON.stringify(data, null, 2);
1365
+ const dataBlob = new Blob([dataStr], {type: 'application/json'});
1366
+ const url = URL.createObjectURL(dataBlob);
1367
+ const link = document.createElement('a');
1368
+ link.href = url;
1369
+ link.download = `gemini-persona-backup-${new Date().toISOString().split('T')[0]}.json`;
1370
+ document.body.appendChild(link);
1371
+ link.click();
1372
+ document.body.removeChild(link);
1373
+ URL.revokeObjectURL(url);
1374
+ });
1375
+ };
1376
+ }
1377
+
1378
+ // Add event listeners for search and sort in characters page
1379
+ document.addEventListener('DOMContentLoaded', function() {
1380
+ document.getElementById('searchInput')?.addEventListener('input', function() {
1381
+ currentPage = 1;
1382
+ renderCharacters();
1383
+ });
1384
+
1385
+ document.getElementById('sortSelect')?.addEventListener('change', function(e) {
1386
+ sortCharacters(e.target.value);
1387
+ currentPage = 1;
1388
+ renderCharacters();
1389
+ });
1390
+
1391
+ document.getElementById('messageInput')?.addEventListener('keypress', function(e) {
1392
+ if (e.key === 'Enter') {
1393
+ sendMessage();
1394
+ }
1395
+ });
1396
+ });
1397
+ </script>
1398
  </body>
1399
  </html>