al00sakkaf commited on
Commit
b9d2156
·
verified ·
1 Parent(s): 2d1c06b

قم بتطوير التطبيق واضف التحسينات التالية : اضف صفحة لاختيار النموذج وادخال مفتاح api ، اضف صفحة لادارة المحادثات السابقة ، قم بتطوير ادارة الشخصيات الافتراضية مع امكانية اضافة شخصية او تعديل شخصية او حذف شخصية ، اجعل التطبيق يقوم بحفظ المحادثات تلقائيا في قاعدة بيانات محلية ، اضف دعم markdown لعرض المحادثات بتنسيق ، اجعل التطبيق قادر على حفظ السياق في المحادثة ويجب ان يتقمص النموذج الشخصية ، النماذج الذي يستخدمها التطبيق هي نماذج Gemini-2.0-flash و glm-4.5-flash ، قم باستخدام واجهة انيقة ومتناسبة مع شاشاة الهواتف المحمولة، اضف التحسينات لجعل التطبيق مثالي

Browse files
Files changed (6) hide show
  1. README.md +7 -4
  2. characters.html +290 -0
  3. chat.html +521 -0
  4. conversations.html +305 -0
  5. index.html +221 -18
  6. settings.html +262 -0
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Geminipersona Chat Master
3
- emoji: 🌖
4
  colorFrom: pink
5
- colorTo: indigo
 
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: GeminiPersona Chat Master 🧠
 
3
  colorFrom: pink
4
+ colorTo: blue
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
characters.html ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>إدارة الشخصيات - GeminiPersona</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <style>
12
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800&display=swap');
13
+ * {
14
+ font-family: 'Tajawal', sans-serif;
15
+ }
16
+ .character-card {
17
+ transition: all 0.3s ease;
18
+ border: 2px solid transparent;
19
+ }
20
+ .character-card:hover {
21
+ border-color: #6366f1;
22
+ transform: translateY(-2px);
23
+ box-shadow: 0 10px 25px rgba(99, 102, 241, 0.15);
24
+ }
25
+ </style>
26
+ </head>
27
+ <body class="bg-gray-50 min-h-screen">
28
+ <!-- Navigation -->
29
+ <nav class="bg-white shadow-lg border-b">
30
+ <div class="max-w-7xl mx-auto px-4">
31
+ <div class="flex justify-between items-center h-16">
32
+ <div class="flex items-center space-x-4 space-x-reverse">
33
+ <a href="index.html" class="text-gray-600 hover:text-primary transition-colors">
34
+ <i data-feather="arrow-right"></i>
35
+ </a>
36
+ <i data-feather="users" class="text-primary w-6 h-6"></i>
37
+ <h1 class="text-xl font-bold text-gray-800">إدارة الشخصيات</h1>
38
+ </div>
39
+ <div class="flex items-center space-x-4 space-x-reverse">
40
+ <a href="settings.html" class="text-gray-600 hover:text-primary transition-colors">
41
+ <i data-feather="settings"></i>
42
+ </a>
43
+ <a href="conversations.html" class="text-gray-600 hover:text-primary transition-colors">
44
+ <i data-feather="message-square"></i>
45
+ </a>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </nav>
50
+
51
+ <!-- Main Content -->
52
+ <div class="max-w-6xl mx-auto py-8 px-4">
53
+ <!-- Header with Add Button -->
54
+ <div class="flex justify-between items-center mb-8">
55
+ <h2 class="text-2xl font-bold text-gray-800">شخصياتك الافتراضية</h2>
56
+ <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">
57
+ <i data-feather="plus" class="w-4 h-4"></i>
58
+ <span>إضافة شخصية جديدة</span>
59
+ </button>
60
+ </div>
61
+
62
+ <!-- Characters Grid -->
63
+ <div id="charactersGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
64
+ <!-- Characters will be loaded here -->
65
+ </div>
66
+
67
+ <!-- Empty State -->
68
+ <div id="emptyState" class="text-center py-12 hidden">
69
+ <i data-feather="users" class="w-16 h-16 text-gray-300 mx-auto mb-4"></i>
70
+ <h3 class="text-xl font-semibold text-gray-600 mb-2">لا توجد شخصيات</h3>
71
+ <p class="text-gray-500 mb-6">ابدأ بإضافة أول شخصية افتراضية لك</p>
72
+ <button onclick="openAddCharacterModal()" class="bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors">
73
+ إضافة شخصية جديدة
74
+ </button>
75
+ </div>
76
+ </div>
77
+
78
+ <!-- Add/Edit Character Modal -->
79
+ <div id="characterModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50 hidden">
80
+ <div class="bg-white rounded-xl shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto">
81
+ <div class="p-6">
82
+ <div class="flex justify-between items-center mb-6">
83
+ <h3 id="modalTitle" class="text-xl font-bold text-gray-800">إضافة شخصية جديدة</h3>
84
+ <button onclick="closeCharacterModal()" class="text-gray-400 hover:text-gray-600">
85
+ <i data-feather="x" class="w-6 h-6"></i>
86
+ </button>
87
+ </div>
88
+
89
+ <form id="characterForm" class="space-y-4">
90
+ <input type="hidden" id="characterId">
91
+
92
+ <div>
93
+ <label for="characterName" class="block text-sm font-medium text-gray-700 mb-2">اسم الشخصية</label>
94
+ <input type="text" id="characterName" required
95
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
96
+ </div>
97
+
98
+ <div>
99
+ <label for="characterRole" class="block text-sm font-medium text-gray-700 mb-2">الدور/المهنة</label>
100
+ <input type="text" id="characterRole"
101
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
102
+ </div>
103
+
104
+ <div>
105
+ <label for="characterDescription" class="block text-sm font-medium text-gray-700 mb-2">الوصف</label>
106
+ <textarea id="characterDescription" rows="4"
107
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"
108
+ placeholder="صف شخصية الذكاء الاصطناعي ودوره وطريقة تحدثه..."></textarea>
109
+ </div>
110
+
111
+ <div>
112
+ <label for="characterInstructions" class="block text-sm font-medium text-gray-700 mb-2">التعليمات الخاصة</label>
113
+ <textarea id="characterInstructions" rows="4"
114
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"
115
+ placeholder="أدخل التعليمات الخاصة بالشخصية..."></textarea>
116
+ </div>
117
+
118
+ <div class="flex justify-end space-x-3 space-x-reverse pt-4">
119
+ <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">
120
+ إلغاء
121
+ </button>
122
+ <button type="submit" class="px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors">
123
+ حفظ الشخصية
124
+ </button>
125
+ </div>
126
+ </form>
127
+ </div>
128
+ </div>
129
+ </div>
130
+
131
+ <script>
132
+ let characters = [];
133
+
134
+ // Load characters from IndexedDB
135
+ function loadCharacters() {
136
+ const request = indexedDB.open("GeminiPersonaDB", 1);
137
+
138
+ request.onsuccess = function(event) {
139
+ const db = event.target.result;
140
+ const transaction = db.transaction(['characters'], 'readonly');
141
+ const store = transaction.objectStore('characters');
142
+ const getAllRequest = store.getAll();
143
+
144
+ getAllRequest.onsuccess = function() {
145
+ characters = getAllRequest.result;
146
+ renderCharacters();
147
+ };
148
+ };
149
+ }
150
+
151
+ // Render characters grid
152
+ function renderCharacters() {
153
+ const grid = document.getElementById('charactersGrid');
154
+ const emptyState = document.getElementById('emptyState');
155
+
156
+ if (characters.length === 0) {
157
+ grid.classList.add('hidden');
158
+ emptyState.classList.remove('hidden');
159
+ return;
160
+ }
161
+
162
+ grid.classList.remove('hidden');
163
+ emptyState.classList.add('hidden');
164
+
165
+ grid.innerHTML = characters.map(character => `
166
+ <div class="character-card bg-white rounded-xl shadow-md p-6">
167
+ <div class="flex justify-between items-start mb-4">
168
+ <div>
169
+ <h3 class="text-lg font-semibold text-gray-800">${character.name}</h3>
170
+ ${character.role ? `<p class="text-sm text-gray-600">${character.role}</p>` : ''}
171
+ </div>
172
+ <div class="flex space-x-2 space-x-reverse">
173
+ <button onclick="editCharacter(${character.id})" class="text-blue-600 hover:text-blue-800">
174
+ <i data-feather="edit-2" class="w-4 h-4"></i>
175
+ </button>
176
+ <button onclick="deleteCharacter(${character.id})" class="text-red-600 hover:text-red-800">
177
+ <i data-feather="trash-2" class="w-4 h-4"></i>
178
+ </button>
179
+ </div>
180
+ </div>
181
+ ${character.description ? `<p class="text-gray-700 text-sm mb-4">${character.description}</p>` : ''}
182
+ <button onclick="startChatWithCharacter(${character.id})" class="w-full bg-primary text-white py-2 px-4 rounded-lg hover:bg-primary/90 transition-colors text-sm">
183
+ بدء محادثة
184
+ </button>
185
+ </div>
186
+ `).join('');
187
+
188
+ feather.replace();
189
+ }
190
+
191
+ // Open add character modal
192
+ function openAddCharacterModal() {
193
+ document.getElementById('characterModal').classList.remove('hidden');
194
+ document.getElementById('modalTitle').textContent = 'إضافة شخصية جديدة';
195
+ document.getElementById('characterForm').reset();
196
+ document.getElementById('characterId').value = '';
197
+ }
198
+
199
+ // Close character modal
200
+ function closeCharacterModal() {
201
+ document.getElementById('characterModal').classList.add('hidden');
202
+ }
203
+
204
+ // Edit character
205
+ function editCharacter(id) {
206
+ const character = characters.find(c => c.id === id);
207
+ if (!character) return;
208
+
209
+ document.getElementById('characterModal').classList.remove('hidden');
210
+ document.getElementById('modalTitle').textContent = 'تعديل الشخصية';
211
+ document.getElementById('characterId').value = character.id;
212
+ document.getElementById('characterName').value = character.name;
213
+ document.getElementById('characterRole').value = character.role || '';
214
+ document.getElementById('characterDescription').value = character.description || '';
215
+ document.getElementById('characterInstructions').value = character.instructions || '';
216
+ }
217
+
218
+ // Delete character
219
+ function deleteCharacter(id) {
220
+ if (!confirm('هل أنت متأكد من حذف هذه الشخصية؟')) return;
221
+
222
+ const request = indexedDB.open("GeminiPersonaDB", 1);
223
+
224
+ request.onsuccess = function(event) {
225
+ const db = event.target.result;
226
+ const transaction = db.transaction(['characters'], 'readwrite');
227
+ const store = transaction.objectStore('characters');
228
+ store.delete(id);
229
+
230
+ transaction.oncomplete = function() {
231
+ characters = characters.filter(c => c.id !== id);
232
+ renderCharacters();
233
+ };
234
+ };
235
+ }
236
+
237
+ // Start chat with character
238
+ function startChatWithCharacter(characterId) {
239
+ const character = characters.find(c => c.id === characterId);
240
+ if (character) {
241
+ localStorage.setItem('selectedCharacter', JSON.stringify(character));
242
+ window.location.href = 'chat.html';
243
+ }
244
+ }
245
+
246
+ // Handle form submission
247
+ document.getElementById('characterForm').addEventListener('submit', function(e) {
248
+ e.preventDefault();
249
+
250
+ const characterData = {
251
+ name: document.getElementById('characterName').value,
252
+ role: document.getElementById('characterRole').value,
253
+ description: document.getElementById('characterDescription').value,
254
+ instructions: document.getElementById('characterInstructions').value,
255
+ createdAt: new Date().toISOString()
256
+ };
257
+
258
+ const characterId = document.getElementById('characterId').value;
259
+
260
+ const request = indexedDB.open("GeminiPersonaDB", 1);
261
+
262
+ request.onsuccess = function(event) {
263
+ const db = event.target.result;
264
+ const transaction = db.transaction(['characters'], 'readwrite');
265
+ const store = transaction.objectStore('characters');
266
+
267
+ if (characterId) {
268
+ // Update existing character
269
+ characterData.id = parseInt(characterId);
270
+ store.put(characterData);
271
+ } else {
272
+ // Add new character
273
+ store.add(characterData);
274
+ }
275
+
276
+ transaction.oncomplete = function() {
277
+ closeCharacterModal();
278
+ loadCharacters();
279
+ };
280
+ };
281
+ });
282
+
283
+ // Initialize
284
+ document.addEventListener('DOMContentLoaded', function() {
285
+ feather.replace();
286
+ loadCharacters();
287
+ });
288
+ </script>
289
+ </body>
290
+ </html>
chat.html ADDED
@@ -0,0 +1,521 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>المحادثة - GeminiPersona</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
12
+ <style>
13
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800&display=swap');
14
+ * {
15
+ font-family: 'Tajawal', sans-serif;
16
+ }
17
+ .chat-container {
18
+ height: calc(100vh - 8rem);
19
+ }
20
+ .messages-container {
21
+ height: calc(100% - 80px);
22
+ }
23
+ .chat-bubble-user {
24
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
25
+ color: white;
26
+ border-radius: 20px 20px 0 20px;
27
+ }
28
+ .chat-bubble-ai {
29
+ background: #f8fafc;
30
+ border: 1px solid #e2e8f0;
31
+ border-radius: 20px 20px 20px 0;
32
+ }
33
+ .typing-indicator {
34
+ display: inline-flex;
35
+ align-items: center;
36
+ }
37
+ .typing-dot {
38
+ width: 8px;
39
+ height: 8px;
40
+ border-radius: 50%;
41
+ background-color: #9ca3af;
42
+ margin: 0 2px;
43
+ animation: typing 1.4s infinite ease-in-out;
44
+ }
45
+ .typing-dot:nth-child(1) { animation-delay: -0.32s; }
46
+ .typing-dot:nth-child(2) { animation-delay: -0.16s; }
47
+ @keyframes typing {
48
+ 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
49
+ 40% { transform: scale(1); opacity: 1; }
50
+ }
51
+ .markdown-content h1, .markdown-content h2, .markdown-content h3 {
52
+ margin-top: 1rem;
53
+ margin-bottom: 0.5rem;
54
+ font-weight: bold;
55
+ }
56
+ .markdown-content h1 { font-size: 1.5rem; }
57
+ .markdown-content h2 { font-size: 1.25rem; }
58
+ .markdown-content h3 { font-size: 1.125rem; }
59
+ .markdown-content code {
60
+ background: #f1f5f9;
61
+ padding: 0.25rem 0.5rem;
62
+ border-radius: 0.375rem;
63
+ font-family: 'Courier New', monospace;
64
+ }
65
+ .markdown-content pre {
66
+ background: #1e293b;
67
+ color: #e2e8f0;
68
+ padding: 1rem;
69
+ border-radius: 0.5rem;
70
+ overflow-x: auto;
71
+ margin: 1rem 0;
72
+ }
73
+ .markdown-content ul, .markdown-content ol {
74
+ margin: 1rem 0;
75
+ padding-right: 1.5rem;
76
+ }
77
+ .markdown-content li {
78
+ margin: 0.5rem 0;
79
+ }
80
+ </style>
81
+ </head>
82
+ <body class="bg-gray-50 min-h-screen">
83
+ <!-- Navigation -->
84
+ <nav class="bg-white shadow-lg border-b">
85
+ <div class="max-w-7xl mx-auto px-4">
86
+ <div class="flex justify-between items-center h-16">
87
+ <div class="flex items-center space-x-4 space-x-reverse">
88
+ <a href="index.html" class="text-gray-600 hover:text-primary transition-colors">
89
+ <i data-feather="arrow-right"></i>
90
+ </a>
91
+ <i data-feather="message-circle" class="text-primary w-6 h-6"></i>
92
+ <h1 class="text-xl font-bold text-gray-800" id="chatTitle">المحادثة</h1>
93
+ </div>
94
+ <div class="flex items-center space-x-4 space-x-reverse">
95
+ <button id="saveChatBtn" class="text-gray-600 hover:text-primary transition-colors">
96
+ <i data-feather="save"></i>
97
+ </button>
98
+ <a href="conversations.html" class="text-gray-600 hover:text-primary transition-colors">
99
+ <i data-feather="archive"></i>
100
+ </a>
101
+ <a href="characters.html" class="text-gray-600 hover:text-primary transition-colors">
102
+ <i data-feather="users"></i>
103
+ </a>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </nav>
108
+
109
+ <!-- Character Info Bar -->
110
+ <div id="characterInfo" class="bg-gradient-to-r from-primary to-secondary text-white py-2 px-4 hidden">
111
+ <div class="max-w-4xl mx-auto flex items-center justify-between">
112
+ <div class="flex items-center space-x-3 space-x-reverse">
113
+ <i data-feather="user" class="w-4 h-4"></i>
114
+ <span id="currentCharacterName">الشخصية المحددة</span>
115
+ </div>
116
+ <button onclick="changeCharacter()" class="text-white/80 hover:text-white text-sm">
117
+ تغيير الشخصية
118
+ </button>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- Main Chat Area -->
123
+ <div class="max-w-4xl mx-auto">
124
+ <div class="chat-container flex flex-col">
125
+ <!-- Messages Container -->
126
+ <div id="messagesContainer" class="messages-container overflow-y-auto p-4 space-y-6">
127
+ <!-- Welcome Message -->
128
+ <div class="text-center py-8">
129
+ <i data-feather="message-circle" class="w-16 h-16 text-gray-300 mx-auto mb-4"></i>
130
+ <h2 class="text-2xl font-bold text-gray-800 mb-2">مرحباً بك في GeminiPersona</h2>
131
+ <p class="text-gray-600">ابدأ محادثة مع الذكاء الاصطناعي. اختر شخصية من قسم الشخصيات أو ابدأ مباشرة!</p>
132
+ </div>
133
+ </div>
134
+
135
+ <!-- Input Area -->
136
+ <div class="border-t bg-white p-4">
137
+ <form id="messageForm" class="flex space-x-3 space-x-reverse">
138
+ <div class="flex-1">
139
+ <input type="text" id="messageInput"
140
+ placeholder="اكتب رسالتك هنا..."
141
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"
142
+ autocomplete="off">
143
+ </div>
144
+ <button type="submit"
145
+ 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 disabled:opacity-50"
146
+ id="sendButton">
147
+ <i data-feather="send" class="w-4 h-4"></i>
148
+ <span>إرسال</span>
149
+ </button>
150
+ </form>
151
+ </div>
152
+ </div>
153
+ </div>
154
+
155
+ <!-- Character Selection Modal -->
156
+ <div id="characterModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50 hidden">
157
+ <div class="bg-white rounded-xl shadow-xl max-w-md w-full max-h-[80vh] overflow-y-auto">
158
+ <div class="p-6">
159
+ <div class="flex justify-between items-center mb-6">
160
+ <h3 class="text-xl font-bold text-gray-800">اختر شخصية</h3>
161
+ <button onclick="closeCharacterModal()" class="text-gray-400 hover:text-gray-600">
162
+ <i data-feather="x" class="w-6 h-6"></i>
163
+ </button>
164
+ </div>
165
+
166
+ <div id="charactersList" class="space-y-3">
167
+ <!-- Characters will be loaded here -->
168
+ </div>
169
+
170
+ <div class="mt-6 pt-4 border-t">
171
+ <button onclick="useDefaultAI()" class="w-full bg-gray-100 text-gray-700 py-3 px-4 rounded-lg hover:bg-gray-200 transition-colors text-center">
172
+ استخدام الذكاء الاصطناعي الافتراضي
173
+ </button>
174
+ </div>
175
+ </div>
176
+ </div>
177
+ </div>
178
+
179
+ <script>
180
+ let messages = [];
181
+ let currentCharacter = null;
182
+ let isTyping = false;
183
+ let currentConversationId = null;
184
+
185
+ // Load characters from IndexedDB
186
+ function loadCharacters() {
187
+ const request = indexedDB.open("GeminiPersonaDB", 1);
188
+
189
+ request.onsuccess = function(event) {
190
+ const db = event.target.result;
191
+ const transaction = db.transaction(['characters'], 'readonly');
192
+ const store = transaction.objectStore('characters');
193
+ const getAllRequest = store.getAll();
194
+
195
+ getAllRequest.onsuccess = function() {
196
+ const characters = getAllRequest.result;
197
+ renderCharacterSelection(characters);
198
+ };
199
+ };
200
+ }
201
+
202
+ // Render character selection
203
+ function renderCharacterSelection(characters) {
204
+ const list = document.getElementById('charactersList');
205
+ list.innerHTML = characters.map(character => `
206
+ <div class="border border-gray-200 rounded-lg p-4 cursor-pointer hover:border-primary transition-colors" onclick="selectCharacter(${character.id})">
207
+ <h4 class="font-semibold text-gray-800">${character.name}</h4>
208
+ ${character.role ? `<p class="text-sm text-gray-600">${character.role}</p>` : ''}
209
+ ${character.description ? `<p class="text-sm text-gray-500 mt-2">${character.description}</p>` : ''}
210
+ </div>
211
+ `).join('');
212
+ }
213
+
214
+ // Select character
215
+ function selectCharacter(characterId) {
216
+ const request = indexedDB.open("GeminiPersonaDB", 1);
217
+
218
+ request.onsuccess = function(event) {
219
+ const db = event.target.result;
220
+ const transaction = db.transaction(['characters'], 'readonly');
221
+ const store = transaction.objectStore('characters');
222
+ const getRequest = store.get(characterId);
223
+
224
+ getRequest.onsuccess = function() {
225
+ currentCharacter = getRequest.result;
226
+ document.getElementById('characterInfo').classList.remove('hidden');
227
+ document.getElementById('currentCharacterName').textContent = currentCharacter.name;
228
+ closeCharacterModal();
229
+
230
+ // Add system message if this is the first message
231
+ if (messages.length === 0) {
232
+ addSystemMessage(`أنت الآن تتحدث مع ${currentCharacter.name}${currentCharacter.role ? ` - ${currentCharacter.role}` : ''}. ${currentCharacter.instructions || ''}`);
233
+ }
234
+ };
235
+ };
236
+ }
237
+
238
+ // Use default AI
239
+ function useDefaultAI() {
240
+ currentCharacter = null;
241
+ document.getElementById('characterInfo').classList.add('hidden');
242
+ closeCharacterModal();
243
+
244
+ if (messages.length === 0) {
245
+ addSystemMessage('أنت الآن تتحدث مع الذكاء الاصطناعي الافتراضي. كيف يمكنني مساعدتك؟');
246
+ }
247
+ }
248
+
249
+ // Change character
250
+ function changeCharacter() {
251
+ loadCharacters();
252
+ document.getElementById('characterModal').classList.remove('hidden');
253
+ }
254
+
255
+ // Close character modal
256
+ function closeCharacterModal() {
257
+ document.getElementById('characterModal').classList.add('hidden');
258
+ }
259
+
260
+ // Add system message
261
+ function addSystemMessage(content) {
262
+ const message = {
263
+ role: 'system',
264
+ content: content,
265
+ timestamp: new Date().toISOString()
266
+ };
267
+ messages.push(message);
268
+ renderMessages();
269
+ }
270
+
271
+ // Add message to chat
272
+ function addMessage(role, content) {
273
+ const message = {
274
+ role: role,
275
+ content: content,
276
+ timestamp: new Date().toISOString()
277
+ };
278
+ messages.push(message);
279
+ renderMessages();
280
+
281
+ // Auto-save if enabled
282
+ const settings = JSON.parse(localStorage.getItem('geminiPersonaSettings') || '{}');
283
+ if (settings.autoSave !== false) {
284
+ autoSaveConversation();
285
+ }
286
+ }
287
+
288
+ // Render messages
289
+ function renderMessages() {
290
+ const container = document.getElementById('messagesContainer');
291
+ const markdownEnabled = JSON.parse(localStorage.getItem('geminiPersonaSettings') || '{}').markdownEnabled !== false;
292
+
293
+ container.innerHTML = messages.map(message => {
294
+ if (message.role === 'system') {
295
+ return `
296
+ <div class="text-center">
297
+ <div class="inline-flex items-center space-x-2 space-x-reverse bg-gray-100 text-gray-600 px-4 py-2 rounded-full text-sm">
298
+ <i data-feather="info" class="w-3 h-3"></i>
299
+ <span>${message.content}</span>
300
+ </div>
301
+ </div>
302
+ `;
303
+ }
304
+
305
+ return `
306
+ <div class="flex ${message.role === 'user' ? 'justify-end' : 'justify-start'}">
307
+ <div class="max-w-3/4 ${message.role === 'user' ? 'chat-bubble-user' : 'chat-bubble-ai'} p-4">
308
+ <div class="${markdownEnabled && message.role === 'assistant' ? 'markdown-content' : ''}">
309
+ ${markdownEnabled && message.role === 'assistant' ? marked.parse(message.content) : message.content}
310
+ </div>
311
+ <div class="text-xs opacity-70 mt-2 ${message.role === 'user' ? 'text-blue-100' : 'text-gray-500'}">
312
+ ${new Date(message.timestamp).toLocaleTimeString('ar-EG', { hour: '2-digit', minute: '2-digit' })}
313
+ </div>
314
+ </div>
315
+ </div>
316
+ `;
317
+ }).join('');
318
+
319
+ container.scrollTop = container.scrollHeight;
320
+ feather.replace();
321
+ }
322
+
323
+ // Show typing indicator
324
+ function showTypingIndicator() {
325
+ if (isTyping) return;
326
+ isTyping = true;
327
+
328
+ const container = document.getElementById('messagesContainer');
329
+ const indicator = document.createElement('div');
330
+ indicator.className = 'flex justify-start';
331
+ indicator.innerHTML = `
332
+ <div class="chat-bubble-ai p-4">
333
+ <div class="typing-indicator">
334
+ <div class="typing-dot"></div>
335
+ <div class="typing-dot"></div>
336
+ <div class="typing-dot"></div>
337
+ </div>
338
+ </div>
339
+ `;
340
+ container.appendChild(indicator);
341
+ container.scrollTop = container.scrollHeight;
342
+ }
343
+
344
+ // Hide typing indicator
345
+ function hideTypingIndicator() {
346
+ isTyping = false;
347
+ const container = document.getElementById('messagesContainer');
348
+ const indicator = container.querySelector('.typing-indicator');
349
+ if (indicator) {
350
+ indicator.closest('.flex').remove();
351
+ }
352
+ }
353
+
354
+ // Send message to AI
355
+ async function sendMessageToAI(message) {
356
+ const settings = JSON.parse(localStorage.getItem('geminiPersonaSettings') || '{}');
357
+
358
+ if (!settings.apiKey) {
359
+ addMessage('assistant', '⚠️ يرجى إضافة مفتاح API من صفحة الإعدادات أولاً.');
360
+ return;
361
+ }
362
+
363
+ showTypingIndicator();
364
+
365
+ try {
366
+ // Prepare conversation context
367
+ const conversationContext = messages
368
+ .filter(msg => msg.role !== 'system')
369
+ .slice(-10) // Keep last 10 messages for context
370
+ .map(msg => ({
371
+ role: msg.role === 'user' ? 'user' : 'model',
372
+ parts: [{ text: msg.content }]
373
+ }));
374
+
375
+ // Add system prompt if character is selected
376
+ let systemInstruction = '';
377
+ if (currentCharacter) {
378
+ systemInstruction = `أنت ${currentCharacter.name}${currentCharacter.role ? ` - ${currentCharacter.role}` : ''}. ${currentCharacter.description || ''}. ${currentCharacter.instructions || ''}. يجب أن تتصرف وتتحدث كما تم وصف شخصيتك.`;
379
+ }
380
+
381
+ const requestBody = {
382
+ contents: conversationContext,
383
+ generationConfig: {
384
+ temperature: 0.7,
385
+ topK: 40,
386
+ topP: 0.95,
387
+ maxOutputTokens: 1024,
388
+ }
389
+ };
390
+
391
+ if (systemInstruction) {
392
+ requestBody.systemInstruction = {
393
+ parts: [{ text: systemInstruction }]
394
+ };
395
+ }
396
+
397
+ const model = settings.model === 'glm-4.5-flash' ? 'glm-4-5-flash' : 'gemini-2.0-flash-exp';
398
+ const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${settings.apiKey}`, {
399
+ method: 'POST',
400
+ headers: {
401
+ 'Content-Type': 'application/json',
402
+ },
403
+ body: JSON.stringify(requestBody)
404
+ });
405
+
406
+ if (!response.ok) {
407
+ throw new Error(`HTTP error! status: ${response.status}`);
408
+ }
409
+
410
+ const data = await response.json();
411
+
412
+ if (data.candidates && data.candidates[0] && data.candidates[0].content) {
413
+ const aiResponse = data.candidates[0].content.parts[0].text;
414
+ hideTypingIndicator();
415
+ addMessage('assistant', aiResponse);
416
+ } else {
417
+ throw new Error('No response from AI');
418
+ }
419
+
420
+ } catch (error) {
421
+ hideTypingIndicator();
422
+ console.error('Error:', error);
423
+ addMessage('assistant', '❌ حدث خطأ في الاتصال بالذكاء الاصطناعي. يرجى التحقق من مفتاح API وإعدادات الاتصال.');
424
+ }
425
+ }
426
+
427
+ // Auto-save conversation
428
+ function autoSaveConversation() {
429
+ if (messages.length < 2) return; // Don't save empty conversations
430
+
431
+ const conversation = {
432
+ title: messages.find(m => m.role === 'user')?.content.substring(0, 50) + '...' || 'محادثة جديدة',
433
+ messages: messages,
434
+ character: currentCharacter,
435
+ createdAt: new Date().toISOString(),
436
+ updatedAt: new Date().toISOString()
437
+ };
438
+
439
+ const request = indexedDB.open("GeminiPersonaDB", 1);
440
+
441
+ request.onsuccess = function(event) {
442
+ const db = event.target.result;
443
+ const transaction = db.transaction(['conversations'], 'readwrite');
444
+ const store = transaction.objectStore('conversations');
445
+
446
+ if (currentConversationId) {
447
+ conversation.id = currentConversationId;
448
+ store.put(conversation);
449
+ } else {
450
+ const addRequest = store.add(conversation);
451
+ addRequest.onsuccess = function() {
452
+ currentConversationId = addRequest.result;
453
+ };
454
+ }
455
+ };
456
+ }
457
+
458
+ // Manual save
459
+ document.getElementById('saveChatBtn').addEventListener('click', function() {
460
+ autoSaveConversation();
461
+
462
+ // Show success message
463
+ const btn = this;
464
+ const originalHTML = btn.innerHTML;
465
+ btn.innerHTML = '<i data-feather="check" class="w-4 h-4 text-green-500"></i>';
466
+ feather.replace();
467
+
468
+ setTimeout(() => {
469
+ btn.innerHTML = originalHTML;
470
+ feather.replace();
471
+ }, 2000);
472
+ });
473
+
474
+ // Handle form submission
475
+ document.getElementById('messageForm').addEventListener('submit', async function(e) {
476
+ e.preventDefault();
477
+
478
+ const messageInput = document.getElementById('messageInput');
479
+ const message = messageInput.value.trim();
480
+
481
+ if (!message) return;
482
+
483
+ // Add user message
484
+ addMessage('user', message);
485
+ messageInput.value = '';
486
+
487
+ // Send to AI
488
+ await sendMessageToAI(message);
489
+ });
490
+
491
+ // Load restored conversation
492
+ function loadRestoredConversation() {
493
+ const restored = localStorage.getItem('restoredConversation');
494
+ if (restored) {
495
+ const conversation = JSON.parse(restored);
496
+ messages = conversation.messages;
497
+ currentCharacter = conversation.character;
498
+ currentConversationId = conversation.id;
499
+
500
+ if (currentCharacter) {
501
+ document.getElementById('characterInfo').classList.remove('hidden');
502
+ document.getElementById('currentCharacterName').textContent = currentCharacter.name;
503
+ }
504
+
505
+ renderMessages();
506
+ localStorage.removeItem('restoredConversation');
507
+ }
508
+ }
509
+
510
+ // Initialize
511
+ document.addEventListener('DOMContentLoaded', function() {
512
+ feather.replace();
513
+ loadCharacters();
514
+ loadRestoredConversation();
515
+
516
+ // Focus on input
517
+ document.getElementById('messageInput').focus();
518
+ });
519
+ </script>
520
+ </body>
521
+ </html>
conversations.html ADDED
@@ -0,0 +1,305 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>المحادثات السابقة - GeminiPersona</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <style>
12
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800&display=swap');
13
+ * {
14
+ font-family: 'Tajawal', sans-serif;
15
+ }
16
+ .conversation-item {
17
+ transition: all 0.3s ease;
18
+ border-left: 4px solid transparent;
19
+ }
20
+ .conversation-item:hover {
21
+ border-left-color: #6366f1;
22
+ background: #f8fafc;
23
+ }
24
+ </style>
25
+ </head>
26
+ <body class="bg-gray-50 min-h-screen">
27
+ <!-- Navigation -->
28
+ <nav class="bg-white shadow-lg border-b">
29
+ <div class="max-w-7xl mx-auto px-4">
30
+ <div class="flex justify-between items-center h-16">
31
+ <div class="flex items-center space-x-4 space-x-reverse">
32
+ <a href="index.html" class="text-gray-600 hover:text-primary transition-colors">
33
+ <i data-feather="arrow-right"></i>
34
+ </a>
35
+ <i data-feather="message-square" class="text-primary w-6 h-6"></i>
36
+ <h1 class="text-xl font-bold text-gray-800">المحادثات السابقة</h1>
37
+ </div>
38
+ <div class="flex items-center space-x-4 space-x-reverse">
39
+ <a href="settings.html" class="text-gray-600 hover:text-primary transition-colors">
40
+ <i data-feather="settings"></i>
41
+ </a>
42
+ <a href="characters.html" class="text-gray-600 hover:text-primary transition-colors">
43
+ <i data-feather="users"></i>
44
+ </a>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </nav>
49
+
50
+ <!-- Main Content -->
51
+ <div class="max-w-4xl mx-auto py-8 px-4">
52
+ <!-- Header -->
53
+ <div class="mb-8">
54
+ <h2 class="text-2xl font-bold text-gray-800 mb-2">محادثاتك المحفوظة</h2>
55
+ <p class="text-gray-600">استعرض وأعد فتح محادثاتك السابقة</p>
56
+ </div>
57
+
58
+ <!-- Search and Filters -->
59
+ <div class="bg-white rounded-xl shadow-md p-4 mb-6">
60
+ <div class="flex flex-col md:flex-row gap-4">
61
+ <div class="flex-1">
62
+ <div class="relative">
63
+ <input type="text" id="searchInput" placeholder="ابحث في المحادثات..."
64
+ class="w-full px-4 py-3 pr-12 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
65
+ <i data-feather="search" class="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4"></i>
66
+ </div>
67
+ </div>
68
+ <div class="flex space-x-3 space-x-reverse">
69
+ <select id="sortSelect" class="px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
70
+ <option value="newest">الأحدث أولاً</option>
71
+ <option value="oldest">الأقدم أولاً</option>
72
+ </select>
73
+ <button onclick="clearAllConversations()" class="px-4 py-3 border border-red-300 text-red-600 rounded-lg hover:bg-red-50 transition-colors flex items-center space-x-2 space-x-reverse">
74
+ <i data-feather="trash-2" class="w-4 h-4"></i>
75
+ <span>حذف الكل</span>
76
+ </button>
77
+ </div>
78
+ </div>
79
+ </div>
80
+
81
+ <!-- Conversations List -->
82
+ <div id="conversationsList" class="space-y-4">
83
+ <!-- Conversations will be loaded here -->
84
+ </div>
85
+
86
+ <!-- Empty State -->
87
+ <div id="emptyState" class="text-center py-12 hidden">
88
+ <i data-feather="message-square" class="w-16 h-16 text-gray-300 mx-auto mb-4"></i>
89
+ <h3 class="text-xl font-semibold text-gray-600 mb-2">لا توجد محادثات</h3>
90
+ <p class="text-gray-500 mb-6">ابدأ محادثة جديدة للحفظ هنا</p>
91
+ <a href="chat.html" class="bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors inline-block">
92
+ بدء محادثة جديدة
93
+ </a>
94
+ </div>
95
+ </div>
96
+
97
+ <!-- Conversation Details Modal -->
98
+ <div id="conversationModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50 hidden">
99
+ <div class="bg-white rounded-xl shadow-xl max-w-4xl w-full max-h-[90vh] overflow-hidden">
100
+ <div class="p-6 border-b">
101
+ <div class="flex justify-between items-center">
102
+ <h3 id="conversationTitle" class="text-xl font-bold text-gray-800">تفاصيل المحادثة</h3>
103
+ <button onclick="closeConversationModal()" class="text-gray-400 hover:text-gray-600">
104
+ <i data-feather="x" class="w-6 h-6"></i>
105
+ </button>
106
+ </div>
107
+ </div>
108
+ <div id="conversationContent" class="p-6 overflow-y-auto max-h-[60vh]">
109
+ <!-- Conversation content will be loaded here -->
110
+ </div>
111
+ <div class="p-6 border-t bg-gray-50">
112
+ <div class="flex justify-end space-x-3 space-x-reverse">
113
+ <button onclick="deleteConversation()" class="px-6 py-3 border border-red-300 text-red-600 rounded-lg hover:bg-red-50 transition-colors">
114
+ حذف المحادثة
115
+ </button>
116
+ <button onclick="restoreConversation()" class="px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors">
117
+ استئناف المحادثة
118
+ </button>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+
124
+ <script>
125
+ let conversations = [];
126
+ let currentConversationId = null;
127
+
128
+ // Load conversations from IndexedDB
129
+ function loadConversations() {
130
+ const request = indexedDB.open("GeminiPersonaDB", 1);
131
+
132
+ request.onsuccess = function(event) {
133
+ const db = event.target.result;
134
+ const transaction = db.transaction(['conversations'], 'readonly');
135
+ const store = transaction.objectStore('conversations');
136
+ const getAllRequest = store.getAll();
137
+
138
+ getAllRequest.onsuccess = function() {
139
+ conversations = getAllRequest.result;
140
+ renderConversations();
141
+ };
142
+ };
143
+ }
144
+
145
+ // Render conversations list
146
+ function renderConversations() {
147
+ const list = document.getElementById('conversationsList');
148
+ const emptyState = document.getElementById('emptyState');
149
+
150
+ if (conversations.length === 0) {
151
+ list.classList.add('hidden');
152
+ emptyState.classList.remove('hidden');
153
+ return;
154
+ }
155
+
156
+ list.classList.remove('hidden');
157
+ emptyState.classList.add('hidden');
158
+
159
+ // Sort conversations
160
+ const sortBy = document.getElementById('sortSelect').value;
161
+ const sortedConversations = [...conversations].sort((a, b) => {
162
+ if (sortBy === 'newest') {
163
+ return new Date(b.createdAt) - new Date(a.createdAt);
164
+ } else {
165
+ return new Date(a.createdAt) - new Date(b.createdAt);
166
+ }
167
+ });
168
+
169
+ // Filter by search
170
+ const searchTerm = document.getElementById('searchInput').value.toLowerCase();
171
+ const filteredConversations = sortedConversations.filter(conv =>
172
+ conv.title.toLowerCase().includes(searchTerm) ||
173
+ conv.messages.some(msg => msg.content.toLowerCase().includes(searchTerm))
174
+ );
175
+
176
+ list.innerHTML = filteredConversations.map(conversation => `
177
+ <div class="conversation-item bg-white rounded-xl shadow-sm p-6 cursor-pointer hover:shadow-md transition-all" onclick="openConversation(${conversation.id})">
178
+ <div class="flex justify-between items-start mb-3">
179
+ <h3 class="text-lg font-semibold text-gray-800">${conversation.title}</h3>
180
+ <span class="text-sm text-gray-500">${formatDate(conversation.createdAt)}</span>
181
+ </div>
182
+ <div class="flex justify-between items-center">
183
+ <p class="text-gray-600 text-sm truncate flex-1 mr-4">
184
+ ${conversation.messages.slice(-1)[0]?.content.substring(0, 100)}${conversation.messages.slice(-1)[0]?.content.length > 100 ? '...' : ''}
185
+ </p>
186
+ <span class="text-xs text-gray-400 bg-gray-100 px-2 py-1 rounded-full">
187
+ ${conversation.messages.length} رسالة
188
+ </span>
189
+ </div>
190
+ </div>
191
+ `).join('');
192
+
193
+ feather.replace();
194
+ }
195
+
196
+ // Format date
197
+ function formatDate(dateString) {
198
+ const date = new Date(dateString);
199
+ return date.toLocaleDateString('ar-EG', {
200
+ year: 'numeric',
201
+ month: 'short',
202
+ day: 'numeric',
203
+ hour: '2-digit',
204
+ minute: '2-digit'
205
+ });
206
+ }
207
+
208
+ // Open conversation details
209
+ function openConversation(id) {
210
+ const conversation = conversations.find(c => c.id === id);
211
+ if (!conversation) return;
212
+
213
+ currentConversationId = id;
214
+ document.getElementById('conversationModal').classList.remove('hidden');
215
+ document.getElementById('conversationTitle').textContent = conversation.title;
216
+
217
+ const contentDiv = document.getElementById('conversationContent');
218
+ contentDiv.innerHTML = conversation.messages.map(message => `
219
+ <div class="mb-6 ${message.role === 'user' ? 'text-left' : 'text-right'}">
220
+ <div class="flex ${message.role === 'user' ? 'justify-end' : 'justify-start'} mb-2">
221
+ <div class="inline-flex items-center space-x-2 space-x-reverse ${message.role === 'user' ? 'bg-blue-100 text-blue-800' : 'bg-gray-100 text-gray-800'} px-3 py-1 rounded-full text-sm">
222
+ <i data-feather="${message.role === 'user' ? 'user' : 'cpu'}" class="w-3 h-3"></i>
223
+ <span>${message.role === 'user' ? 'أنت' : 'المساعد'}</span>
224
+ </div>
225
+ </div>
226
+ <div class="${message.role === 'user' ? 'bg-blue-50 border border-blue-200' : 'bg-gray-50 border border-gray-200'} rounded-lg p-4">
227
+ <div class="markdown-content">${marked.parse(message.content)}</div>
228
+ </div>
229
+ <div class="text-xs text-gray-400 mt-1 ${message.role === 'user' ? 'text-right' : 'text-left'}">
230
+ ${formatDate(message.timestamp)}
231
+ </div>
232
+ </div>
233
+ `).join('');
234
+
235
+ feather.replace();
236
+ }
237
+
238
+ // Close conversation modal
239
+ function closeConversationModal() {
240
+ document.getElementById('conversationModal').classList.add('hidden');
241
+ currentConversationId = null;
242
+ }
243
+
244
+ // Delete conversation
245
+ function deleteConversation() {
246
+ if (!currentConversationId || !confirm('هل أنت متأكد من حذف هذه المحادثة؟')) return;
247
+
248
+ const request = indexedDB.open("GeminiPersonaDB", 1);
249
+
250
+ request.onsuccess = function(event) {
251
+ const db = event.target.result;
252
+ const transaction = db.transaction(['conversations'], 'readwrite');
253
+ const store = transaction.objectStore('conversations');
254
+ store.delete(currentConversationId);
255
+
256
+ transaction.oncomplete = function() {
257
+ conversations = conversations.filter(c => c.id !== currentConversationId);
258
+ renderConversations();
259
+ closeConversationModal();
260
+ };
261
+ };
262
+ }
263
+
264
+ // Restore conversation
265
+ function restoreConversation() {
266
+ if (!currentConversationId) return;
267
+
268
+ const conversation = conversations.find(c => c.id === currentConversationId);
269
+ if (conversation) {
270
+ localStorage.setItem('restoredConversation', JSON.stringify(conversation));
271
+ window.location.href = 'chat.html';
272
+ }
273
+ }
274
+
275
+ // Clear all conversations
276
+ function clearAllConversations() {
277
+ if (!confirm('هل أنت متأكد من حذف جميع المحادثات؟ لا يمكن التراجع عن هذا الإجراء.')) return;
278
+
279
+ const request = indexedDB.open("GeminiPersonaDB", 1);
280
+
281
+ request.onsuccess = function(event) {
282
+ const db = event.target.result;
283
+ const transaction = db.transaction(['conversations'], 'readwrite');
284
+ const store = transaction.objectStore('conversations');
285
+ store.clear();
286
+
287
+ transaction.oncomplete = function() {
288
+ conversations = [];
289
+ renderConversations();
290
+ };
291
+ };
292
+ }
293
+
294
+ // Search and filter
295
+ document.getElementById('searchInput').addEventListener('input', renderConversations);
296
+ document.getElementById('sortSelect').addEventListener('change', renderConversations);
297
+
298
+ // Initialize
299
+ document.addEventListener('DOMContentLoaded', function() {
300
+ feather.replace();
301
+ loadConversations();
302
+ });
303
+ </script>
304
+ </body>
305
+ </html>
index.html CHANGED
@@ -1,19 +1,222 @@
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="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>GeminiPersona - الدردشة الذكية</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
12
+ <script>
13
+ tailwind.config = {
14
+ theme: {
15
+ extend: {
16
+ colors: {
17
+ primary: '#6366f1',
18
+ secondary: '#8b5cf6',
19
+ accent: '#06b6d4'
20
+ }
21
+ }
22
+ }
23
+ }
24
+ </script>
25
+ <style>
26
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800&display=swap');
27
+ * {
28
+ font-family: 'Tajawal', sans-serif;
29
+ }
30
+ .gradient-bg {
31
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
32
+ }
33
+ .chat-bubble-user {
34
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
35
+ color: white;
36
+ border-radius: 20px 20px 0 20px;
37
+ }
38
+ .chat-bubble-ai {
39
+ background: #f8fafc;
40
+ border: 1px solid #e2e8f0;
41
+ border-radius: 20px 20px 20px 0;
42
+ }
43
+ .sidebar-item {
44
+ transition: all 0.3s ease;
45
+ }
46
+ .sidebar-item:hover {
47
+ background: #f1f5f9;
48
+ transform: translateX(-5px);
49
+ }
50
+ .character-card {
51
+ transition: all 0.3s ease;
52
+ border: 2px solid transparent;
53
+ }
54
+ .character-card:hover {
55
+ border-color: #6366f1;
56
+ transform: translateY(-2px);
57
+ box-shadow: 0 10px 25px rgba(99, 102, 241, 0.15);
58
+ }
59
+ .markdown-content h1, .markdown-content h2, .markdown-content h3 {
60
+ margin-top: 1rem;
61
+ margin-bottom: 0.5rem;
62
+ font-weight: bold;
63
+ }
64
+ .markdown-content h1 { font-size: 1.5rem; }
65
+ .markdown-content h2 { font-size: 1.25rem; }
66
+ .markdown-content h3 { font-size: 1.125rem; }
67
+ .markdown-content code {
68
+ background: #f1f5f9;
69
+ padding: 0.25rem 0.5rem;
70
+ border-radius: 0.375rem;
71
+ font-family: 'Courier New', monospace;
72
+ }
73
+ .markdown-content pre {
74
+ background: #1e293b;
75
+ color: #e2e8f0;
76
+ padding: 1rem;
77
+ border-radius: 0.5rem;
78
+ overflow-x: auto;
79
+ margin: 1rem 0;
80
+ }
81
+ </style>
82
+ </head>
83
+ <body class="bg-gray-50 min-h-screen">
84
+ <!-- Navigation -->
85
+ <nav class="bg-white shadow-lg border-b">
86
+ <div class="max-w-7xl mx-auto px-4">
87
+ <div class="flex justify-between items-center h-16">
88
+ <div class="flex items-center space-x-4 space-x-reverse">
89
+ <i data-feather="message-circle" class="text-primary w-8 h-8"></i>
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
+ </div>
103
+ </div>
104
+ </div>
105
+ </nav>
106
+
107
+ <!-- Main Content -->
108
+ <div class="max-w-4xl mx-auto py-8 px-4">
109
+ <!-- Welcome Section -->
110
+ <div class="text-center mb-12">
111
+ <h2 class="text-3xl font-bold text-gray-800 mb-4">مرحباً بك في GeminiPersona</h2>
112
+ <p class="text-gray-600 text-lg">تطبيق الدردشة الذكي الذي يتقمص الشخصيات باستخدام نماذج Gemini المتقدمة</p>
113
+ </div>
114
+
115
+ <!-- Quick Actions -->
116
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
117
+ <a href="chat.html" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow">
118
+ <div class="text-center">
119
+ <i data-feather="message-square" class="w-12 h-12 text-primary mx-auto mb-4"></i>
120
+ <h3 class="text-xl font-semibold text-gray-800 mb-2">بدء محادثة جديدة</h3>
121
+ <p class="text-gray-600">ابدأ محادثة مع الذكاء الاصطناعي</p>
122
+ </div>
123
+ </a>
124
+
125
+ <a href="characters.html" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow">
126
+ <div class="text-center">
127
+ <i data-feather="users" class="w-12 h-12 text-secondary mx-auto mb-4"></i>
128
+ <h3 class="text-xl font-semibold text-gray-800 mb-2">إدارة الشخصيات</h3>
129
+ <p class="text-gray-600">أنشئ وعدّل الشخصيات الافتراضية</p>
130
+ </div>
131
+ </a>
132
+
133
+ <a href="conversations.html" class="bg-white p-6 rounded-xl shadow-md border border-gray-200 hover:shadow-lg transition-shadow">
134
+ <div class="text-center">
135
+ <i data-feather="archive" class="w-12 h-12 text-accent mx-auto mb-4"></i>
136
+ <h3 class="text-xl font-semibold text-gray-800 mb-2">المحادثات السابقة</h3>
137
+ <p class="text-gray-600">راجع محادثاتك المحفوظة</p>
138
+ </div>
139
+ </a>
140
+ </div>
141
+
142
+ <!-- Features Section -->
143
+ <div class="bg-white rounded-xl shadow-md p-8 mb-8">
144
+ <h3 class="text-2xl font-bold text-gray-800 mb-6 text-center">المميزات الرئيسية</h3>
145
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
146
+ <div class="flex items-start space-x-4 space-x-reverse">
147
+ <i data-feather="zap" class="w-6 h-6 text-green-500 mt-1"></i>
148
+ <div>
149
+ <h4 class="font-semibold text-gray-800 mb-2">نماذج Gemini المتقدمة</h4>
150
+ <p class="text-gray-600">استخدم أحدث نماذج الذكاء الاصطناعي من Google</p>
151
+ </div>
152
+ </div>
153
+ <div class="flex items-start space-x-4 space-x-reverse">
154
+ <i data-feather="user" class="w-6 h-6 text-blue-500 mt-1"></i>
155
+ <div>
156
+ <h4 class="font-semibold text-gray-800 mb-2">تقمص الشخصيات</h4>
157
+ <p class="text-gray-600">تحدث مع شخصيات افتراضية مختلفة</p>
158
+ </div>
159
+ </div>
160
+ <div class="flex items-start space-x-4 space-x-reverse">
161
+ <i data-feather="save" class="w-6 h-6 text-purple-500 mt-1"></i>
162
+ <div>
163
+ <h4 class="font-semibult text-gray-800 mb-2">حفظ تلقائي</h4>
164
+ <p class="text-gray-600">المحادثات تحفظ تلقائياً في قاعدة البيانات المحلية</p>
165
+ </div>
166
+ </div>
167
+ <div class="flex items-start space-x-4 space-x-reverse">
168
+ <i data-feather="code" class="w-6 h-6 text-orange-500 mt-1"></i>
169
+ <div>
170
+ <h4 class="font-semibold text-gray-800 mb-2">دعم Markdown</h4>
171
+ <p class="text-gray-600">عرض المحادثات بتنسيق Markdown متقدم</p>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ </div>
177
+
178
+ <script>
179
+ // Initialize database
180
+ function initDB() {
181
+ if (!window.indexedDB) {
182
+ console.log("IndexedDB غير مدعوم في هذا المتصفح");
183
+ return;
184
+ }
185
+
186
+ const request = indexedDB.open("GeminiPersonaDB", 1);
187
+
188
+ request.onerror = function(event) {
189
+ console.log("خطأ في فتح قاعدة البيانات");
190
+ };
191
+
192
+ request.onupgradeneeded = function(event) {
193
+ const db = event.target.result;
194
+
195
+ // Create conversations store
196
+ if (!db.objectStoreNames.contains('conversations')) {
197
+ const conversationsStore = db.createObjectStore('conversations', { keyPath: 'id', autoIncrement: true });
198
+ conversationsStore.createIndex('title', 'title', { unique: false });
199
+ conversationsStore.createIndex('createdAt', 'createdAt', { unique: false });
200
+ }
201
+
202
+ // Create characters store
203
+ if (!db.objectStoreNames.contains('characters')) {
204
+ const charactersStore = db.createObjectStore('characters', { keyPath: 'id', autoIncrement: true });
205
+ charactersStore.createIndex('name', 'name', { unique: false });
206
+ }
207
+
208
+ // Create settings store
209
+ if (!db.objectStoreNames.contains('settings')) {
210
+ const settingsStore = db.createObjectStore('settings', { keyPath: 'id' });
211
+ }
212
+ };
213
+ }
214
+
215
+ // Initialize app
216
+ document.addEventListener('DOMContentLoaded', function() {
217
+ initDB();
218
+ feather.replace();
219
+ });
220
+ </script>
221
+ </body>
222
  </html>
settings.html ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>الإعدادات - GeminiPersona</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <style>
12
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800&display=swap');
13
+ * {
14
+ font-family: 'Tajawal', sans-serif;
15
+ }
16
+ </style>
17
+ </head>
18
+ <body class="bg-gray-50 min-h-screen">
19
+ <!-- Navigation -->
20
+ <nav class="bg-white shadow-lg border-b">
21
+ <div class="max-w-7xl mx-auto px-4">
22
+ <div class="flex justify-between items-center h-16">
23
+ <div class="flex items-center space-x-4 space-x-reverse">
24
+ <a href="index.html" class="text-gray-600 hover:text-primary transition-colors">
25
+ <i data-feather="arrow-right"></i>
26
+ </a>
27
+ <i data-feather="settings" class="text-primary w-6 h-6"></i>
28
+ <h1 class="text-xl font-bold text-gray-800">الإعدادات</h1>
29
+ </div>
30
+ <div class="flex items-center space-x-4 space-x-reverse">
31
+ <a href="characters.html" class="text-gray-600 hover:text-primary transition-colors">
32
+ <i data-feather="users"></i>
33
+ </a>
34
+ <a href="conversations.html" class="text-gray-600 hover:text-primary transition-colors">
35
+ <i data-feather="message-square"></i>
36
+ </a>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </nav>
41
+
42
+ <!-- Main Content -->
43
+ <div class="max-w-2xl mx-auto py-8 px-4">
44
+ <div class="bg-white rounded-xl shadow-md p-6">
45
+ <h2 class="text-2xl font-bold text-gray-800 mb-6">إعدادات النموذج والمفتاح</h2>
46
+
47
+ <!-- Model Selection -->
48
+ <div class="mb-8">
49
+ <label class="block text-sm font-medium text-gray-700 mb-3">اختر نموذج الذكاء الاصطناعي</label>
50
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
51
+ <div class="border-2 border-gray-200 rounded-lg p-4 cursor-pointer transition-all hover:border-primary model-option" data-model="gemini-2.0-flash">
52
+ <div class="flex items-center space-x-3 space-x-reverse">
53
+ <div class="w-3 h-3 rounded-full bg-primary"></div>
54
+ <div>
55
+ <h4 class="font-semibold text-gray-800">Gemini 2.0 Flash</h4>
56
+ <p class="text-sm text-gray-600">نموذج سريع وفعال</p>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ <div class="border-2 border-gray-200 rounded-lg p-4 cursor-pointer transition-all hover:border-primary model-option" data-model="glm-4.5-flash">
61
+ <div class="flex items-center space-x-3 space-x-reverse">
62
+ <div class="w-3 h-3 rounded-full bg-gray-300"></div>
63
+ <div>
64
+ <h4 class="font-semibold text-gray-800">GLM 4.5 Flash</h4>
65
+ <p class="text-sm text-gray-600">نموذج متقدم وسريع</p>
66
+ </div>
67
+ </div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+
72
+ <!-- API Key Input -->
73
+ <div class="mb-8">
74
+ <label for="apiKey" class="block text-sm font-medium text-gray-700 mb-2">مفتاح API</label>
75
+ <div class="relative">
76
+ <input type="password" id="apiKey" placeholder="أدخل مفتاح API الخاص بك"
77
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent">
78
+ <button id="toggleApiKey" class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600">
79
+ <i data-feather="eye"></i>
80
+ </button>
81
+ </div>
82
+ <p class="text-sm text-gray-500 mt-2">سيتم تخزين المفتاح محلياً في متصفحك فقط</p>
83
+ </div>
84
+
85
+ <!-- Save Settings -->
86
+ <div class="flex justify-end space-x-3 space-x-reverse">
87
+ <button onclick="resetSettings()" class="px-6 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors">
88
+ إعادة تعيين
89
+ </button>
90
+ <button onclick="saveSettings()" class="px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors flex items-center space-x-2 space-x-reverse">
91
+ <i data-feather="save" class="w-4 h-4"></i>
92
+ <span>حفظ الإعدادات</span>
93
+ </button>
94
+ </div>
95
+
96
+ <!-- Status Message -->
97
+ <div id="statusMessage" class="mt-4 hidden"></div>
98
+ </div>
99
+
100
+ <!-- Additional Settings -->
101
+ <div class="bg-white rounded-xl shadow-md p-6 mt-6">
102
+ <h3 class="text-xl font-bold text-gray-800 mb-4">إعدادات إضافية</h3>
103
+
104
+ <div class="space-y-4">
105
+ <div class="flex items-center justify-between">
106
+ <div>
107
+ <h4 class="font-medium text-gray-800">الحفظ التلقائي</h4>
108
+ <p class="text-sm text-gray-600">حفظ المحادثات تلقائياً</p>
109
+ </div>
110
+ <label class="relative inline-flex items-center cursor-pointer">
111
+ <input type="checkbox" id="autoSave" class="sr-only peer" checked>
112
+ <div class="w-11 h-6 bg-gray-200 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:right-[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-primary"></div>
113
+ </label>
114
+ </div>
115
+
116
+ <div class="flex items-center justify-between">
117
+ <div>
118
+ <h4 class="font-medium text-gray-800">عرض Markdown</h4>
119
+ <p class="text-sm text-gray-600">عرض المحادثات بتنسيق Markdown</p>
120
+ </div>
121
+ <label class="relative inline-flex items-center cursor-pointer">
122
+ <input type="checkbox" id="markdownEnabled" class="sr-only peer" checked>
123
+ <div class="w-11 h-6 bg-gray-200 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:right-[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-primary"></div>
124
+ </label>
125
+ </div>
126
+ </div>
127
+ </div>
128
+ </div>
129
+
130
+ <script>
131
+ // Load settings
132
+ function loadSettings() {
133
+ const settings = JSON.parse(localStorage.getItem('geminiPersonaSettings') || '{}');
134
+
135
+ // Set model
136
+ if (settings.model) {
137
+ document.querySelectorAll('.model-option').forEach(option => {
138
+ if (option.dataset.model === settings.model) {
139
+ option.classList.add('border-primary', 'bg-primary/5');
140
+ option.querySelector('.w-3').classList.add('bg-primary');
141
+ option.querySelector('.w-3').classList.remove('bg-gray-300');
142
+ } else {
143
+ option.classList.remove('border-primary', 'bg-primary/5');
144
+ option.querySelector('.w-3').classList.remove('bg-primary');
145
+ option.querySelector('.w-3').classList.add('bg-gray-300');
146
+ }
147
+ });
148
+ }
149
+
150
+ // Set API key
151
+ if (settings.apiKey) {
152
+ document.getElementById('apiKey').value = settings.apiKey;
153
+ }
154
+
155
+ // Set checkboxes
156
+ if (settings.autoSave !== undefined) {
157
+ document.getElementById('autoSave').checked = settings.autoSave;
158
+ }
159
+ if (settings.markdownEnabled !== undefined) {
160
+ document.getElementById('markdownEnabled').checked = settings.markdownEnabled;
161
+ }
162
+ }
163
+
164
+ // Save settings
165
+ function saveSettings() {
166
+ const selectedModel = document.querySelector('.model-option.border-primary')?.dataset.model || 'gemini-2.0-flash';
167
+ const apiKey = document.getElementById('apiKey').value;
168
+ const autoSave = document.getElementById('autoSave').checked;
169
+ const markdownEnabled = document.getElementById('markdownEnabled').checked;
170
+
171
+ const settings = {
172
+ model: selectedModel,
173
+ apiKey: apiKey,
174
+ autoSave: autoSave,
175
+ markdownEnabled: markdownEnabled,
176
+ lastUpdated: new Date().toISOString()
177
+ };
178
+
179
+ localStorage.setItem('geminiPersonaSettings', JSON.stringify(settings));
180
+
181
+ // Save to IndexedDB
182
+ const request = indexedDB.open("GeminiPersonaDB", 1);
183
+ request.onsuccess = function(event) {
184
+ const db = event.target.result;
185
+ const transaction = db.transaction(['settings'], 'readwrite');
186
+ const store = transaction.objectStore('settings');
187
+ store.put({ id: 'appSettings', ...settings });
188
+ };
189
+
190
+ showStatus('تم حفظ الإعدادات بنجاح', 'success');
191
+ }
192
+
193
+ // Reset settings
194
+ function resetSettings() {
195
+ localStorage.removeItem('geminiPersonaSettings');
196
+ document.getElementById('apiKey').value = '';
197
+ document.getElementById('autoSave').checked = true;
198
+ document.getElementById('markdownEnabled').checked = true;
199
+
200
+ document.querySelectorAll('.model-option').forEach(option => {
201
+ option.classList.remove('border-primary', 'bg-primary/5');
202
+ option.querySelector('.w-3').classList.remove('bg-primary');
203
+ option.querySelector('.w-3').classList.add('bg-gray-300');
204
+ });
205
+
206
+ // Select first model by default
207
+ document.querySelector('.model-option').classList.add('border-primary', 'bg-primary/5');
208
+ document.querySelector('.model-option .w-3').classList.add('bg-primary');
209
+ document.querySelector('.model-option .w-3').classList.remove('bg-gray-300');
210
+
211
+ showStatus('تم إعادة تعيين الإعدادات', 'info');
212
+ }
213
+
214
+ // Show status message
215
+ function showStatus(message, type) {
216
+ const statusDiv = document.getElementById('statusMessage');
217
+ statusDiv.className = `mt-4 p-4 rounded-lg ${type === 'success' ? 'bg-green-100 text-green-800' : 'bg-blue-100 text-blue-800'}`;
218
+ statusDiv.textContent = message;
219
+ statusDiv.classList.remove('hidden');
220
+
221
+ setTimeout(() => {
222
+ statusDiv.classList.add('hidden');
223
+ }, 3000);
224
+ }
225
+
226
+ // Toggle API key visibility
227
+ document.getElementById('toggleApiKey').addEventListener('click', function() {
228
+ const apiKeyInput = document.getElementById('apiKey');
229
+ const icon = this.querySelector('i');
230
+
231
+ if (apiKeyInput.type === 'password') {
232
+ apiKeyInput.type = 'text';
233
+ feather.icons.eye.replace(icon);
234
+ } else {
235
+ apiKeyInput.type = 'password';
236
+ feather.icons.eye.replace(icon);
237
+ }
238
+ });
239
+
240
+ // Model selection
241
+ document.querySelectorAll('.model-option').forEach(option => {
242
+ option.addEventListener('click', function() {
243
+ document.querySelectorAll('.model-option').forEach(opt => {
244
+ opt.classList.remove('border-primary', 'bg-primary/5');
245
+ opt.querySelector('.w-3').classList.remove('bg-primary');
246
+ opt.querySelector('.w-3').classList.add('bg-gray-300');
247
+ });
248
+
249
+ this.classList.add('border-primary', 'bg-primary/5');
250
+ this.querySelector('.w-3').classList.add('bg-primary');
251
+ this.querySelector('.w-3').classList.remove('bg-gray-300');
252
+ });
253
+ });
254
+
255
+ // Initialize
256
+ document.addEventListener('DOMContentLoaded', function() {
257
+ feather.replace();
258
+ loadSettings();
259
+ });
260
+ </script>
261
+ </body>
262
+ </html>