wasmdashai commited on
Commit
921216b
·
verified ·
1 Parent(s): 3ce58aa

تصميم متقن بحيث كل واجهه تظهر بصفحه خاصه بها مع عرض اظافه واجهه speech 2speech واظافهىمشغل صوتي لكل رساله في تكيست اصوات النظام واصوات الهجه<!DOCTYPE html>

Browse files

<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LAHJA AI - مساعد صوتي ذكي</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>


@import
url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700&display=swap');

body {
font-family: 'Tajawal', sans-serif;
background: linear-gradient(135deg, #0f172a, #1e293b);
color: #fff;
min-height: 100vh;
}

.chat-container {
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(10px);
border-radius: 1.5rem;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 255, 255, 0.1);
}

.message-bubble {
max-width: 85%;
padding: 0.75rem 1.25rem;
border-radius: 1.25rem;
margin-bottom: 0.75rem;
position: relative;
animation: fadeIn 0.3s ease-out;
line-height: 1.6;
}

.user-message {
background: linear-gradient(135deg, #7c3aed, #6d28d9);
align-self: flex-end;
border-bottom-right-radius: 0.5rem;
color: white;
}

.ai-message {
background: rgba(255, 255, 255, 0.08);
align-self: flex-start;
border-bottom-left-radius: 0.5rem;
border: 1px solid rgba(255, 255, 255, 0.05);
}

.pulse {
animation: pulse 1.5s infinite;
}



@keyframes
pulse {
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.7); }
70% { transform: scale(1.05); box-shadow: 0 0 0 10px rgba(124, 58, 237, 0); }
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(124, 58, 237, 0); }
}



@keyframes
fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}

.waveform {
display: flex;
align-items: center;
height: 2.5rem;
gap: 0.25rem;
justify-content: flex-end;
}

.waveform-bar {
background: rgba(255, 255, 255, 0.7);
width: 0.25rem;
border-radius: 0.25rem;
animation: equalize 1.5s infinite ease-in-out;
}



@keyframes
equalize {
0%, 100% { height: 0.5rem; }
50% { height: 1.5rem; }
}

.waveform-bar:nth-child(1) { animation-delay: -0.9s; }
.waveform-bar:nth-child(2) { animation-delay: -0.7s; }
.waveform-bar:nth-child(3) { animation-delay: -0.5s; }
.waveform-bar:nth-child(4) { animation-delay: -0.3s; }
.waveform-bar:nth-child(5) { animation-delay: -0.1s; }

.typing-indicator {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0;
}

.typing-dot {
width: 0.5rem;
height: 0.5rem;
background: rgba(255, 255, 255, 0.7);
border-radius: 50%;
animation: typingAnimation 1.4s infinite ease-in-out;
}

.typing-dot:nth-child(1) { animation-delay: 0s; }
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }



@keyframes
typingAnimation {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-0.25rem); }
}

.scrollbar-hide::-webkit-scrollbar {
display: none;
}

.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}

.modal-overlay {
background: rgba(0, 0, 0, 0.7);
}

.modal-content {
animation: modalFadeIn 0.3s ease-out;
}



@keyframes
modalFadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}

.voice-btn {
transition: all 0.3s ease;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}

.voice-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}

.voice-btn:active {
transform: translateY(0);
}

.language-badge {
font-size: 0.65rem;
padding: 0.15rem 0.5rem;
border-radius: 9999px;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
}

/* RTL specific styles */
[dir="rtl"] .message-bubble {
text-align: right;
}

[dir="rtl"] .ai-message {
margin-right: 1rem;
}

[dir="rtl"] .user-message {
margin-left: 1rem;
}

/* Dark mode toggle animation */
.toggle-circle {
transition: all 0.3s ease;
}

input:checked ~ .toggle-circle {
transform: translateX(1.25rem);
}
</style>
</head>
<body class="flex items-center justify-center p-4 md:p-6">
<div class="chat-container w-full max-w-2xl h-[85vh] md:h-[80vh] flex flex-col">
<!-- Header -->
<div class="p-4 border-b border-slate-700 flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center shadow-md">
<i class="fas fa-robot text-white text-lg"></i>
</div>
<div>
<h2 class="font-bold text-lg">مساعد لهــجة الصوتي</h2>
<div class="flex items-center gap-2">
<span class="text-xs text-slate-300">مدعوم بالذكاء الاصطناعي</span>
<span class="language-badge">العربية</span>
</div>
</div>
</div>
<div class="flex items-center gap-2">
<button id="dark-mode-toggle" class="p-2 rounded-full hover:bg-slate-700 transition">
<i class="fas fa-moon text-slate-300"></i>
</button>
<button id="settings-btn" class="p-2 rounded-full hover:bg-slate-700 transition">
<i class="fas fa-cog text-slate-300"></i>
</button>
</div>
</div>

<!-- Chat Messages -->
<div id="chat-messages" class="flex-1 p-4 overflow-y-auto scrollbar-hide flex flex-col">
<!-- Initial welcome message -->
<div class="message-bubble ai-message">
<p>مرحباً بك! 👋 أنا مساعدك الصوتي الذكي "لُحْجَة". يمكنك التحدث معي بالضغط على زر الميكروفون أدناه.</p>
</div>
<div class="message-bubble ai-message">
<p>أنا أستطيع الإجابة على أسئلتك، تقديم المعلومات، وحتى إجراء محادثات ذكية معك. جرب أن تسألني عن أي شيء!</p>
</div>
</div>

<!-- Input Area -->
<div class="p-4 border-t border-slate-700">
<div class="flex items-center gap-2">
<button id="voice-btn" class="voice-btn w-14 h-14 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center text-white hover:from-purple-700 hover:to-blue-600 transition-all shadow-lg">
<i class="fas fa-microphone text-xl"></i>
</button>
<div class="flex-1 bg-slate-700 rounded-full px-4 py-2 flex items-center justify-between">
<p id="voice-status" class="text-sm text-slate-300">اضغط على الميكروفون للتحدث</p>
<div id="waveform" class="waveform hidden">
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
</div>
</div>
<button id="keyboard-btn" class="w-12 h-12 rounded-full bg-slate-700 flex items-center justify-center text-slate-300 hover:bg-slate-600 transition">
<i class="fas fa-keyboard text-lg"></i>
</button>
</div>
</div>
</div>

<!-- Settings Modal -->
<div id="settings-modal" class="fixed inset-0 modal-overlay flex items-center justify-center hidden z-50 p-4">
<div class="bg-slate-800 rounded-xl p-6 w-full max-w-md modal-content">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold">إعدادات المساعد</h3>
<button id="close-settings" class="text-slate-400 hover:text-white p-1 rounded-full hover:bg-slate-700">
<i class="fas fa-times text-lg"></i>
</button>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium mb-2">نموذج ا�

Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +1024 -18
  3. prompts.txt +1956 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Chatspeech
3
- emoji: 🌍
4
- colorFrom: purple
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: chatspeech
3
+ emoji: 🐳
4
+ colorFrom: yellow
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1025 @@
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>LAHJA AI - مساعد صوتي ذكي</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
10
+ <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
11
+ <style>
12
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700&display=swap');
13
+
14
+ body {
15
+ font-family: 'Tajawal', sans-serif;
16
+ background: linear-gradient(135deg, #0f172a, #1e293b);
17
+ color: #fff;
18
+ min-height: 100vh;
19
+ }
20
+
21
+ .chat-container {
22
+ background: rgba(15, 23, 42, 0.8);
23
+ backdrop-filter: blur(10px);
24
+ border-radius: 1.5rem;
25
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
26
+ border: 1px solid rgba(255, 255, 255, 0.1);
27
+ }
28
+
29
+ .message-bubble {
30
+ max-width: 85%;
31
+ padding: 0.75rem 1.25rem;
32
+ border-radius: 1.25rem;
33
+ margin-bottom: 0.75rem;
34
+ position: relative;
35
+ animation: fadeIn 0.3s ease-out;
36
+ line-height: 1.6;
37
+ }
38
+
39
+ .user-message {
40
+ background: linear-gradient(135deg, #7c3aed, #6d28d9);
41
+ align-self: flex-end;
42
+ border-bottom-right-radius: 0.5rem;
43
+ color: white;
44
+ }
45
+
46
+ .ai-message {
47
+ background: rgba(255, 255, 255, 0.08);
48
+ align-self: flex-start;
49
+ border-bottom-left-radius: 0.5rem;
50
+ border: 1px solid rgba(255, 255, 255, 0.05);
51
+ }
52
+
53
+ .pulse {
54
+ animation: pulse 1.5s infinite;
55
+ }
56
+
57
+ @keyframes pulse {
58
+ 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.7); }
59
+ 70% { transform: scale(1.05); box-shadow: 0 0 0 10px rgba(124, 58, 237, 0); }
60
+ 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(124, 58, 237, 0); }
61
+ }
62
+
63
+ @keyframes fadeIn {
64
+ from { opacity: 0; transform: translateY(10px); }
65
+ to { opacity: 1; transform: translateY(0); }
66
+ }
67
+
68
+ .waveform {
69
+ display: flex;
70
+ align-items: center;
71
+ height: 2.5rem;
72
+ gap: 0.25rem;
73
+ justify-content: flex-end;
74
+ }
75
+
76
+ .waveform-bar {
77
+ background: rgba(255, 255, 255, 0.7);
78
+ width: 0.25rem;
79
+ border-radius: 0.25rem;
80
+ animation: equalize 1.5s infinite ease-in-out;
81
+ }
82
+
83
+ @keyframes equalize {
84
+ 0%, 100% { height: 0.5rem; }
85
+ 50% { height: 1.5rem; }
86
+ }
87
+
88
+ .waveform-bar:nth-child(1) { animation-delay: -0.9s; }
89
+ .waveform-bar:nth-child(2) { animation-delay: -0.7s; }
90
+ .waveform-bar:nth-child(3) { animation-delay: -0.5s; }
91
+ .waveform-bar:nth-child(4) { animation-delay: -0.3s; }
92
+ .waveform-bar:nth-child(5) { animation-delay: -0.1s; }
93
+
94
+ .typing-indicator {
95
+ display: flex;
96
+ align-items: center;
97
+ gap: 0.5rem;
98
+ padding: 0.5rem 0;
99
+ }
100
+
101
+ .typing-dot {
102
+ width: 0.5rem;
103
+ height: 0.5rem;
104
+ background: rgba(255, 255, 255, 0.7);
105
+ border-radius: 50%;
106
+ animation: typingAnimation 1.4s infinite ease-in-out;
107
+ }
108
+
109
+ .typing-dot:nth-child(1) { animation-delay: 0s; }
110
+ .typing-dot:nth-child(2) { animation-delay: 0.2s; }
111
+ .typing-dot:nth-child(3) { animation-delay: 0.4s; }
112
+
113
+ @keyframes typingAnimation {
114
+ 0%, 60%, 100% { transform: translateY(0); }
115
+ 30% { transform: translateY(-0.25rem); }
116
+ }
117
+
118
+ .scrollbar-hide::-webkit-scrollbar {
119
+ display: none;
120
+ }
121
+
122
+ .scrollbar-hide {
123
+ -ms-overflow-style: none;
124
+ scrollbar-width: none;
125
+ }
126
+
127
+ .modal-overlay {
128
+ background: rgba(0, 0, 0, 0.7);
129
+ }
130
+
131
+ .modal-content {
132
+ animation: modalFadeIn 0.3s ease-out;
133
+ }
134
+
135
+ @keyframes modalFadeIn {
136
+ from { opacity: 0; transform: translateY(20px); }
137
+ to { opacity: 1; transform: translateY(0); }
138
+ }
139
+
140
+ .voice-btn {
141
+ transition: all 0.3s ease;
142
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
143
+ }
144
+
145
+ .voice-btn:hover {
146
+ transform: translateY(-2px);
147
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
148
+ }
149
+
150
+ .voice-btn:active {
151
+ transform: translateY(0);
152
+ }
153
+
154
+ .language-badge {
155
+ font-size: 0.65rem;
156
+ padding: 0.15rem 0.5rem;
157
+ border-radius: 9999px;
158
+ background: rgba(255, 255, 255, 0.1);
159
+ border: 1px solid rgba(255, 255, 255, 0.2);
160
+ }
161
+
162
+ /* RTL specific styles */
163
+ [dir="rtl"] .message-bubble {
164
+ text-align: right;
165
+ }
166
+
167
+ [dir="rtl"] .ai-message {
168
+ margin-right: 1rem;
169
+ }
170
+
171
+ [dir="rtl"] .user-message {
172
+ margin-left: 1rem;
173
+ }
174
+
175
+ /* Dark mode toggle animation */
176
+ .toggle-circle {
177
+ transition: all 0.3s ease;
178
+ }
179
+
180
+ input:checked ~ .toggle-circle {
181
+ transform: translateX(1.25rem);
182
+ }
183
+
184
+ /* Audio player styles */
185
+ .audio-player {
186
+ width: 100%;
187
+ margin-top: 1rem;
188
+ display: none;
189
+ }
190
+
191
+ .audio-player audio {
192
+ width: 100%;
193
+ border-radius: 0.5rem;
194
+ }
195
+
196
+ /* Navigation styles */
197
+ .nav-tabs {
198
+ display: flex;
199
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
200
+ margin-bottom: 1rem;
201
+ }
202
+
203
+ .nav-tab {
204
+ padding: 0.75rem 1.5rem;
205
+ cursor: pointer;
206
+ border-bottom: 2px solid transparent;
207
+ transition: all 0.3s ease;
208
+ }
209
+
210
+ .nav-tab.active {
211
+ border-bottom: 2px solid #7c3aed;
212
+ color: white;
213
+ font-weight: 500;
214
+ }
215
+
216
+ .nav-tab:hover:not(.active) {
217
+ border-bottom: 2px solid rgba(124, 58, 237, 0.5);
218
+ }
219
+
220
+ .tab-content {
221
+ display: none;
222
+ }
223
+
224
+ .tab-content.active {
225
+ display: block;
226
+ }
227
+
228
+ /* System sounds toggle */
229
+ .system-sounds-toggle {
230
+ display: flex;
231
+ align-items: center;
232
+ justify-content: space-between;
233
+ margin-top: 1rem;
234
+ padding: 0.75rem 1rem;
235
+ background: rgba(255, 255, 255, 0.05);
236
+ border-radius: 0.5rem;
237
+ }
238
+
239
+ /* Sound selection dropdown */
240
+ .sound-select {
241
+ margin-top: 0.5rem;
242
+ width: 100%;
243
+ padding: 0.5rem;
244
+ background: rgba(255, 255, 255, 0.1);
245
+ border: 1px solid rgba(255, 255, 255, 0.2);
246
+ border-radius: 0.375rem;
247
+ color: white;
248
+ }
249
+ </style>
250
+ </head>
251
+ <body class="flex items-center justify-center p-4 md:p-6">
252
+ <div class="chat-container w-full max-w-2xl h-[85vh] md:h-[80vh] flex flex-col">
253
+ <!-- Navigation Tabs -->
254
+ <div class="nav-tabs flex border-b border-slate-700">
255
+ <button class="nav-tab active px-4 py-2" data-tab="text">المحادثة النصية</button>
256
+ <button class="nav-tab px-4 py-2" data-tab="speech">المحادثة الصوتية</button>
257
+ </div>
258
+ <!-- Header with navigation tabs -->
259
+ <div class="p-4 border-b border-slate-700">
260
+ <div class="flex items-center justify-between mb-2">
261
+ <div class="flex items-center gap-3">
262
+ <div class="w-10 h-10 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center shadow-md">
263
+ <i class="fas fa-robot text-white text-lg"></i>
264
+ </div>
265
+ <div>
266
+ <h2 class="font-bold text-lg">مساعد لهــجة الصوتي</h2>
267
+ <div class="flex items-center gap-2">
268
+ <span class="text-xs text-slate-300">مدعوم بالذكاء الاصطناعي</span>
269
+ <span class="language-badge">العربية</span>
270
+ </div>
271
+ </div>
272
+ </div>
273
+ <div class="flex items-center gap-2">
274
+ <button id="dark-mode-toggle" class="p-2 rounded-full hover:bg-slate-700 transition">
275
+ <i class="fas fa-moon text-slate-300"></i>
276
+ </button>
277
+ <button id="settings-btn" class="p-2 rounded-full hover:bg-slate-700 transition">
278
+ <i class="fas fa-cog text-slate-300"></i>
279
+ </button>
280
+ </div>
281
+ </div>
282
+
283
+ <div class="nav-tabs">
284
+ <div class="nav-tab active" data-tab="chat">المحادثة النصية</div>
285
+ <div class="nav-tab" data-tab="voice">المحادثة الصوتية</div>
286
+ </div>
287
+ </div>
288
+
289
+ <!-- Chat Tab Content -->
290
+ <div id="chat-tab" class="tab-content active flex-1 p-4 overflow-y-auto scrollbar-hide flex flex-col">
291
+ <!-- Initial welcome message -->
292
+ <div class="message-bubble ai-message">
293
+ <p>مرحباً بك! 👋 أنا مساعدك الصوتي الذكي "لُحْجَة". يمكنك التحدث معي بالضغط على زر الميكروفون أدناه.</p>
294
+ </div>
295
+ <div class="message-bubble ai-message">
296
+ <p>أنا أستطيع الإجابة على أسئلتك، تقديم المعلومات، وحتى إجراء محادثات ذكية معك. جرب أن تسألني عن أي شيء!</p>
297
+ </div>
298
+
299
+ <!-- Audio player for responses -->
300
+ <div id="audio-player" class="audio-player">
301
+ <audio controls id="response-audio"></audio>
302
+ </div>
303
+ </div>
304
+
305
+ <!-- Voice Tab Content -->
306
+ <div id="voice-tab" class="tab-content flex-1 p-4 overflow-y-auto scrollbar-hide flex flex-col items-center justify-center">
307
+ <!-- Voice Assistant UI -->
308
+ <div class="circle-outer w-64 h-64 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center cursor-pointer mb-4" id="micCircle">
309
+ <div class="circle-middle w-48 h-48 rounded-full bg-purple-500 flex items-center justify-center">
310
+ <div class="circle-inner w-32 h-32 rounded-full bg-white flex items-center justify-center">
311
+ <i class="fas fa-microphone text-purple-600 text-3xl" id="micIcon"></i>
312
+ </div>
313
+ </div>
314
+ </div>
315
+
316
+ <div class="status text-center text-lg mb-4" id="voiceStatus">انقر على الدائرة للتحدث</div>
317
+
318
+ <div class="wave hidden" id="wave">
319
+ <span></span><span></span><span></span><span></span><span></span>
320
+ </div>
321
+
322
+ <!-- Audio player for voice responses -->
323
+ <div id="voice-audio-player" class="audio-player mt-4">
324
+ <audio controls id="voice-response-audio"></audio>
325
+ </div>
326
+ </div>
327
+
328
+ <!-- Input Area for Chat Tab -->
329
+ <div id="chat-input" class="p-4 border-t border-slate-700">
330
+ <div class="flex items-center gap-2">
331
+ <button id="voice-btn" class="voice-btn w-14 h-14 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center text-white hover:from-purple-700 hover:to-blue-600 transition-all shadow-lg">
332
+ <i class="fas fa-microphone text-xl"></i>
333
+ </button>
334
+ <div class="flex-1 bg-slate-700 rounded-full px-4 py-2 flex items-center justify-between">
335
+ <p id="voice-status" class="text-sm text-slate-300">اضغط على الميكروفون للتحدث</p>
336
+ <div id="waveform" class="waveform hidden">
337
+ <div class="waveform-bar"></div>
338
+ <div class="waveform-bar"></div>
339
+ <div class="waveform-bar"></div>
340
+ <div class="waveform-bar"></div>
341
+ <div class="waveform-bar"></div>
342
+ </div>
343
+ </div>
344
+ <button id="keyboard-btn" class="w-12 h-12 rounded-full bg-slate-700 flex items-center justify-center text-slate-300 hover:bg-slate-600 transition">
345
+ <i class="fas fa-keyboard text-lg"></i>
346
+ </button>
347
+ </div>
348
+ </div>
349
+ </div>
350
+
351
+ <!-- Settings Modal -->
352
+ <div id="settings-modal" class="fixed inset-0 modal-overlay flex items-center justify-center hidden z-50 p-4">
353
+ <div class="bg-slate-800 rounded-xl p-6 w-full max-w-md modal-content">
354
+ <div class="flex justify-between items-center mb-4">
355
+ <h3 class="text-xl font-bold">إعدادات المساعد</h3>
356
+ <button id="close-settings" class="text-slate-400 hover:text-white p-1 rounded-full hover:bg-slate-700">
357
+ <i class="fas fa-times text-lg"></i>
358
+ </button>
359
+ </div>
360
+ <div class="space-y-4">
361
+ <div>
362
+ <label class="block text-sm font-medium mb-2">نموذج الصوت</label>
363
+ <select id="voiceSelect" class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-2 text-white focus:ring-2 focus:ring-purple-500 focus:border-transparent">
364
+ <option value="SA2">الله��ة النجدية - حصة v2</option>
365
+ <option value="us">الإنجليزية الأمريكية</option>
366
+ <option value="SA1">اللهجة النجدية - حصة v1</option>
367
+ <option value="SA3">اللهجة النجدية - أحمد v1</option>
368
+ </select>
369
+ </div>
370
+ <div>
371
+ <label class="block text-sm font-medium mb-2">نوع الصوت</label>
372
+ <select id="voiceType" class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-2 text-white focus:ring-2 focus:ring-purple-500 focus:border-transparent">
373
+ <option value="male">ذكر</option>
374
+ <option value="female">أنثى</option>
375
+ </select>
376
+ </div>
377
+ <div>
378
+ <label class="block text-sm font-medium mb-2">سرعة الصوت</label>
379
+ <div class="flex items-center gap-3">
380
+ <span class="text-slate-300 text-sm">بطيء</span>
381
+ <input type="range" id="voiceSpeed" min="0.5" max="2" step="0.1" value="1" class="w-full h-2 bg-slate-600 rounded-lg appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-purple-500">
382
+ <span class="text-slate-300 text-sm">سريع</span>
383
+ </div>
384
+ </div>
385
+ <div class="pt-2">
386
+ <label class="inline-flex items-center cursor-pointer">
387
+ <input type="checkbox" id="voiceResponsesToggle" class="sr-only peer" checked>
388
+ <div class="relative w-11 h-6 bg-slate-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
389
+ <span class="mr-3 text-sm font-medium text-slate-300">تفعيل الردود الصوتية</span>
390
+ </label>
391
+ </div>
392
+
393
+ <!-- System Sounds Settings -->
394
+ <div class="system-sounds-toggle">
395
+ <span class="text-sm font-medium">أصوات النظام</span>
396
+ <label class="relative inline-flex items-center cursor-pointer">
397
+ <input type="checkbox" id="systemSoundsToggle" class="sr-only peer" checked>
398
+ <div class="w-11 h-6 bg-slate-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
399
+ </label>
400
+ </div>
401
+
402
+ <div id="sound-options" class="mt-2">
403
+ <label class="block text-sm font-medium mb-2">صوت بداية المحادثة</label>
404
+ <select id="startSound" class="sound-select">
405
+ <option value="chime">جرس</option>
406
+ <option value="beep">بيب</option>
407
+ <option value="ding">دينغ</option>
408
+ </select>
409
+
410
+ <label class="block text-sm font-medium mb-2 mt-4">صوت نهاية المحادثة</label>
411
+ <select id="endSound" class="sound-select">
412
+ <option value="chime">جرس</option>
413
+ <option value="beep">بيب</option>
414
+ <option value="ding">دينغ</option>
415
+ </select>
416
+
417
+ <label class="block text-sm font-medium mb-2 mt-4">صوت الخطأ</label>
418
+ <select id="errorSound" class="sound-select">
419
+ <option value="alert">تنبيه</option>
420
+ <option value="buzz">طنين</option>
421
+ </select>
422
+ </div>
423
+ </div>
424
+ <div class="mt-6 flex justify-end gap-3">
425
+ <button id="cancel-settings" class="px-4 py-2 bg-slate-700 rounded-lg hover:bg-slate-600 transition">
426
+ إلغاء
427
+ </button>
428
+ <button id="save-settings" class="px-4 py-2 bg-purple-600 rounded-lg hover:bg-purple-700 transition font-medium">
429
+ حفظ الإعدادات
430
+ </button>
431
+ </div>
432
+ </div>
433
+ </div>
434
+
435
+ <!-- Keyboard Input Modal -->
436
+ <div id="keyboard-modal" class="fixed inset-0 modal-overlay flex items-center justify-center hidden z-50 p-4">
437
+ <div class="bg-slate-800 rounded-xl p-6 w-full max-w-md modal-content">
438
+ <div class="flex justify-between items-center mb-4">
439
+ <h3 class="text-xl font-bold">اكتب رسالتك</h3>
440
+ <button id="close-keyboard" class="text-slate-400 hover:text-white p-1 rounded-full hover:bg-slate-700">
441
+ <i class="fas fa-times text-lg"></i>
442
+ </button>
443
+ </div>
444
+ <div class="mb-4">
445
+ <textarea id="text-input" class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-3 text-white h-32 focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="اكتب رسالتك هنا..."></textarea>
446
+ </div>
447
+ <div class="flex justify-end gap-3">
448
+ <button id="cancel-keyboard" class="px-4 py-2 bg-slate-700 rounded-lg hover:bg-slate-600 transition">
449
+ إلغاء
450
+ </button>
451
+ <button id="send-text" class="px-4 py-2 bg-purple-600 rounded-lg hover:bg-purple-700 transition font-medium">
452
+ إرسال
453
+ </button>
454
+ </div>
455
+ </div>
456
+ </div>
457
+
458
+ <!-- Audio elements for system sounds -->
459
+ <audio id="start-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-positive-interface-beep-221.mp3"></audio>
460
+ <audio id="end-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-achievement-bell-600.mp3"></audio>
461
+ <audio id="error-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-warning-alarm-buzzer-991.mp3"></audio>
462
+
463
+ <!-- Audio element for dialect preview -->
464
+ <audio id="dialect-preview" class="hidden"></audio>
465
+
466
+ <script>
467
+ // Initialize AOS animations
468
+ AOS.init();
469
+
470
+ // State management
471
+ const state = {
472
+ settings: {
473
+ voiceModel: 'SA2',
474
+ voiceType: 'male',
475
+ voiceSpeed: 1,
476
+ voiceResponses: true,
477
+ systemSounds: true,
478
+ startSound: 'chime',
479
+ endSound: 'chime',
480
+ errorSound: 'alert'
481
+ },
482
+ conversationHistory: [],
483
+ isListening: false,
484
+ isDarkMode: true,
485
+ currentTab: 'chat'
486
+ };
487
+
488
+ // DOM Elements
489
+ const elements = {
490
+ voiceBtn: document.getElementById('voice-btn'),
491
+ voiceStatus: document.getElementById('voice-status'),
492
+ waveform: document.getElementById('waveform'),
493
+ chatMessages: document.getElementById('chat-tab'),
494
+ voiceMessages: document.getElementById('voice-tab'),
495
+ settingsBtn: document.getElementById('settings-btn'),
496
+ settingsModal: document.getElementById('settings-modal'),
497
+ closeSettings: document.getElementById('close-settings'),
498
+ saveSettings: document.getElementById('save-settings'),
499
+ cancelSettings: document.getElementById('cancel-settings'),
500
+ keyboardBtn: document.getElementById('keyboard-btn'),
501
+ keyboardModal: document.getElementById('keyboard-modal'),
502
+ closeKeyboard: document.getElementById('close-keyboard'),
503
+ cancelKeyboard: document.getElementById('cancel-keyboard'),
504
+ sendText: document.getElementById('send-text'),
505
+ textInput: document.getElementById('text-input'),
506
+ darkModeToggle: document.getElementById('dark-mode-toggle'),
507
+ audioPlayer: document.getElementById('audio-player'),
508
+ responseAudio: document.getElementById('response-audio'),
509
+ voiceAudioPlayer: document.getElementById('voice-audio-player'),
510
+ voiceResponseAudio: document.getElementById('voice-response-audio'),
511
+ micCircle: document.getElementById('micCircle'),
512
+ micIcon: document.getElementById('micIcon'),
513
+ voiceStatusText: document.getElementById('voiceStatus'),
514
+ wave: document.getElementById('wave'),
515
+ navTabs: document.querySelectorAll('.nav-tab'),
516
+ tabContents: document.querySelectorAll('.tab-content'),
517
+ voiceSelect: document.getElementById('voiceSelect'),
518
+ voiceType: document.getElementById('voiceType'),
519
+ voiceSpeed: document.getElementById('voiceSpeed'),
520
+ voiceResponsesToggle: document.getElementById('voiceResponsesToggle'),
521
+ systemSoundsToggle: document.getElementById('systemSoundsToggle'),
522
+ startSound: document.getElementById('startSound'),
523
+ endSound: document.getElementById('endSound'),
524
+ errorSound: document.getElementById('errorSound'),
525
+ startAudio: document.getElementById('start-sound'),
526
+ endAudio: document.getElementById('end-sound'),
527
+ errorAudio: document.getElementById('error-sound')
528
+ };
529
+
530
+ // Initialize speech recognition
531
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
532
+ const recognition = new SpeechRecognition();
533
+ recognition.lang = 'ar-SA';
534
+ recognition.interimResults = false;
535
+ recognition.maxAlternatives = 1;
536
+
537
+ // Speech synthesis
538
+ const synth = window.speechSynthesis;
539
+
540
+ // VITS Model Integration
541
+ const voiceModels = {
542
+ 'us': 'wasmdashai/vits-en-v1',
543
+ 'SA1': 'wasmdashai/vits-ar-sa-huba-v1',
544
+ 'SA2': 'wasmdashai/vits-ar-sa-huba-v2',
545
+ 'SA3': 'wasmdashai/vits-ar-sa-A',
546
+ };
547
+
548
+ // Load settings from localStorage
549
+ function loadSettings() {
550
+ const savedSettings = localStorage.getItem('lahjaSettings');
551
+ if (savedSettings) {
552
+ state.settings = JSON.parse(savedSettings);
553
+ applySettings();
554
+ }
555
+ }
556
+
557
+ // Save settings to localStorage
558
+ function saveSettings() {
559
+ localStorage.setItem('lahjaSettings', JSON.stringify(state.settings));
560
+ }
561
+
562
+ // Apply settings to UI
563
+ function applySettings() {
564
+ // Update UI elements with current settings
565
+ elements.voiceSelect.value = state.settings.voiceModel;
566
+ elements.voiceType.value = state.settings.voiceType;
567
+ elements.voiceSpeed.value = state.settings.voiceSpeed;
568
+ elements.voiceResponsesToggle.checked = state.settings.voiceResponses;
569
+ elements.systemSoundsToggle.checked = state.settings.systemSounds;
570
+ elements.startSound.value = state.settings.startSound;
571
+ elements.endSound.value = state.settings.endSound;
572
+ elements.errorSound.value = state.settings.errorSound;
573
+
574
+ // Update audio sources
575
+ updateSystemSounds();
576
+ }
577
+
578
+ // Update system sounds based on settings
579
+ function updateSystemSounds() {
580
+ elements.startAudio.src = getSoundPath(state.settings.startSound);
581
+ elements.endAudio.src = getSoundPath(state.settings.endSound);
582
+ elements.errorAudio.src = getSoundPath(state.settings.errorSound);
583
+ }
584
+
585
+ // Get sound path based on sound type
586
+ function getSoundPath(soundType) {
587
+ const sounds = {
588
+ 'chime': 'https://assets.mixkit.co/sfx/preview/mixkit-positive-interface-beep-221.mp3',
589
+ 'beep': 'https://assets.mixkit.co/sfx/preview/mixkit-software-interface-start-2574.mp3',
590
+ 'ding': 'https://assets.mixkit.co/sfx/preview/mixkit-achievement-bell-600.mp3',
591
+ 'alert': 'https://assets.mixkit.co/sfx/preview/mixkit-warning-alarm-buzzer-991.mp3',
592
+ 'buzz': 'https://assets.mixkit.co/sfx/preview/mixkit-sci-fi-alarm-905.mp3'
593
+ };
594
+ return sounds[soundType] || sounds['chime'];
595
+ }
596
+
597
+ // Play system sound
598
+ function playSystemSound(type) {
599
+ if (!state.settings.systemSounds) return;
600
+
601
+ const soundMap = {
602
+ 'start': elements.startAudio,
603
+ 'end': elements.endAudio,
604
+ 'error': elements.errorAudio
605
+ };
606
+
607
+ const sound = soundMap[type];
608
+ if (sound) {
609
+ sound.currentTime = 0;
610
+ sound.play().catch(e => console.error('Error playing sound:', e));
611
+ }
612
+ }
613
+
614
+ // Play dialect preview
615
+ async function playDialectPreview(voiceModel) {
616
+ try {
617
+ const client = await Client.connect("wasmdashai/DemoLahja");
618
+ const result = await client.predict("/predict", {
619
+ text: "مرحباً بك في مساعد لهجة الصوتي",
620
+ name_model: voiceModels[voiceModel],
621
+ speaking_rate: 1.0
622
+ });
623
+
624
+ const audioUrl = result.data?.[0]?.url;
625
+ if (audioUrl) {
626
+ elements.dialectPreview.src = audioUrl;
627
+ elements.dialectPreview.play().catch(e => console.error('Error playing preview:', e));
628
+ }
629
+ } catch (err) {
630
+ console.error("Preview error:", err);
631
+ }
632
+ }
633
+
634
+ // Event Listeners
635
+ function setupEventListeners() {
636
+ // Navigation tabs
637
+ elements.navTabs.forEach(tab => {
638
+ tab.addEventListener('click', () => {
639
+ const tabId = tab.getAttribute('data-tab');
640
+ switchTab(tabId);
641
+ });
642
+ });
643
+
644
+ // Voice recognition
645
+ elements.voiceBtn.addEventListener('click', toggleVoiceRecognition);
646
+ elements.micCircle.addEventListener('click', toggleVoiceRecognition);
647
+
648
+ // Settings
649
+ elements.settingsBtn.addEventListener('click', () => elements.settingsModal.classList.remove('hidden'));
650
+ elements.closeSettings.addEventListener('click', () => elements.settingsModal.classList.add('hidden'));
651
+ elements.saveSettings.addEventListener('click', saveSettingsHandler);
652
+ elements.cancelSettings.addEventListener('click', () => elements.settingsModal.classList.add('hidden'));
653
+
654
+ // Keyboard input
655
+ elements.keyboardBtn.addEventListener('click', () => elements.keyboardModal.classList.remove('hidden'));
656
+ elements.closeKeyboard.addEventListener('click', () => elements.keyboardModal.classList.add('hidden'));
657
+ elements.cancelKeyboard.addEventListener('click', () => elements.keyboardModal.classList.add('hidden'));
658
+ elements.sendText.addEventListener('click', sendTextMessage);
659
+ elements.textInput.addEventListener('keypress', (e) => {
660
+ if (e.key === 'Enter' && !e.shiftKey) {
661
+ e.preventDefault();
662
+ sendTextMessage();
663
+ }
664
+ });
665
+
666
+ // Dark mode toggle
667
+ elements.darkModeToggle.addEventListener('click', toggleDarkMode);
668
+
669
+ // Recognition event handlers
670
+ recognition.onresult = (event) => {
671
+ const speechResult = event.results[0][0].transcript;
672
+ processUserInput(speechResult);
673
+ stopListening();
674
+ };
675
+
676
+ recognition.onerror = (event) => {
677
+ console.error('Speech recognition error', event.error);
678
+ stopListening();
679
+ playSystemSound('error');
680
+
681
+ if (event.error === 'not-allowed') {
682
+ showSystemMessage('يجب السماح باستخدام الميكروفون لتفعيل هذه الميزة. يرجى التحقق من إعدادات المتصفح.');
683
+ } else {
684
+ showSystemMessage('حدث خطأ في التعرف على الصوت. يرجى المحاولة مرة أخرى لاحقاً.');
685
+ }
686
+ };
687
+
688
+ recognition.onend = () => {
689
+ if (state.isListening) {
690
+ setTimeout(() => {
691
+ try {
692
+ recognition.start();
693
+ } catch (e) {
694
+ console.error('Error restarting recognition:', e);
695
+ stopListening();
696
+ }
697
+ }, 500);
698
+ }
699
+ };
700
+ }
701
+
702
+ // Switch between tabs
703
+ function switchTab(tabId) {
704
+ state.currentTab = tabId;
705
+
706
+ // Update active tab
707
+ elements.navTabs.forEach(tab => {
708
+ if (tab.getAttribute('data-tab') === tabId) {
709
+ tab.classList.add('active');
710
+ } else {
711
+ tab.classList.remove('active');
712
+ }
713
+ });
714
+
715
+ // Update active content
716
+ elements.tabContents.forEach(content => {
717
+ if (content.id === `${tabId}-tab`) {
718
+ content.classList.add('active');
719
+ } else {
720
+ content.classList.remove('active');
721
+ }
722
+ });
723
+
724
+ // Show/hide input area based on tab
725
+ if (tabId === 'chat') {
726
+ elements.chatInput.style.display = 'block';
727
+ } else {
728
+ elements.chatInput.style.display = 'none';
729
+ }
730
+ }
731
+
732
+ // Toggle voice recognition
733
+ function toggleVoiceRecognition() {
734
+ if (state.isListening) {
735
+ stopListening();
736
+ } else {
737
+ startListening();
738
+ }
739
+ }
740
+
741
+ function startListening() {
742
+ state.isListening = true;
743
+
744
+ if (state.currentTab === 'chat') {
745
+ elements.voiceBtn.classList.add('pulse');
746
+ elements.voiceBtn.innerHTML = '<i class="fas fa-stop text-xl"></i>';
747
+ elements.voiceStatus.textContent = 'أنا أستمع لك...';
748
+ elements.waveform.classList.remove('hidden');
749
+ } else {
750
+ elements.micIcon.classList.remove('fa-microphone');
751
+ elements.micIcon.classList.add('fa-stop');
752
+ elements.voiceStatusText.textContent = 'أستمع إليك...';
753
+ elements.wave.classList.remove('hidden');
754
+ elements.micCircle.classList.add('listening');
755
+ }
756
+
757
+ playSystemSound('start');
758
+
759
+ try {
760
+ recognition.start();
761
+ } catch (e) {
762
+ console.error('Error starting recognition:', e);
763
+ stopListening();
764
+ showSystemMessage('حدث خطأ في تشغيل الميكروفون. يرجى التحقق من الإذن.');
765
+ }
766
+ }
767
+
768
+ function stopListening() {
769
+ state.isListening = false;
770
+
771
+ if (state.currentTab === 'chat') {
772
+ elements.voiceBtn.classList.remove('pulse');
773
+ elements.voiceBtn.innerHTML = '<i class="fas fa-microphone text-xl"></i>';
774
+ elements.voiceStatus.textContent = 'اضغط على الميكروفون للتحدث';
775
+ elements.waveform.classList.add('hidden');
776
+ } else {
777
+ elements.micIcon.classList.remove('fa-stop');
778
+ elements.micIcon.classList.add('fa-microphone');
779
+ elements.voiceStatusText.textContent = 'انقر على الدائرة للتحدث';
780
+ elements.wave.classList.add('hidden');
781
+ elements.micCircle.classList.remove('listening');
782
+ }
783
+
784
+ playSystemSound('end');
785
+
786
+ try {
787
+ recognition.stop();
788
+ } catch (e) {
789
+ console.error('Error stopping recognition:', e);
790
+ }
791
+ }
792
+
793
+ // Save settings handler
794
+ function saveSettingsHandler() {
795
+ // Update state with new settings
796
+ state.settings = {
797
+ voiceModel: elements.voiceSelect.value,
798
+ voiceType: elements.voiceType.value,
799
+ voiceSpeed: parseFloat(elements.voiceSpeed.value),
800
+ voiceResponses: elements.voiceResponsesToggle.checked,
801
+ systemSounds: elements.systemSoundsToggle.checked,
802
+ startSound: elements.startSound.value,
803
+ endSound: elements.endSound.value,
804
+ errorSound: elements.errorSound.value
805
+ };
806
+
807
+ saveSettings();
808
+ elements.settingsModal.classList.add('hidden');
809
+ showSystemMessage('تم حفظ الإعدادات بنجاح');
810
+ }
811
+
812
+ // Show system message
813
+ function showSystemMessage(text) {
814
+ const messageDiv = document.createElement('div');
815
+ messageDiv.className = 'text-center text-xs text-slate-400 my-2';
816
+ messageDiv.textContent = text;
817
+
818
+ if (state.currentTab === 'chat') {
819
+ elements.chatMessages.appendChild(messageDiv);
820
+ elements.chatMessages.scrollTop = elements.chatMessages.scrollHeight;
821
+ } else {
822
+ elements.voiceMessages.appendChild(messageDiv);
823
+ elements.voiceMessages.scrollTop = elements.voiceMessages.scrollHeight;
824
+ }
825
+ }
826
+
827
+ // Add user message
828
+ function addUserMessage(text) {
829
+ const messageDiv = document.createElement('div');
830
+ messageDiv.className = 'message-bubble user-message';
831
+ messageDiv.innerHTML = `<p>${text}</p>`;
832
+
833
+ if (state.currentTab === 'chat') {
834
+ elements.chatMessages.appendChild(messageDiv);
835
+ elements.chatMessages.scrollTop = elements.chatMessages.scrollHeight;
836
+ } else {
837
+ elements.voiceMessages.appendChild(messageDiv);
838
+ elements.voiceMessages.scrollTop = elements.voiceMessages.scrollHeight;
839
+ }
840
+ }
841
+
842
+ // Add AI message
843
+ function addAiMessage(text) {
844
+ const messageDiv = document.createElement('div');
845
+ messageDiv.className = 'message-bubble ai-message';
846
+
847
+ // Add typing indicator temporarily
848
+ const typingDiv = document.createElement('div');
849
+ typingDiv.className = 'typing-indicator';
850
+ typingDiv.innerHTML = `
851
+ <div class="typing-dot"></div>
852
+ <div class="typing-dot"></div>
853
+ <div class="typing-dot"></div>
854
+ `;
855
+ messageDiv.appendChild(typingDiv);
856
+
857
+ if (state.currentTab === 'chat') {
858
+ elements.chatMessages.appendChild(messageDiv);
859
+ elements.chatMessages.scrollTop = elements.chatMessages.scrollHeight;
860
+ } else {
861
+ elements.voiceMessages.appendChild(messageDiv);
862
+ elements.voiceMessages.scrollTop = elements.voiceMessages.scrollHeight;
863
+ }
864
+
865
+ // Simulate AI thinking delay
866
+ setTimeout(() => {
867
+ typingDiv.remove();
868
+ messageDiv.innerHTML = `<p>${text}</p>`;
869
+
870
+ if (state.settings.voiceResponses) {
871
+ speakResponse(text);
872
+ }
873
+ }, 1500 + Math.random() * 1000);
874
+ }
875
+
876
+ // Speak response
877
+ async function speakResponse(text) {
878
+ const voice = state.settings.voiceModel;
879
+
880
+ try {
881
+ const client = await Client.connect("wasmdashai/DemoLahja");
882
+ const result = await client.predict("/predict", {
883
+ text: text,
884
+ name_model: voiceModels[voice],
885
+ speaking_rate: state.settings.voiceSpeed
886
+ });
887
+
888
+ const audioUrl = result.data?.[0]?.url;
889
+ if (audioUrl) {
890
+ const audioPlayer = state.currentTab === 'chat' ? elements.responseAudio : elements.voiceResponseAudio;
891
+ const playerContainer = state.currentTab === 'chat' ? elements.audioPlayer : elements.voiceAudioPlayer;
892
+
893
+ audioPlayer.src = audioUrl;
894
+ playerContainer.style.display = 'block';
895
+ audioPlayer.play().catch(e => console.error('Error playing audio:', e));
896
+ } else {
897
+ fallbackTTS(text);
898
+ }
899
+ } catch (err) {
900
+ console.error("VITS model error:", err);
901
+ fallbackTTS(text);
902
+ }
903
+ }
904
+
905
+ // Fallback to Web Speech API
906
+ function fallbackTTS(text) {
907
+ if (synth.speaking) {
908
+ synth.cancel();
909
+ }
910
+
911
+ const utterance = new SpeechSynthesisUtterance(text);
912
+ utterance.lang = state.settings.voiceModel === 'us' ? 'en-US' : 'ar-SA';
913
+ utterance.rate = state.settings.voiceSpeed;
914
+ synth.speak(utterance);
915
+ }
916
+
917
+ // Process user input
918
+ function processUserInput(text) {
919
+ if (!text.trim()) return;
920
+
921
+ addUserMessage(text);
922
+ state.conversationHistory.push({ role: 'user', content: text });
923
+
924
+ // Simulate AI response
925
+ simulateChatGPTResponse(text);
926
+ }
927
+
928
+ // Simulate ChatGPT response
929
+ async function simulateChatGPTResponse(userInput) {
930
+ const response = await askAzureOpenAI(userInput);
931
+ setTimeout(() => {
932
+ addAiMessage(response);
933
+ state.conversationHistory.push({ role: 'assistant', content: response });
934
+ }, 2000);
935
+ }
936
+
937
+ // Send text message
938
+ function sendTextMessage() {
939
+ const text = elements.textInput.value.trim();
940
+ if (text) {
941
+ processUserInput(text);
942
+ elements.textInput.value = '';
943
+ elements.keyboardModal.classList.add('hidden');
944
+ }
945
+ }
946
+
947
+ // Toggle dark mode
948
+ function toggleDarkMode() {
949
+ state.isDarkMode = !state.isDarkMode;
950
+ if (state.isDarkMode) {
951
+ document.body.classList.add('bg-gradient-to-br', 'from-slate-900', 'to-slate-800');
952
+ elements.darkModeToggle.innerHTML = '<i class="fas fa-moon text-slate-300"></i>';
953
+ } else {
954
+ document.body.classList.remove('bg-gradient-to-br', 'from-slate-900', 'to-slate-800');
955
+ document.body.classList.add('bg-gradient-to-br', 'from-slate-100', 'to-slate-200');
956
+ elements.darkModeToggle.innerHTML = '<i class="fas fa-sun text-yellow-400"></i>';
957
+ }
958
+ }
959
+
960
+ // Azure OpenAI API call
961
+ async function askAzureOpenAI(prompt) {
962
+ const endpoint = "https://lahja-dev-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2023-03-15-preview";
963
+
964
+ try {
965
+ const response = await fetch(endpoint, {
966
+ method: "POST",
967
+ headers: {
968
+ "Content-Type": "application/json",
969
+ "api-key": "4AwsIf87cyBIgaJVsy0phWUQdZFcbrJxpQBDQNzL4xjcP2MFzrrYJQQJ99BIACHYHv6XJ3w3AAAAACOGYrzM"
970
+ },
971
+ body: JSON.stringify({
972
+ messages: [
973
+ { role: "system", content: "إنت تمثل شركة أسس الذكاء الاصطناعي وترد باللهجة السعودية." },
974
+ { role: "user", content: prompt }
975
+ ]
976
+ }),
977
+ });
978
+
979
+ const data = await response.json();
980
+ return data.choices[0].message.content;
981
+
982
+ } catch (err) {
983
+ console.error("خطأ في الاتصال بـ Azure OpenAI:", err);
984
+ return "أعتذر، حدث خطأ أثناء معالجة طلبك.";
985
+ }
986
+ }
987
+
988
+ // Initialize the app
989
+ function init() {
990
+ loadSettings();
991
+ setupEventListeners();
992
+
993
+ // Add sound preview event listeners
994
+ document.querySelectorAll('.play-sound-btn').forEach(btn => {
995
+ btn.addEventListener('click', function() {
996
+ const soundType = this.getAttribute('data-sound');
997
+ const voiceModel = this.getAttribute('data-voice');
998
+ const type = this.getAttribute('data-type');
999
+
1000
+ if (type === 'system') {
1001
+ playSystemSound(soundType);
1002
+ } else if (type === 'dialect') {
1003
+ playDialectPreview(voiceModel);
1004
+ }
1005
+ });
1006
+ });
1007
+
1008
+ // Add some sample messages after a delay to simulate a more interactive experience
1009
+ setTimeout(() => {
1010
+ if (elements.chatMessages.children.length <= 2) {
1011
+ addAiMessage('هل لديك أي أسئلة محددة تريد أن أساعدك بها اليوم؟ 😊');
1012
+ }
1013
+ }, 8000);
1014
+ }
1015
+
1016
+ // Start the app
1017
+ init();
1018
+ </script>
1019
+
1020
+ <script src="https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js"></script>
1021
+ </body>
1022
  </html>
1023
+
1024
+
1025
+
prompts.txt ADDED
@@ -0,0 +1,1956 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <!DOCTYPE html>
3
+ <html lang="ar" dir="rtl">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>LAHJA AI - مساعد صوتي ذكي</title>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <style>
11
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700&display=swap');
12
+
13
+ body {
14
+ font-family: 'Tajawal', sans-serif;
15
+ background: linear-gradient(135deg, #0f172a, #1e293b);
16
+ color: #fff;
17
+ min-height: 100vh;
18
+ }
19
+
20
+ .chat-container {
21
+ background: rgba(15, 23, 42, 0.8);
22
+ backdrop-filter: blur(10px);
23
+ border-radius: 1.5rem;
24
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
25
+ border: 1px solid rgba(255, 255, 255, 0.1);
26
+ }
27
+
28
+ .message-bubble {
29
+ max-width: 85%;
30
+ padding: 0.75rem 1.25rem;
31
+ border-radius: 1.25rem;
32
+ margin-bottom: 0.75rem;
33
+ position: relative;
34
+ animation: fadeIn 0.3s ease-out;
35
+ line-height: 1.6;
36
+ }
37
+
38
+ .user-message {
39
+ background: linear-gradient(135deg, #7c3aed, #6d28d9);
40
+ align-self: flex-end;
41
+ border-bottom-right-radius: 0.5rem;
42
+ color: white;
43
+ }
44
+
45
+ .ai-message {
46
+ background: rgba(255, 255, 255, 0.08);
47
+ align-self: flex-start;
48
+ border-bottom-left-radius: 0.5rem;
49
+ border: 1px solid rgba(255, 255, 255, 0.05);
50
+ }
51
+
52
+ .pulse {
53
+ animation: pulse 1.5s infinite;
54
+ }
55
+
56
+ @keyframes pulse {
57
+ 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.7); }
58
+ 70% { transform: scale(1.05); box-shadow: 0 0 0 10px rgba(124, 58, 237, 0); }
59
+ 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(124, 58, 237, 0); }
60
+ }
61
+
62
+ @keyframes fadeIn {
63
+ from { opacity: 0; transform: translateY(10px); }
64
+ to { opacity: 1; transform: translateY(0); }
65
+ }
66
+
67
+ .waveform {
68
+ display: flex;
69
+ align-items: center;
70
+ height: 2.5rem;
71
+ gap: 0.25rem;
72
+ justify-content: flex-end;
73
+ }
74
+
75
+ .waveform-bar {
76
+ background: rgba(255, 255, 255, 0.7);
77
+ width: 0.25rem;
78
+ border-radius: 0.25rem;
79
+ animation: equalize 1.5s infinite ease-in-out;
80
+ }
81
+
82
+ @keyframes equalize {
83
+ 0%, 100% { height: 0.5rem; }
84
+ 50% { height: 1.5rem; }
85
+ }
86
+
87
+ .waveform-bar:nth-child(1) { animation-delay: -0.9s; }
88
+ .waveform-bar:nth-child(2) { animation-delay: -0.7s; }
89
+ .waveform-bar:nth-child(3) { animation-delay: -0.5s; }
90
+ .waveform-bar:nth-child(4) { animation-delay: -0.3s; }
91
+ .waveform-bar:nth-child(5) { animation-delay: -0.1s; }
92
+
93
+ .typing-indicator {
94
+ display: flex;
95
+ align-items: center;
96
+ gap: 0.5rem;
97
+ padding: 0.5rem 0;
98
+ }
99
+
100
+ .typing-dot {
101
+ width: 0.5rem;
102
+ height: 0.5rem;
103
+ background: rgba(255, 255, 255, 0.7);
104
+ border-radius: 50%;
105
+ animation: typingAnimation 1.4s infinite ease-in-out;
106
+ }
107
+
108
+ .typing-dot:nth-child(1) { animation-delay: 0s; }
109
+ .typing-dot:nth-child(2) { animation-delay: 0.2s; }
110
+ .typing-dot:nth-child(3) { animation-delay: 0.4s; }
111
+
112
+ @keyframes typingAnimation {
113
+ 0%, 60%, 100% { transform: translateY(0); }
114
+ 30% { transform: translateY(-0.25rem); }
115
+ }
116
+
117
+ .scrollbar-hide::-webkit-scrollbar {
118
+ display: none;
119
+ }
120
+
121
+ .scrollbar-hide {
122
+ -ms-overflow-style: none;
123
+ scrollbar-width: none;
124
+ }
125
+
126
+ .modal-overlay {
127
+ background: rgba(0, 0, 0, 0.7);
128
+ }
129
+
130
+ .modal-content {
131
+ animation: modalFadeIn 0.3s ease-out;
132
+ }
133
+
134
+ @keyframes modalFadeIn {
135
+ from { opacity: 0; transform: translateY(20px); }
136
+ to { opacity: 1; transform: translateY(0); }
137
+ }
138
+
139
+ .voice-btn {
140
+ transition: all 0.3s ease;
141
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
142
+ }
143
+
144
+ .voice-btn:hover {
145
+ transform: translateY(-2px);
146
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
147
+ }
148
+
149
+ .voice-btn:active {
150
+ transform: translateY(0);
151
+ }
152
+
153
+ .language-badge {
154
+ font-size: 0.65rem;
155
+ padding: 0.15rem 0.5rem;
156
+ border-radius: 9999px;
157
+ background: rgba(255, 255, 255, 0.1);
158
+ border: 1px solid rgba(255, 255, 255, 0.2);
159
+ }
160
+
161
+ /* RTL specific styles */
162
+ [dir="rtl"] .message-bubble {
163
+ text-align: right;
164
+ }
165
+
166
+ [dir="rtl"] .ai-message {
167
+ margin-right: 1rem;
168
+ }
169
+
170
+ [dir="rtl"] .user-message {
171
+ margin-left: 1rem;
172
+ }
173
+
174
+ /* Dark mode toggle animation */
175
+ .toggle-circle {
176
+ transition: all 0.3s ease;
177
+ }
178
+
179
+ input:checked ~ .toggle-circle {
180
+ transform: translateX(1.25rem);
181
+ }
182
+ </style>
183
+ </head>
184
+ <body class="flex items-center justify-center p-4 md:p-6">
185
+ <div class="chat-container w-full max-w-2xl h-[85vh] md:h-[80vh] flex flex-col">
186
+ <!-- Header -->
187
+ <div class="p-4 border-b border-slate-700 flex items-center justify-between">
188
+ <div class="flex items-center gap-3">
189
+ <div class="w-10 h-10 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center shadow-md">
190
+ <i class="fas fa-robot text-white text-lg"></i>
191
+ </div>
192
+ <div>
193
+ <h2 class="font-bold text-lg">مساعد لهــجة الصوتي</h2>
194
+ <div class="flex items-center gap-2">
195
+ <span class="text-xs text-slate-300">مدعوم بالذكاء الاصطناعي</span>
196
+ <span class="language-badge">العربية</span>
197
+ </div>
198
+ </div>
199
+ </div>
200
+ <div class="flex items-center gap-2">
201
+ <button id="dark-mode-toggle" class="p-2 rounded-full hover:bg-slate-700 transition">
202
+ <i class="fas fa-moon text-slate-300"></i>
203
+ </button>
204
+ <button id="settings-btn" class="p-2 rounded-full hover:bg-slate-700 transition">
205
+ <i class="fas fa-cog text-slate-300"></i>
206
+ </button>
207
+ </div>
208
+ </div>
209
+
210
+ <!-- Chat Messages -->
211
+ <div id="chat-messages" class="flex-1 p-4 overflow-y-auto scrollbar-hide flex flex-col">
212
+ <!-- Initial welcome message -->
213
+ <div class="message-bubble ai-message">
214
+ <p>مرحباً بك! 👋 أنا مساعدك الصوتي الذكي "لُحْجَة". يمكنك التحدث معي بالضغط على زر الميكروفون أدناه.</p>
215
+ </div>
216
+ <div class="message-bubble ai-message">
217
+ <p>أنا أستطيع الإجابة على أسئلتك، تقديم المعلومات، وحتى إجراء محادثات ذكية معك. جرب أن تسألني عن أي شيء!</p>
218
+ </div>
219
+ </div>
220
+
221
+ <!-- Input Area -->
222
+ <div class="p-4 border-t border-slate-700">
223
+ <div class="flex items-center gap-2">
224
+ <button id="voice-btn" class="voice-btn w-14 h-14 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center text-white hover:from-purple-700 hover:to-blue-600 transition-all shadow-lg">
225
+ <i class="fas fa-microphone text-xl"></i>
226
+ </button>
227
+ <div class="flex-1 bg-slate-700 rounded-full px-4 py-2 flex items-center justify-between">
228
+ <p id="voice-status" class="text-sm text-slate-300">اضغط على الميكروفون للتحدث</p>
229
+ <div id="waveform" class="waveform hidden">
230
+ <div class="waveform-bar"></div>
231
+ <div class="waveform-bar"></div>
232
+ <div class="waveform-bar"></div>
233
+ <div class="waveform-bar"></div>
234
+ <div class="waveform-bar"></div>
235
+ </div>
236
+ </div>
237
+ <button id="keyboard-btn" class="w-12 h-12 rounded-full bg-slate-700 flex items-center justify-center text-slate-300 hover:bg-slate-600 transition">
238
+ <i class="fas fa-keyboard text-lg"></i>
239
+ </button>
240
+ </div>
241
+ </div>
242
+ </div>
243
+
244
+ <!-- Settings Modal -->
245
+ <div id="settings-modal" class="fixed inset-0 modal-overlay flex items-center justify-center hidden z-50 p-4">
246
+ <div class="bg-slate-800 rounded-xl p-6 w-full max-w-md modal-content">
247
+ <div class="flex justify-between items-center mb-4">
248
+ <h3 class="text-xl font-bold">إعدادات المساعد</h3>
249
+ <button id="close-settings" class="text-slate-400 hover:text-white p-1 rounded-full hover:bg-slate-700">
250
+ <i class="fas fa-times text-lg"></i>
251
+ </button>
252
+ </div>
253
+ <div class="space-y-4">
254
+ <div>
255
+ <label class="block text-sm font-medium mb-2">نموذج الصوت</label>
256
+ <select id="voiceSelect" class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-2 text-white focus:ring-2 focus:ring-purple-500 focus:border-transparent">
257
+ <option value="SA2">اللهجة النجدية - حصة v2</option>
258
+ <option value="us">الإنجليزية الأمريكية</option>
259
+ <option value="SA1">اللهجة النجدية - حصة v1</option>
260
+ <option value="SA3">اللهجة النجدية - أحمد v1</option>
261
+ </select>
262
+ </div>
263
+ <div>
264
+ <label class="block text-sm font-medium mb-2">نوع الصوت</label>
265
+ <select class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-2 text-white focus:ring-2 focus:ring-purple-500 focus:border-transparent">
266
+ <option>ذكر</option>
267
+ <option>أنثى</option>
268
+ </select>
269
+ </div>
270
+ <div>
271
+ <label class="block text-sm font-medium mb-2">سرعة الصوت</label>
272
+ <div class="flex items-center gap-3">
273
+ <span class="text-slate-300 text-sm">بطيء</span>
274
+ <input type="range" min="0.5" max="2" step="0.1" value="1" class="w-full h-2 bg-slate-600 rounded-lg appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-purple-500">
275
+ <span class="text-slate-300 text-sm">سريع</span>
276
+ </div>
277
+ </div>
278
+ <div class="pt-2">
279
+ <label class="inline-flex items-center cursor-pointer">
280
+ <input type="checkbox" value="" class="sr-only peer" checked>
281
+ <div class="relative w-11 h-6 bg-slate-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
282
+ <span class="mr-3 text-sm font-medium text-slate-300">تفعيل الردود الصوتية</span>
283
+ </label>
284
+ </div>
285
+ </div>
286
+ <div class="mt-6 flex justify-end gap-3">
287
+ <button id="cancel-settings" class="px-4 py-2 bg-slate-700 rounded-lg hover:bg-slate-600 transition">
288
+ إلغاء
289
+ </button>
290
+ <button id="save-settings" class="px-4 py-2 bg-purple-600 rounded-lg hover:bg-purple-700 transition font-medium">
291
+ حفظ الإعدادات
292
+ </button>
293
+ </div>
294
+ </div>
295
+ </div>
296
+
297
+ <!-- Keyboard Input Modal -->
298
+ <div id="keyboard-modal" class="fixed inset-0 modal-overlay flex items-center justify-center hidden z-50 p-4">
299
+ <div class="bg-slate-800 rounded-xl p-6 w-full max-w-md modal-content">
300
+ <div class="flex justify-between items-center mb-4">
301
+ <h3 class="text-xl font-bold">اكتب رسالتك</h3>
302
+ <button id="close-keyboard" class="text-slate-400 hover:text-white p-1 rounded-full hover:bg-slate-700">
303
+ <i class="fas fa-times text-lg"></i>
304
+ </button>
305
+ </div>
306
+ <div class="mb-4">
307
+ <textarea id="text-input" class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-3 text-white h-32 focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="اكتب رسالتك هنا..."></textarea>
308
+ </div>
309
+ <div class="flex justify-end gap-3">
310
+ <button id="cancel-keyboard" class="px-4 py-2 bg-slate-700 rounded-lg hover:bg-slate-600 transition">
311
+ إلغاء
312
+ </button>
313
+ <button id="send-text" class="px-4 py-2 bg-purple-600 rounded-lg hover:bg-purple-700 transition font-medium">
314
+ إرسال
315
+ </button>
316
+ </div>
317
+ </div>
318
+ </div>
319
+
320
+ <script type="module">
321
+ async function askAzureOpenAI(prompt)
322
+ {
323
+ const endpoint = "https://lahja-dev-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2023-03-15-preview";
324
+
325
+ try {
326
+ const response = await fetch(endpoint, {
327
+ method: "POST",
328
+ headers: {
329
+ "Content-Type": "application/json",
330
+ "api-key": "4AwsIf87cyBIgaJVsy0phWUQdZFcbrJxpQBDQNzL4xjcP2MFzrrYJQQJ99BIACHYHv6XJ3w3AAAAACOGYrzM"
331
+ },
332
+ body: JSON.stringify({
333
+ messages: [
334
+ { role: "system", content: "إنت تمثل شركة أسس الذكاء الاصطناعي وترد باللهجة السعودية." },
335
+ { role: "user", content: prompt }
336
+ ]
337
+ }),
338
+ });
339
+
340
+ const data = await response.json();
341
+ return data.choices[0].message.content;
342
+
343
+ } catch (err) {
344
+ console.error("خطأ في الاتصال بـ Azure OpenAI:", err);
345
+ return "أعتذر، حدث خطأ أثناء معالجة طلبك.";
346
+ }
347
+ }
348
+ async function simulateChatGPTResponse(userInput)
349
+ {
350
+
351
+ conversationHistory.push({ role: 'user', content: userInput });
352
+
353
+ const response = await askAzureOpenAI(userInput);
354
+ setTimeout(() => {
355
+ addAiMessage(response);
356
+ conversationHistory.push({ role: 'assistant', content: response });
357
+ }, 2000);
358
+
359
+
360
+ }
361
+
362
+
363
+ // دالة المحادثة
364
+
365
+ import {Client} from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
366
+
367
+ // DOM Elements
368
+ const voiceBtn = document.getElementById('voice-btn');
369
+ const voiceStatus = document.getElementById('voice-status');
370
+ const waveform = document.getElementById('waveform');
371
+ const chatMessages = document.getElementById('chat-messages');
372
+ const settingsBtn = document.getElementById('settings-btn');
373
+ const settingsModal = document.getElementById('settings-modal');
374
+ const closeSettings = document.getElementById('close-settings');
375
+ const saveSettings = document.getElementById('save-settings');
376
+ const cancelSettings = document.getElementById('cancel-settings');
377
+ const keyboardBtn = document.getElementById('keyboard-btn');
378
+ const keyboardModal = document.getElementById('keyboard-modal');
379
+ const closeKeyboard = document.getElementById('close-keyboard');
380
+ const cancelKeyboard = document.getElementById('cancel-keyboard');
381
+ const sendText = document.getElementById('send-text');
382
+ const textInput = document.getElementById('text-input');
383
+ const darkModeToggle = document.getElementById('dark-mode-toggle');
384
+
385
+
386
+
387
+ // Speech recognition setup
388
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
389
+ const recognition = new SpeechRecognition();
390
+ recognition.lang = 'ar-SA';
391
+ recognition.interimResults = false;
392
+ recognition.maxAlternatives = 1;
393
+
394
+ // Speech synthesis setup
395
+ const synth = window.speechSynthesis;
396
+
397
+ // VITS Model Integration
398
+ const voiceModels = {
399
+ 'us': 'wasmdashai/vits-en-v1',
400
+ 'SA1': 'wasmdashai/vits-ar-sa-huba-v1',
401
+ 'SA2': 'wasmdashai/vits-ar-sa-huba-v2',
402
+ 'SA3': 'wasmdashai/vits-ar-sa-A',
403
+ };
404
+
405
+ // State variables
406
+ let isListening = false;
407
+ let conversationHistory = [];
408
+ let isDarkMode = true;
409
+
410
+ // Event Listeners
411
+ voiceBtn.addEventListener('click', toggleVoiceRecognition);
412
+ settingsBtn.addEventListener('click', () => settingsModal.classList.remove('hidden'));
413
+ closeSettings.addEventListener('click', () => settingsModal.classList.add('hidden'));
414
+ saveSettings.addEventListener('click', saveSettingsHandler);
415
+ cancelSettings.addEventListener('click', () => settingsModal.classList.add('hidden'));
416
+ keyboardBtn.addEventListener('click', () => keyboardModal.classList.remove('hidden'));
417
+ closeKeyboard.addEventListener('click', () => keyboardModal.classList.add('hidden'));
418
+ cancelKeyboard.addEventListener('click', () => keyboardModal.classList.add('hidden'));
419
+ sendText.addEventListener('click', sendTextMessage);
420
+ textInput.addEventListener('keypress', (e) => {
421
+ if (e.key === 'Enter' && !e.shiftKey) {
422
+ e.preventDefault();
423
+ sendTextMessage();
424
+ }
425
+ });
426
+ darkModeToggle.addEventListener('click', toggleDarkMode);
427
+
428
+ // Functions
429
+ function toggleVoiceRecognition() {
430
+ if (isListening) {
431
+ stopListening();
432
+ } else {
433
+ startListening();
434
+ }
435
+ }
436
+
437
+ function startListening() {
438
+ isListening = true;
439
+ voiceBtn.classList.add('pulse');
440
+ voiceBtn.innerHTML = '<i class="fas fa-stop text-xl"></i>';
441
+ voiceStatus.textContent = 'أنا أستمع لك...';
442
+ waveform.classList.remove('hidden');
443
+
444
+ try {
445
+ recognition.start();
446
+ } catch (e) {
447
+ console.error('Error starting recognition:', e);
448
+ stopListening();
449
+ showSystemMessage('حدث خطأ في تشغيل الميكروفون. يرجى التحقق من الإذن.');
450
+ }
451
+ }
452
+
453
+ function stopListening() {
454
+ isListening = false;
455
+ voiceBtn.classList.remove('pulse');
456
+ voiceBtn.innerHTML = '<i class="fas fa-microphone text-xl"></i>';
457
+ voiceStatus.textContent = 'اضغط على الميكروفون للتحدث';
458
+ waveform.classList.add('hidden');
459
+
460
+ try {
461
+ recognition.stop();
462
+ } catch (e) {
463
+ console.error('Error stopping recognition:', e);
464
+ }
465
+ }
466
+
467
+ function saveSettingsHandler() {
468
+ // In a real app, you would save these settings to localStorage or a backend
469
+ settingsModal.classList.add('hidden');
470
+ showSystemMessage('تم حفظ الإعدادات بنجاح');
471
+ }
472
+
473
+ function showSystemMessage(text) {
474
+ const messageDiv = document.createElement('div');
475
+ messageDiv.className = 'text-center text-xs text-slate-400 my-2';
476
+ messageDiv.textContent = text;
477
+ chatMessages.appendChild(messageDiv);
478
+ chatMessages.scrollTop = chatMessages.scrollHeight;
479
+ }
480
+
481
+ function addUserMessage(text) {
482
+ const messageDiv = document.createElement('div');
483
+ messageDiv.className = 'message-bubble user-message';
484
+ messageDiv.innerHTML = `<p>${text}</p>`;
485
+ chatMessages.appendChild(messageDiv);
486
+ chatMessages.scrollTop = chatMessages.scrollHeight;
487
+ }
488
+
489
+ function addAiMessage(text) {
490
+ const messageDiv = document.createElement('div');
491
+ messageDiv.className = 'message-bubble ai-message';
492
+
493
+ // Add typing indicator temporarily
494
+ const typingDiv = document.createElement('div');
495
+ typingDiv.className = 'typing-indicator';
496
+ typingDiv.innerHTML = `
497
+ <div class="typing-dot"></div>
498
+ <div class="typing-dot"></div>
499
+ <div class="typing-dot"></div>
500
+ `;
501
+ messageDiv.appendChild(typingDiv);
502
+ chatMessages.appendChild(messageDiv);
503
+ chatMessages.scrollTop = chatMessages.scrollHeight;
504
+
505
+ // Simulate AI thinking delay
506
+ setTimeout(() => {
507
+ typingDiv.remove();
508
+ messageDiv.innerHTML = `<p>${text}</p>`;
509
+ speakResponse(text);
510
+ }, 1500 + Math.random() * 1000); // Random delay between 1.5-2.5s for more natural feel
511
+ }
512
+
513
+ async function speakResponse(text) {
514
+ const voiceSelect = document.getElementById('voiceSelect');
515
+ const voice = voiceSelect.value;
516
+
517
+ try {
518
+ const client = await Client.connect("wasmdashai/DemoLahja");
519
+ const result = await client.predict("/predict", {
520
+ text: text,
521
+ name_model: voiceModels[voice],
522
+ speaking_rate: 1.0
523
+ });
524
+
525
+ const audioUrl = result.data?.[0]?.url;
526
+ if (audioUrl) {
527
+ const audio = new Audio(audioUrl);
528
+ audio.play();
529
+ } else {
530
+ fallbackTTS(text);
531
+ }
532
+ } catch (err) {
533
+ console.error("VITS model error:", err);
534
+ fallbackTTS(text);
535
+ }
536
+ }
537
+
538
+ function fallbackTTS(text) {
539
+ if (synth.speaking) {
540
+ synth.cancel();
541
+ }
542
+
543
+ const utterance = new SpeechSynthesisUtterance(text);
544
+ utterance.lang = voiceSelect.value === 'us' ? 'en-US' : 'ar-SA';
545
+ utterance.rate = 1.0;
546
+ synth.speak(utterance);
547
+ }
548
+
549
+ function processUserInput(text) {
550
+ if (!text.trim()) return;
551
+
552
+ addUserMessage(text);
553
+ conversationHistory.push({ role: 'user', content: text });
554
+
555
+ // In a real app, you would send this to your backend which connects to ChatGPT API
556
+ // For this demo, we'll simulate a response
557
+ simulateChatGPTResponse(text);
558
+ }
559
+
560
+ function simulateChatGPTResponseg(userInput) {
561
+ // Enhanced responses with more natural Arabic
562
+ const responses = {
563
+ "مرحبا": "مرحباً بك! 🌸 كيف يمكنني مساعدتك اليوم؟",
564
+ "السلام عليكم": "وعليكم السلام ورحمة الله وبركاته 🌹 كيف حالك اليوم؟",
565
+ "كيف حالك": "الحمد لله بخير، شكراً لسؤالك! 😊 كيف يمكنني مساعدتك؟",
566
+ "ما هو اسمك": "أنا مساع��ك الذكي 'لُحْجَة'، سعيد بتواصلك معي!",
567
+ "من صممك": "تم تطويري باستخدام أحدث تقنيات الذكاء الاصطناعي لخدمتك بشكل أفضل.",
568
+ "ماذا تستطيع ان تفعل": "أستطيع مساعدتك في:\n- الإجابة على أسئلتك\n- تقديم المعلومات\n- إجراء محادثات ذكية\n- وغير ذلك الكثير! جرب أن تسألني 😊",
569
+ "شكرا": "العفو! 🌺 دائماً سعيد بمساعدتك. هل هناك شيء آخر تحتاجه؟",
570
+ "شكراً": "على الرحب والسعة! 💐 لا تتردد في سؤالي عن أي شيء آخر.",
571
+ "وداعا": "إلى اللقاء! 👋 أراك لاحقاً بإذن الله.",
572
+ "مع السلامة": "مع السلامة 🌷 لا تنسى أن تعود إذا احتجت إلى أي مساعدة.",
573
+ "ما هو تاريخ اليوم": `تاريخ اليوم هو: ${new Date().toLocaleDateString("ar-EG", { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}`,
574
+ "ما هو الوقت الان": `الوقت الآن هو: ${new Date().toLocaleTimeString("ar-EG", { hour: 'numeric', minute: 'numeric', second: 'numeric' })}`,
575
+ "من اين انت": "أنا مساعد افتراضي موجود في كل مكان 🌍 حيثما تكون أنت!",
576
+ "ماهي عاصمه السعوديه": "عاصمة المملكة العربية السعودية هي الرياض 🏙️، وهي مدينة جميلة ومزدهرة.",
577
+ "ماهي عاصمه اليمن": "عاصمة اليمن هي صنعاء 🕌، إحدى أقدم المدن المأهولة في العالم.",
578
+ "اعطني نصيحه": "✨ من أفضل النصائح التي يمكنني تقديمها:\n1- لا تؤجل عمل اليوم إلى الغد\n2- ابدأ بخطوات صغيرة نحو أهدافك الكبيرة\n3- حافظ على توازنك بين العمل والحياة الشخصية",
579
+ "كيف اتعلم البرمجة": "لتعلم البرمجة:\n1- ابدأ بلغة سهلة مثل Python\n2- تدرب يومياً ولو قليلاً\n3- انضم لمجتمعات المبرمجين\n4- نفذ مشاريع صغيرة\n5- لا تخف من الأخطاء، فهي جزء من التعلم 💻",
580
+ "ما هو الذكاء الاصطناعي": "الذكاء الاصطناعي هو مجال في علوم الكمبيوتر يهدف إلى جعل الآلات قادرة على أداء مهام تتطلب ذكاءً بشرياً مثل:\n- فهم اللغة\n- التعلم\n- حل المشكلات\n- اتخاذ القرارات",
581
+ "هل يمكنك الغناء": "للأسف لا أستطيع الغناء جيداً ، لكني أستطيع مساعدتك في العثور على الأغاني أو توفير كلماتها!",
582
+ "ما هو الطقس اليوم": "للحصول على معلومات دقيقة عن الطقس، أحتاج إلى معرفة موقعك الجغرافي. يمكنك ذكر المدينة وسأساعدك في ذلك ☀️🌧️",
583
+ "ما هي لغة البرمجة الافضل": "لا توجد لغة برمجة 'أفضل' بشكل مطلق، ولكن:\n- للويب: JavaScript\n- للبيانات: Python\n- للأنظمة: C++\n- للأجهزة المحمولة: Swift/Kotlin\nالاختيار يعتمد على احتياجاتك! 💻"
584
+ };
585
+
586
+ const defaultResponse = "أعتذر، لم أفهم سؤالك بالكامل. هل يمكنك إعادة صياغته بطريقة أخرى؟";
587
+
588
+ // Find the best matching response (case insensitive)
589
+ const normalizedInput = userInput.trim().toLowerCase();
590
+ let response = defaultResponse;
591
+
592
+ for (const [key, value] of Object.entries(responses)) {
593
+ if (normalizedInput.includes(key.toLowerCase())) {
594
+ response = value;
595
+ break;
596
+ }
597
+ }
598
+
599
+ setTimeout(() => {
600
+ addAiMessage(response);
601
+ conversationHistory.push({ role: 'assistant', content: response });
602
+ }, 2000);
603
+ }
604
+
605
+
606
+ function sendTextMessage() {
607
+ const text = textInput.value.trim();
608
+ if (text) {
609
+ processUserInput(text);
610
+ textInput.value = '';
611
+ keyboardModal.classList.add('hidden');
612
+ }
613
+ }
614
+
615
+ function toggleDarkMode() {
616
+ isDarkMode = !isDarkMode;
617
+ if (isDarkMode) {
618
+ document.body.classList.add('bg-gradient-to-br', 'from-slate-900', 'to-slate-800');
619
+ darkModeToggle.innerHTML = '<i class="fas fa-moon text-slate-300"></i>';
620
+ } else {
621
+ document.body.classList.remove('bg-gradient-to-br', 'from-slate-900', 'to-slate-800');
622
+ document.body.classList.add('bg-gradient-to-br', 'from-slate-100', 'to-slate-200');
623
+ darkModeToggle.innerHTML = '<i class="fas fa-sun text-yellow-400"></i>';
624
+ }
625
+ }
626
+
627
+ // Recognition event handlers
628
+ recognition.onresult = (event) => {
629
+ const speechResult = event.results[0][0].transcript;
630
+ processUserInput(speechResult);
631
+ stopListening();
632
+ };
633
+
634
+ recognition.onerror = (event) => {
635
+ console.error('Speech recognition error', event.error);
636
+ stopListening();
637
+
638
+ if (event.error === 'not-allowed') {
639
+ showSystemMessage('يجب السماح باستخدام الميكروفون لتفعيل هذه الميزة. يرجى التحقق من إعدادات المتصفح.');
640
+ } else {
641
+ showSystemMessage('حدث خطأ في التعرف على الصوت. يرجى المحاولة مرة أخرى لاحقاً.');
642
+ }
643
+ };
644
+
645
+ recognition.onend = () => {
646
+ if (isListening) {
647
+ // If we're still supposed to be listening, restart recognition
648
+ setTimeout(() => {
649
+ try {
650
+ recognition.start();
651
+ } catch (e) {
652
+ console.error('Error restarting recognition:', e);
653
+ stopListening();
654
+ }
655
+ }, 500);
656
+ }
657
+ };
658
+
659
+ // Initialize voices when they become available
660
+ if (speechSynthesis.onvoiceschanged !== undefined) {
661
+ speechSynthesis.onvoiceschanged = () => {
662
+ // Voices are now loaded
663
+ };
664
+ }
665
+
666
+ // Add some sample messages after a delay to simulate a more interactive experience
667
+ setTimeout(() => {
668
+ if (chatMessages.children.length <= 2) { // Only if no other messages have been added
669
+ addAiMessage('هل لديك أي أسئلة محددة تريد أن أساعدك بها اليوم؟ 😊');
670
+ }
671
+ }, 8000);
672
+ </script>
673
+
674
+ <div style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px; position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">
675
+ Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle; display: inline-block; margin-right: 3px; filter: brightness(0) invert(1);">
676
+ <a href="https://enzostvs-deepsite.hf.space" style="color: #fff; text-decoration: underline;" target="_blank">DeepSite</a> - 🧬
677
+ <a href="https://enzostvs-deepsite.hf.space?remix=wasmdashai/wasmdashai-chatlhja" style="color: #fff; text-decoration: underline;" target="_blank">Remix</a>
678
+ </div>
679
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=wasmdashai/wasmdashai-wasmdashai-chatlhja" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
680
+ </html> <!DOCTYPE html>
681
+ <html lang="ar" dir="rtl">
682
+ <head>
683
+ <meta charset="UTF-8">
684
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
685
+ <title>مساعد صوتي متحرك - وضع ليلي/نهاري</title>
686
+ <style>
687
+ * { margin:0; padding:0; box-sizing:border-box; font-family:'Segoe UI','Noto Sans Arabic',sans-serif; }
688
+ body {
689
+ background:#fff;
690
+ display:flex;
691
+ justify-content:center;
692
+ align-items:center;
693
+ min-height:100vh;
694
+ flex-direction:column;
695
+ color: rgb(11, 186, 131);
696
+ transition: all 0.3s ease;
697
+ overflow: hidden;
698
+ position: relative;
699
+ }
700
+
701
+ /* تنسيقات الوضع الليلي */
702
+ body.night-mode {
703
+ background: #1a202c;
704
+ color: rgb(11, 186, 131);
705
+ }
706
+
707
+ /* تأثير خلفية ديناميكي */
708
+ .background-effect {
709
+ position: absolute;
710
+ top: 0;
711
+ left: 0;
712
+ width: 100%;
713
+ height: 100%;
714
+ z-index: -1;
715
+ opacity: 0.1;
716
+ background: radial-gradient(circle at 20% 50%, rgba(11, 186, 131, 0.4) 0%, transparent 50%),
717
+ radial-gradient(circle at 80% 80%, rgba(11, 186, 131, 0.3) 0%, transparent 40%);
718
+ animation: backgroundMove 20s infinite alternate ease-in-out;
719
+ }
720
+
721
+ @keyframes backgroundMove {
722
+ 0% { transform: scale(1) rotate(0deg); }
723
+ 100% { transform: scale(1.2) rotate(5deg); }
724
+ }
725
+
726
+ .night-mode .background-effect {
727
+ background: radial-gradient(circle at 20% 50%, rgba(11, 186, 131, 0.2) 0%, transparent 50%),
728
+ radial-gradient(circle at 80% 80%, rgba(11, 186, 131, 0.15) 0%, transparent 40%);
729
+ }
730
+
731
+ .circle-outer {
732
+ width:220px; height:220px;
733
+ border-radius:50%;
734
+ background: rgba(11, 186, 131, 0.15);
735
+ display:flex; justify-content:center; align-items:center;
736
+ cursor:pointer; transition: all 0.3s ease;
737
+ box-shadow: 0 15px 30px rgba(0,0,0,0.1);
738
+ position: relative;
739
+ overflow:hidden;
740
+ animation: subtlePulse 3s infinite ease-in-out;
741
+ z-index: 10;
742
+ }
743
+
744
+ @keyframes subtlePulse {
745
+ 0% { transform: scale(1); box-shadow: 0 15px 30px rgba(0,0,0,0.1); }
746
+ 50% { transform: scale(1.02); box-shadow: 0 20px 40px rgba(0,0,0,0.15); }
747
+ 100% { transform: scale(1); box-shadow: 0 15px 30px rgba(0,0,0,0.1); }
748
+ }
749
+
750
+ .night-mode .circle-outer {
751
+ background: rgba(11, 186, 131, 0.15);
752
+ box-shadow: 0 15px 30px rgba(0,0,0,0.3);
753
+ animation: subtlePulseNight 3s infinite ease-in-out;
754
+ }
755
+
756
+ @keyframes subtlePulseNight {
757
+ 0% { transform: scale(1); box-shadow: 0 15px 30px rgba(0,0,0,0.3); }
758
+ 50% { transform: scale(1.02); box-shadow: 0 20px 40px rgba(0,0,0,0.4); }
759
+ 100% { transform: scale(1); box-shadow: 0 15px 30px rgba(0,0,0,0.3); }
760
+ }
761
+
762
+ .circle-middle {
763
+ width:180px; height:180px;
764
+ border-radius:50%;
765
+ background: rgba(11, 186, 131, 0.25);
766
+ display:flex; justify-content:center; align-items:center;
767
+ transition: all 0.3s ease;
768
+ animation: middlePulse 4s infinite ease-in-out;
769
+ }
770
+
771
+ @keyframes middlePulse {
772
+ 0% { transform: scale(1); background: rgba(11, 186, 131, 0.25); }
773
+ 50% { transform: scale(1.03); background: rgba(11, 186, 131, 0.3); }
774
+ 100% { transform: scale(1); background: rgba(11, 186, 131, 0.25); }
775
+ }
776
+
777
+ .night-mode .circle-middle {
778
+ background: rgba(11, 186, 131, 0.25);
779
+ animation: middlePulseNight 4s infinite ease-in-out;
780
+ }
781
+
782
+ @keyframes middlePulseNight {
783
+ 0% { transform: scale(1); background: rgba(11, 186, 131, 0.25); }
784
+ 50% { transform: scale(1.03); background: rgba(11, 186, 131, 0.3); }
785
+ 100% { transform: scale(1); background: rgba(11, 186, 131, 0.25); }
786
+ }
787
+
788
+ .circle-inner {
789
+ width:140px; height:140px;
790
+ border-radius:50%;
791
+ background:white;
792
+ display:flex; justify-content:center; align-items:center;
793
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
794
+ transition: all 0.3s ease;
795
+ animation: innerGlow 5s infinite alternate;
796
+ }
797
+
798
+ @keyframes innerGlow {
799
+ 0% { box-shadow: 0 5px 15px rgba(0,0,0,0.1); }
800
+ 100% { box-shadow: 0 5px 25px rgba(11, 186, 131, 0.3); }
801
+ }
802
+
803
+ .night-mode .circle-inner {
804
+ background: #2d3748;
805
+ box-shadow: 0 5px 15px rgba(0,0,0,0.3);
806
+ animation: innerGlowNight 5s infinite alternate;
807
+ }
808
+
809
+ @keyframes innerGlowNight {
810
+ 0% { box-shadow: 0 5px 15px rgba(0,0,0,0.3); }
811
+ 100% { box-shadow: 0 5px 25px rgba(11, 186, 131, 0.4); }
812
+ }
813
+
814
+ .mic-svg {
815
+ width:60px; height:60px;
816
+ fill: rgb(11, 186, 131);
817
+ transition: all 0.3s ease;
818
+ animation: iconFloat 6s infinite ease-in-out;
819
+ }
820
+
821
+ @keyframes iconFloat {
822
+ 0% { transform: translateY(0) scale(1); }
823
+ 50% { transform: translateY(-5px) scale(1.05); }
824
+ 100% { transform: translateY(0) scale(1); }
825
+ }
826
+
827
+ .night-mode .mic-svg {
828
+ fill: rgb(11, 186, 131);
829
+ }
830
+
831
+ /* أثناء الاستماع */
832
+ .circle-outer.listening {
833
+ animation: rotatePulse 1.5s infinite linear, colorShift 3s infinite alternate;
834
+ }
835
+ @keyframes rotatePulse {
836
+ 0% { transform: rotate(0deg) scale(1); }
837
+ 25% { transform: rotate(5deg) scale(1.05); }
838
+ 50% { transform: rotate(0deg) scale(1.1); }
839
+ 75% { transform: rotate(-5deg) scale(1.05); }
840
+ 100% { transform: rotate(0deg) scale(1); }
841
+ }
842
+ @keyframes colorShift {
843
+ 0% { background: rgba(11, 186, 131, 0.15); }
844
+ 25% { background: rgba(11, 186, 131, 0.25); }
845
+ 50% { background: rgba(11, 186, 131, 0.35); }
846
+ 75% { background: rgba(11, 186, 131, 0.25); }
847
+ 100% { background: rgba(11, 186, 131, 0.15); }
848
+ }
849
+
850
+ .night-mode .circle-outer.listening {
851
+ animation: rotatePulse 1.5s infinite linear, colorShiftNight 3s infinite alternate;
852
+ }
853
+ @keyframes colorShiftNight {
854
+ 0% { background: rgba(11, 186, 131, 0.15); }
855
+ 25% { background: rgba(11, 186, 131, 0.25); }
856
+ 50% { background: rgba(11, 186, 131, 0.35); }
857
+ 75% { background: rgba(11, 186, 131, 0.25); }
858
+ 100% { background: rgba(11, 186, 131, 0.15); }
859
+ }
860
+
861
+ /* حركة الميكروفون أثناء الرد */
862
+ .circle-outer.speaking .mic-svg {
863
+ animation: speakIcon 0.8s infinite alternate, glowMic 1.2s infinite alternate;
864
+ }
865
+ @keyframes speakIcon {
866
+ 0% { transform: translateY(0) scale(1); }
867
+ 25% { transform: translateY(-8px) scale(1.1); }
868
+ 50% { transform: translateY(0) scale(1); }
869
+ 75% { transform: translateY(8px) scale(1.1); }
870
+ 100% { transform: translateY(0) scale(1); }
871
+ }
872
+ @keyframes glowMic {
873
+ 0% { filter: drop-shadow(0 0 0 rgba(11, 186, 131, 0.4)); }
874
+ 50% { filter: drop-shadow(0 0 15px rgba(11, 186, 131, 0.8)); }
875
+ 100% { filter: drop-shadow(0 0 0 rgba(11, 186, 131, 0.4)); }
876
+ }
877
+
878
+ .night-mode .circle-outer.speaking .mic-svg {
879
+ animation: speakIcon 0.8s infinite alternate, glowMicNight 1.2s infinite alternate;
880
+ }
881
+ @keyframes glowMicNight {
882
+ 0% { filter: drop-shadow(0 0 0 rgba(11, 186, 131, 0.4)); }
883
+ 50% { filter: drop-shadow(0 0 15px rgba(11, 186, 131, 0.8)); }
884
+ 100% { filter: drop-shadow(0 0 0 rgba(11, 186, 131, 0.4)); }
885
+ }
886
+
887
+ /* موجات نابضة حول الدائرة - دائمة الآن */
888
+ .pulse-wave {
889
+ position:absolute;
890
+ border:2px solid rgba(11, 186, 131, 0.5);
891
+ border-radius:50%;
892
+ width:220px;
893
+ height:220px;
894
+ top:0; left:0;
895
+ animation: pulse 3s infinite ease-in-out;
896
+ opacity: 0.7;
897
+ }
898
+
899
+ .pulse-wave:nth-child(2) {
900
+ animation-delay: 1s;
901
+ }
902
+
903
+ .pulse-wave:nth-child(3) {
904
+ animation-delay: 2s;
905
+ }
906
+
907
+ @keyframes pulse {
908
+ 0% { transform: scale(1); opacity:0.5; }
909
+ 50% { transform: scale(1.3); opacity:0.2; }
910
+ 100% { transform: scale(1.6); opacity:0; }
911
+ }
912
+
913
+ .night-mode .pulse-wave {
914
+ border:2px solid rgba(11, 186, 131, 0.5);
915
+ }
916
+
917
+ /* أشرطة الصوت */
918
+ .wave { display:flex; justify-content:center; align-items:flex-end; height:50px; margin-top:15px; }
919
+ .wave span {
920
+ display:inline-block;
921
+ width:5px; height:25px;
922
+ background: rgb(11, 186, 131);
923
+ margin:0 4px; border-radius:3px;
924
+ animation: wave 1.2s infinite ease-in-out;
925
+ }
926
+ .wave span:nth-child(2){animation-delay:0.1s;}
927
+ .wave span:nth-child(3){animation-delay:0.2s;}
928
+ .wave span:nth-child(4){animation-delay:0.3s;}
929
+ .wave span:nth-child(5){animation-delay:0.4s;}
930
+ @keyframes wave {
931
+ 0%,40%,100% { transform: scaleY(0.6); }
932
+ 20% { transform: scaleY(1.5); }
933
+ }
934
+
935
+ .night-mode .wave span {
936
+ background: rgb(11, 186, 131);
937
+ }
938
+
939
+ .hidden { display:none; }
940
+
941
+ .status {
942
+ text-align:center;
943
+ margin-top:20px;
944
+ font-size:18px;
945
+ color:#4a5568;
946
+ transition: all 0.3s ease;
947
+ min-height: 30px;
948
+ padding: 0 10px;
949
+ }
950
+
951
+ .night-mode .status {
952
+ color: #a0aec0;
953
+ }
954
+
955
+ /* زر تبديل الوضع */
956
+ .theme-toggle {
957
+ position: absolute;
958
+ top: 20px;
959
+ right: 20px;
960
+ background: rgba(11, 186, 131, 0.1);
961
+ border: none;
962
+ border-radius: 50%;
963
+ width: 50px;
964
+ height: 50px;
965
+ cursor: pointer;
966
+ font-size: 24px;
967
+ display: flex;
968
+ justify-content: center;
969
+ align-items: center;
970
+ transition: all 0.3s ease;
971
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
972
+ animation: buttonPulse 4s infinite ease-in-out;
973
+ z-index: 100;
974
+ }
975
+
976
+ @keyframes buttonPulse {
977
+ 0% { transform: scale(1); box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
978
+ 50% { transform: scale(1.05); box-shadow: 0 4px 15px rgba(0,0,0,0.2); }
979
+ 100% { transform: scale(1); box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
980
+ }
981
+
982
+ .night-mode .theme-toggle {
983
+ background: rgba(11, 186, 131, 0.1);
984
+ box-shadow: 0 2px 10px rgba(0,0,0,0.3);
985
+ }
986
+
987
+ .theme-toggle:hover {
988
+ transform: scale(1.1);
989
+ animation: none;
990
+ }
991
+
992
+ /* رسالة حالة المتصفح */
993
+ .browser-warning {
994
+ position: fixed;
995
+ bottom: 20px;
996
+ left: 50%;
997
+ transform: translateX(-50%);
998
+ background: #ff4757;
999
+ color: white;
1000
+ padding: 10px 20px;
1001
+ border-radius: 5px;
1002
+ font-size: 14px;
1003
+ display: none;
1004
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
1005
+ z-index: 1000;
1006
+ text-align: center;
1007
+ max-width: 90%;
1008
+ }
1009
+
1010
+ /* تأثيرات النص المتحركة */
1011
+ @keyframes textPulse {
1012
+ 0% { opacity: 0.8; }
1013
+ 50% { opacity: 1; }
1014
+ 100% { opacity: 0.8; }
1015
+ }
1016
+
1017
+ .listening-text {
1018
+ animation: textPulse 1.5s infinite;
1019
+ font-weight: bold;
1020
+ }
1021
+
1022
+ /* تخصيص شريط التمرير */
1023
+ ::-webkit-scrollbar {
1024
+ width: 8px;
1025
+ }
1026
+
1027
+ ::-webkit-scrollbar-track {
1028
+ background: rgba(11, 186, 131, 0.1);
1029
+ border-radius: 10px;
1030
+ }
1031
+
1032
+ ::-webkit-scrollbar-thumb {
1033
+ background: rgba(11, 186, 131, 0.3);
1034
+ border-radius: 10px;
1035
+ }
1036
+
1037
+ ::-webkit-scrollbar-thumb:hover {
1038
+ background: rgba(11, 186, 131, 0.5);
1039
+ }
1040
+
1041
+ .night-mode ::-webkit-scrollbar-track {
1042
+ background: rgba(11, 186, 131, 0.05);
1043
+ }
1044
+
1045
+ .night-mode ::-webkit-scrollbar-thumb {
1046
+ background: rgba(11, 186, 131, 0.2);
1047
+ }
1048
+
1049
+ .night-mode ::-webkit-scrollbar-thumb:hover {
1050
+ background: rgba(11, 186, 131, 0.4);
1051
+ }
1052
+ </style>
1053
+ </head>
1054
+ <body>
1055
+
1056
+ <!-- تأثير الخلفية الديناميكي -->
1057
+ <div class="background-effect"></div>
1058
+
1059
+ <!-- زر تبديل الوضع -->
1060
+ <button class="theme-toggle" id="themeToggle">🌙</button>
1061
+
1062
+ <div class="circle-outer" id="micCircle">
1063
+ <div class="pulse-wave"></div>
1064
+ <div class="pulse-wave"></div>
1065
+ <div class="pulse-wave"></div>
1066
+ <div class="circle-middle">
1067
+ <div class="circle-inner">
1068
+ <svg class="mic-svg" focusable="false" viewBox="0 0 24 24" aria-hidden="true" role="img">
1069
+ <title>API</title>
1070
+ <path d="M0 0h24v24H0z" fill="none"></path>
1071
+ <path d="M6 13c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-8c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm-3 .5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM6 5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm15 5.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM14 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-3.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm-11 10c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm7 7c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm0-17c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM10 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0 5.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm8 .5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-8c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm3 8.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM14 17c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm-4-12c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0 8.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm4-4.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-4c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"></path>
1072
+ </svg>
1073
+ </div>
1074
+ </div>
1075
+ </div>
1076
+
1077
+ <div class="status" id="status">انقر على الدائرة للتحدث</div>
1078
+ <div class="wave hidden" id="wave">
1079
+ <span></span><span></span><span></span><span></span><span></span>
1080
+ </div>
1081
+
1082
+ <div class="browser-warning" id="browserWarning">
1083
+ عذرًا، متصفحك الحالي لا يدعم خاصية التعرف على الصوت. يرجى استخدام Chrome أو Edge للحصول على أفضل تجربة.
1084
+ </div>
1085
+
1086
+ <script>
1087
+
1088
+ const micCircle = document.getElementById('micCircle');
1089
+ const status = document.getElementById('status');
1090
+ const wave = document.getElementById('wave');
1091
+ const themeToggle = document.getElementById('themeToggle');
1092
+ const browserWarning = document.getElementById('browserWarning');
1093
+
1094
+ // التحقق من دعم المتصفح للوضع الليلي
1095
+ let isNightMode = localStorage.getItem('nightMode') === 'true';
1096
+
1097
+ // تطبيق الوضع الليلي عند التحميل
1098
+ if (isNightMode) {
1099
+ document.body.classList.add('night-mode');
1100
+ themeToggle.textContent = '☀️';
1101
+ }
1102
+
1103
+ // تبديل الوضع الليلي/النهاري
1104
+ themeToggle.addEventListener('click', function() {
1105
+ isNightMode = !isNightMode;
1106
+ document.body.classList.toggle('night-mode');
1107
+
1108
+ if (isNightMode) {
1109
+ themeToggle.textContent = '☀️';
1110
+ localStorage.setItem('nightMode', 'true');
1111
+ } else {
1112
+ themeToggle.textContent = '🌙';
1113
+ localStorage.setItem('nightMode', 'false');
1114
+ }
1115
+ });
1116
+
1117
+
1118
+ if(!('webkitSpeechRecognition' in window || 'SpeechRecognition' in window)){
1119
+ status.textContent = "متصفحك لا يدعم التعرف على الصوت";
1120
+ browserWarning.style.display = 'block';
1121
+ } else {
1122
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
1123
+ const recognition = new SpeechRecognition();
1124
+ recognition.lang = 'ar-SA';
1125
+ recognition.continuous = false;
1126
+ recognition.interimResults = false;
1127
+
1128
+ const speech = new SpeechSynthesisUtterance();
1129
+ speech.lang = 'ar-SA';
1130
+ speech.rate = 1;
1131
+ speech.pitch = 1;
1132
+ speech.volume = 1;
1133
+
1134
+ let isListening = false;
1135
+
1136
+ micCircle.addEventListener('click', function(){
1137
+ if(isListening){
1138
+
1139
+ recognition.stop();
1140
+ return;
1141
+ }
1142
+ try {
1143
+
1144
+ recognition.start();
1145
+ status.textContent = "أستمع إليك...";
1146
+ status.classList.add('listening-text');
1147
+ micCircle.classList.add('listening');
1148
+ wave.classList.remove('hidden');
1149
+ isListening = true;
1150
+ } catch(e){
1151
+
1152
+ status.textContent = "حدث خطأ";
1153
+ console.error(e);
1154
+
1155
+ isListening = false;
1156
+ }
1157
+ });
1158
+
1159
+ recognition.onresult = async function(event){
1160
+ const transcript = event.results[0][0].transcript;
1161
+ status.textContent = `تم الاستماع إلى: "${transcript}"`;
1162
+ status.classList.remove('listening-text');
1163
+
1164
+ // إزالة الاستماع وإضافة حركة الرد
1165
+ micCircle.classList.remove('listening');
1166
+ micCircle.classList.add('speaking');
1167
+ isListening = false;
1168
+
1169
+ let scale = 1;
1170
+ let direction = 1;
1171
+ let speakingAnim = setInterval(()=>{
1172
+ scale += 0.01 * direction;
1173
+ if(scale > 1.1) direction = -1;
1174
+ if(scale < 0.9) direction = 1;
1175
+ micCircle.style.transform = `scale(${scale})`;
1176
+ }, 16);
1177
+
1178
+ let reply = await generateReply(transcript);
1179
+ reply = removeSymbols(reply);
1180
+
1181
+ speakResponse(reply, speakingAnim);
1182
+ }
1183
+
1184
+ recognition.onend = function(){
1185
+ if(!micCircle.classList.contains('speaking')){
1186
+ micCircle.classList.remove('listening');
1187
+ status.classList.remove('listening-text');
1188
+ wave.classList.add('hidden');
1189
+ isListening=false;
1190
+ status.textContent = "انقر على الدائرة للتحدث مرة أخرى";
1191
+ }
1192
+ }
1193
+
1194
+ recognition.onerror = function(event) {
1195
+ console.error('خطأ في التعرف على الصوت:', event.error);
1196
+ status.textContent = "حدث خطأ: " + event.error;
1197
+ status.classList.remove('listening-text');
1198
+ micCircle.classList.remove('listening');
1199
+ wave.classList.add('hidden');
1200
+ isListening = false;
1201
+ }
1202
+
1203
+ function speakResponse(text, speakingAnim){
1204
+ speech.text = text;
1205
+ window.speechSynthesis.speak(speech);
1206
+
1207
+ speech.onstart = () => {
1208
+ status.textContent = "جاري الرد...";
1209
+ };
1210
+
1211
+ speech.onend = () => {
1212
+ clearInterval(speakingAnim);
1213
+ micCircle.classList.remove('speaking');
1214
+ micCircle.style.transform = "scale(1)";
1215
+ wave.classList.add('hidden');
1216
+ status.textContent = "انقر على الدائرة للتحدث مرة أخرى";
1217
+ };
1218
+
1219
+ speech.onerror = (event) => {
1220
+ console.error('خطأ في الصوت:', event);
1221
+ status.textContent = "حدث خطأ في الصوت";
1222
+ clearInterval(speakingAnim);
1223
+ micCircle.classList.remove('speaking');
1224
+ micCircle.style.transform = "scale(1)";
1225
+ wave.classList.add('hidden');
1226
+ isListening = false;
1227
+ };
1228
+ }
1229
+
1230
+
1231
+
1232
+ function removeSymbols(text)
1233
+ {
1234
+
1235
+ return text.replace(/[\p{Emoji_Presentation}\p{Extended_Pictographic}\p{Symbol}\p{Emoji}\u2600-\u27BF]+/gu, "");
1236
+ }
1237
+
1238
+ async function askAzureOpenAI(prompt) {
1239
+ const endpoint = "https://lahja-dev-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2023-03-15-preview";
1240
+
1241
+ try {
1242
+ const response = await fetch(endpoint, {
1243
+ method: "POST",
1244
+ headers: {
1245
+ "Content-Type": "application/json",
1246
+ "api-key":"4AwsIf87cyBIgaJVsy0phWUQdZFcbrJxpQBDQNzL4xjcP2MFzrrYJQQJ99BIACHYHv6XJ3w3AAAAACOGYrzM"
1247
+ },
1248
+ body: JSON.stringify({
1249
+ messages: [
1250
+ { role: "system", content: "إنت تمثل شركة أسس الذكاء الاصطناعي وترد باللهجة السعودية." },
1251
+ { role: "user", content: prompt }
1252
+ ]
1253
+ }),
1254
+ });
1255
+
1256
+ const data = await response.json();
1257
+ return data.choices[0].message.content;
1258
+
1259
+ } catch (err) {
1260
+ console.error("خطأ في الاتصال بـ Azure OpenAI:", err);
1261
+ return "أعتذر، حدث خطأ أثناء معالجة طلبك.";
1262
+ }
1263
+ }
1264
+
1265
+ async function generateReply(userInput) {
1266
+ return await askAzureOpenAI(userInput);
1267
+ }
1268
+ }
1269
+ </script>
1270
+
1271
+
1272
+ </body>
1273
+ </html> عتماد الاصوات الذي في الواجهه في الاعدادات الى الواجهتين استخدام داله البحث التي تعتمد على الموديل الى يكون واجهتين مع اظافه مشغل صوت الشاش واظافه اصوات النظام الواجهتين
1274
+ بتصميم متقن حيث يمكن عرض اصوات الهجه واصوات النظام
1275
+ تصميم متقن بحيث كل واجهه تظهر بصفحه خاصه بها مع عرض اصوات النظام واصوات الهجه
1276
+ تصميم متقن بحيث كل واجهه تظهر بصفحه خاصه بها مع عرض اصوات النظام واصوات الهجه
1277
+ تصميم متقن بحيث كل واجهه تظهر بصفحه خاصه بها مع عرض اظافه واجهه speech 2speech واظافهىمشغل صوتي لكل رساله في تكيست اصوات النظام واصوات الهجه<!DOCTYPE html>
1278
+ <!DOCTYPE html>
1279
+ <html lang="ar" dir="rtl">
1280
+ <head>
1281
+ <meta charset="UTF-8">
1282
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
1283
+ <title>LAHJA AI - مساعد صوتي ذكي</title>
1284
+ <script src="https://cdn.tailwindcss.com"></script>
1285
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
1286
+ <style>
1287
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700&display=swap');
1288
+
1289
+ body {
1290
+ font-family: 'Tajawal', sans-serif;
1291
+ background: linear-gradient(135deg, #0f172a, #1e293b);
1292
+ color: #fff;
1293
+ min-height: 100vh;
1294
+ }
1295
+
1296
+ .chat-container {
1297
+ background: rgba(15, 23, 42, 0.8);
1298
+ backdrop-filter: blur(10px);
1299
+ border-radius: 1.5rem;
1300
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
1301
+ border: 1px solid rgba(255, 255, 255, 0.1);
1302
+ }
1303
+
1304
+ .message-bubble {
1305
+ max-width: 85%;
1306
+ padding: 0.75rem 1.25rem;
1307
+ border-radius: 1.25rem;
1308
+ margin-bottom: 0.75rem;
1309
+ position: relative;
1310
+ animation: fadeIn 0.3s ease-out;
1311
+ line-height: 1.6;
1312
+ }
1313
+
1314
+ .user-message {
1315
+ background: linear-gradient(135deg, #7c3aed, #6d28d9);
1316
+ align-self: flex-end;
1317
+ border-bottom-right-radius: 0.5rem;
1318
+ color: white;
1319
+ }
1320
+
1321
+ .ai-message {
1322
+ background: rgba(255, 255, 255, 0.08);
1323
+ align-self: flex-start;
1324
+ border-bottom-left-radius: 0.5rem;
1325
+ border: 1px solid rgba(255, 255, 255, 0.05);
1326
+ }
1327
+
1328
+ .pulse {
1329
+ animation: pulse 1.5s infinite;
1330
+ }
1331
+
1332
+ @keyframes pulse {
1333
+ 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.7); }
1334
+ 70% { transform: scale(1.05); box-shadow: 0 0 0 10px rgba(124, 58, 237, 0); }
1335
+ 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(124, 58, 237, 0); }
1336
+ }
1337
+
1338
+ @keyframes fadeIn {
1339
+ from { opacity: 0; transform: translateY(10px); }
1340
+ to { opacity: 1; transform: translateY(0); }
1341
+ }
1342
+
1343
+ .waveform {
1344
+ display: flex;
1345
+ align-items: center;
1346
+ height: 2.5rem;
1347
+ gap: 0.25rem;
1348
+ justify-content: flex-end;
1349
+ }
1350
+
1351
+ .waveform-bar {
1352
+ background: rgba(255, 255, 255, 0.7);
1353
+ width: 0.25rem;
1354
+ border-radius: 0.25rem;
1355
+ animation: equalize 1.5s infinite ease-in-out;
1356
+ }
1357
+
1358
+ @keyframes equalize {
1359
+ 0%, 100% { height: 0.5rem; }
1360
+ 50% { height: 1.5rem; }
1361
+ }
1362
+
1363
+ .waveform-bar:nth-child(1) { animation-delay: -0.9s; }
1364
+ .waveform-bar:nth-child(2) { animation-delay: -0.7s; }
1365
+ .waveform-bar:nth-child(3) { animation-delay: -0.5s; }
1366
+ .waveform-bar:nth-child(4) { animation-delay: -0.3s; }
1367
+ .waveform-bar:nth-child(5) { animation-delay: -0.1s; }
1368
+
1369
+ .typing-indicator {
1370
+ display: flex;
1371
+ align-items: center;
1372
+ gap: 0.5rem;
1373
+ padding: 0.5rem 0;
1374
+ }
1375
+
1376
+ .typing-dot {
1377
+ width: 0.5rem;
1378
+ height: 0.5rem;
1379
+ background: rgba(255, 255, 255, 0.7);
1380
+ border-radius: 50%;
1381
+ animation: typingAnimation 1.4s infinite ease-in-out;
1382
+ }
1383
+
1384
+ .typing-dot:nth-child(1) { animation-delay: 0s; }
1385
+ .typing-dot:nth-child(2) { animation-delay: 0.2s; }
1386
+ .typing-dot:nth-child(3) { animation-delay: 0.4s; }
1387
+
1388
+ @keyframes typingAnimation {
1389
+ 0%, 60%, 100% { transform: translateY(0); }
1390
+ 30% { transform: translateY(-0.25rem); }
1391
+ }
1392
+
1393
+ .scrollbar-hide::-webkit-scrollbar {
1394
+ display: none;
1395
+ }
1396
+
1397
+ .scrollbar-hide {
1398
+ -ms-overflow-style: none;
1399
+ scrollbar-width: none;
1400
+ }
1401
+
1402
+ .modal-overlay {
1403
+ background: rgba(0, 0, 0, 0.7);
1404
+ }
1405
+
1406
+ .modal-content {
1407
+ animation: modalFadeIn 0.3s ease-out;
1408
+ }
1409
+
1410
+ @keyframes modalFadeIn {
1411
+ from { opacity: 0; transform: translateY(20px); }
1412
+ to { opacity: 1; transform: translateY(0); }
1413
+ }
1414
+
1415
+ .voice-btn {
1416
+ transition: all 0.3s ease;
1417
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
1418
+ }
1419
+
1420
+ .voice-btn:hover {
1421
+ transform: translateY(-2px);
1422
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
1423
+ }
1424
+
1425
+ .voice-btn:active {
1426
+ transform: translateY(0);
1427
+ }
1428
+
1429
+ .language-badge {
1430
+ font-size: 0.65rem;
1431
+ padding: 0.15rem 0.5rem;
1432
+ border-radius: 9999px;
1433
+ background: rgba(255, 255, 255, 0.1);
1434
+ border: 1px solid rgba(255, 255, 255, 0.2);
1435
+ }
1436
+
1437
+ /* RTL specific styles */
1438
+ [dir="rtl"] .message-bubble {
1439
+ text-align: right;
1440
+ }
1441
+
1442
+ [dir="rtl"] .ai-message {
1443
+ margin-right: 1rem;
1444
+ }
1445
+
1446
+ [dir="rtl"] .user-message {
1447
+ margin-left: 1rem;
1448
+ }
1449
+
1450
+ /* Dark mode toggle animation */
1451
+ .toggle-circle {
1452
+ transition: all 0.3s ease;
1453
+ }
1454
+
1455
+ input:checked ~ .toggle-circle {
1456
+ transform: translateX(1.25rem);
1457
+ }
1458
+ </style>
1459
+ </head>
1460
+ <body class="flex items-center justify-center p-4 md:p-6">
1461
+ <div class="chat-container w-full max-w-2xl h-[85vh] md:h-[80vh] flex flex-col">
1462
+ <!-- Header -->
1463
+ <div class="p-4 border-b border-slate-700 flex items-center justify-between">
1464
+ <div class="flex items-center gap-3">
1465
+ <div class="w-10 h-10 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center shadow-md">
1466
+ <i class="fas fa-robot text-white text-lg"></i>
1467
+ </div>
1468
+ <div>
1469
+ <h2 class="font-bold text-lg">مساعد لهــجة الصوتي</h2>
1470
+ <div class="flex items-center gap-2">
1471
+ <span class="text-xs text-slate-300">مدعوم بالذكاء الاصطناعي</span>
1472
+ <span class="language-badge">العربية</span>
1473
+ </div>
1474
+ </div>
1475
+ </div>
1476
+ <div class="flex items-center gap-2">
1477
+ <button id="dark-mode-toggle" class="p-2 rounded-full hover:bg-slate-700 transition">
1478
+ <i class="fas fa-moon text-slate-300"></i>
1479
+ </button>
1480
+ <button id="settings-btn" class="p-2 rounded-full hover:bg-slate-700 transition">
1481
+ <i class="fas fa-cog text-slate-300"></i>
1482
+ </button>
1483
+ </div>
1484
+ </div>
1485
+
1486
+ <!-- Chat Messages -->
1487
+ <div id="chat-messages" class="flex-1 p-4 overflow-y-auto scrollbar-hide flex flex-col">
1488
+ <!-- Initial welcome message -->
1489
+ <div class="message-bubble ai-message">
1490
+ <p>مرحباً بك! 👋 أنا مساعدك الصوتي الذكي "لُحْجَة". يمكنك التحدث معي بالضغط على زر الميكروفون أدناه.</p>
1491
+ </div>
1492
+ <div class="message-bubble ai-message">
1493
+ <p>أنا أستطيع الإجابة على أسئلتك، تقديم المعلومات، وحتى إجراء محادثات ذكية معك. جرب أن تسألني عن أي شيء!</p>
1494
+ </div>
1495
+ </div>
1496
+
1497
+ <!-- Input Area -->
1498
+ <div class="p-4 border-t border-slate-700">
1499
+ <div class="flex items-center gap-2">
1500
+ <button id="voice-btn" class="voice-btn w-14 h-14 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center text-white hover:from-purple-700 hover:to-blue-600 transition-all shadow-lg">
1501
+ <i class="fas fa-microphone text-xl"></i>
1502
+ </button>
1503
+ <div class="flex-1 bg-slate-700 rounded-full px-4 py-2 flex items-center justify-between">
1504
+ <p id="voice-status" class="text-sm text-slate-300">اضغط على الميكروفون للتحدث</p>
1505
+ <div id="waveform" class="waveform hidden">
1506
+ <div class="waveform-bar"></div>
1507
+ <div class="waveform-bar"></div>
1508
+ <div class="waveform-bar"></div>
1509
+ <div class="waveform-bar"></div>
1510
+ <div class="waveform-bar"></div>
1511
+ </div>
1512
+ </div>
1513
+ <button id="keyboard-btn" class="w-12 h-12 rounded-full bg-slate-700 flex items-center justify-center text-slate-300 hover:bg-slate-600 transition">
1514
+ <i class="fas fa-keyboard text-lg"></i>
1515
+ </button>
1516
+ </div>
1517
+ </div>
1518
+ </div>
1519
+
1520
+ <!-- Settings Modal -->
1521
+ <div id="settings-modal" class="fixed inset-0 modal-overlay flex items-center justify-center hidden z-50 p-4">
1522
+ <div class="bg-slate-800 rounded-xl p-6 w-full max-w-md modal-content">
1523
+ <div class="flex justify-between items-center mb-4">
1524
+ <h3 class="text-xl font-bold">إعدادات المساعد</h3>
1525
+ <button id="close-settings" class="text-slate-400 hover:text-white p-1 rounded-full hover:bg-slate-700">
1526
+ <i class="fas fa-times text-lg"></i>
1527
+ </button>
1528
+ </div>
1529
+ <div class="space-y-4">
1530
+ <div>
1531
+ <label class="block text-sm font-medium mb-2">نموذج الصوت</label>
1532
+ <select id="voiceSelect" class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-2 text-white focus:ring-2 focus:ring-purple-500 focus:border-transparent">
1533
+ <option value="SA2">اللهجة النجدية - حصة v2</option>
1534
+ <option value="us">الإنجليزية الأمريكية</option>
1535
+ <option value="SA1">اللهجة النجدية - حصة v1</option>
1536
+ <option value="SA3">اللهجة النجدية - أحمد v1</option>
1537
+ </select>
1538
+ </div>
1539
+ <div>
1540
+ <label class="block text-sm font-medium mb-2">نوع الصوت</label>
1541
+ <select class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-2 text-white focus:ring-2 focus:ring-purple-500 focus:border-transparent">
1542
+ <option>ذكر</option>
1543
+ <option>أنثى</option>
1544
+ </select>
1545
+ </div>
1546
+ <div>
1547
+ <label class="block text-sm font-medium mb-2">سرعة الصوت</label>
1548
+ <div class="flex items-center gap-3">
1549
+ <span class="text-slate-300 text-sm">بطيء</span>
1550
+ <input type="range" min="0.5" max="2" step="0.1" value="1" class="w-full h-2 bg-slate-600 rounded-lg appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-purple-500">
1551
+ <span class="text-slate-300 text-sm">سريع</span>
1552
+ </div>
1553
+ </div>
1554
+ <div class="pt-2">
1555
+ <label class="inline-flex items-center cursor-pointer">
1556
+ <input type="checkbox" value="" class="sr-only peer" checked>
1557
+ <div class="relative w-11 h-6 bg-slate-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
1558
+ <span class="mr-3 text-sm font-medium text-slate-300">تفعيل الردود الصوتية</span>
1559
+ </label>
1560
+ </div>
1561
+ </div>
1562
+ <div class="mt-6 flex justify-end gap-3">
1563
+ <button id="cancel-settings" class="px-4 py-2 bg-slate-700 rounded-lg hover:bg-slate-600 transition">
1564
+ إلغاء
1565
+ </button>
1566
+ <button id="save-settings" class="px-4 py-2 bg-purple-600 rounded-lg hover:bg-purple-700 transition font-medium">
1567
+ حفظ الإعدادات
1568
+ </button>
1569
+ </div>
1570
+ </div>
1571
+ </div>
1572
+
1573
+ <!-- Keyboard Input Modal -->
1574
+ <div id="keyboard-modal" class="fixed inset-0 modal-overlay flex items-center justify-center hidden z-50 p-4">
1575
+ <div class="bg-slate-800 rounded-xl p-6 w-full max-w-md modal-content">
1576
+ <div class="flex justify-between items-center mb-4">
1577
+ <h3 class="text-xl font-bold">اكتب رسالتك</h3>
1578
+ <button id="close-keyboard" class="text-slate-400 hover:text-white p-1 rounded-full hover:bg-slate-700">
1579
+ <i class="fas fa-times text-lg"></i>
1580
+ </button>
1581
+ </div>
1582
+ <div class="mb-4">
1583
+ <textarea id="text-input" class="w-full bg-slate-700 border border-slate-600 rounded-lg px-4 py-3 text-white h-32 focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="اكتب رسالتك هنا..."></textarea>
1584
+ </div>
1585
+ <div class="flex justify-end gap-3">
1586
+ <button id="cancel-keyboard" class="px-4 py-2 bg-slate-700 rounded-lg hover:bg-slate-600 transition">
1587
+ إلغاء
1588
+ </button>
1589
+ <button id="send-text" class="px-4 py-2 bg-purple-600 rounded-lg hover:bg-purple-700 transition font-medium">
1590
+ إرسال
1591
+ </button>
1592
+ </div>
1593
+ </div>
1594
+ </div>
1595
+
1596
+ <script type="module">
1597
+ async function askAzureOpenAI(prompt)
1598
+ {
1599
+ const endpoint = "https://lahja-dev-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2023-03-15-preview";
1600
+
1601
+ try {
1602
+ const response = await fetch(endpoint, {
1603
+ method: "POST",
1604
+ headers: {
1605
+ "Content-Type": "application/json",
1606
+ "api-key": "4AwsIf87cyBIgaJVsy0phWUQdZFcbrJxpQBDQNzL4xjcP2MFzrrYJQQJ99BIACHYHv6XJ3w3AAAAACOGYrzM"
1607
+ },
1608
+ body: JSON.stringify({
1609
+ messages: [
1610
+ { role: "system", content: "إنت تمثل شركة أسس الذكاء الاصطناعي وترد باللهجة السعودية." },
1611
+ { role: "user", content: prompt }
1612
+ ]
1613
+ }),
1614
+ });
1615
+
1616
+ const data = await response.json();
1617
+ return data.choices[0].message.content;
1618
+
1619
+ } catch (err) {
1620
+ console.error("خطأ في الاتصال بـ Azure OpenAI:", err);
1621
+ return "أعتذر، حدث خطأ أثناء معالجة طلبك.";
1622
+ }
1623
+ }
1624
+ async function simulateChatGPTResponse(userInput)
1625
+ {
1626
+
1627
+ conversationHistory.push({ role: 'user', content: userInput });
1628
+
1629
+ const response = await askAzureOpenAI(userInput);
1630
+ setTimeout(() => {
1631
+ addAiMessage(response);
1632
+ conversationHistory.push({ role: 'assistant', content: response });
1633
+ }, 2000);
1634
+
1635
+
1636
+ }
1637
+
1638
+
1639
+ // دالة المحادثة
1640
+
1641
+ import {Client} from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
1642
+
1643
+ // DOM Elements
1644
+ const voiceBtn = document.getElementById('voice-btn');
1645
+ const voiceStatus = document.getElementById('voice-status');
1646
+ const waveform = document.getElementById('waveform');
1647
+ const chatMessages = document.getElementById('chat-messages');
1648
+ const settingsBtn = document.getElementById('settings-btn');
1649
+ const settingsModal = document.getElementById('settings-modal');
1650
+ const closeSettings = document.getElementById('close-settings');
1651
+ const saveSettings = document.getElementById('save-settings');
1652
+ const cancelSettings = document.getElementById('cancel-settings');
1653
+ const keyboardBtn = document.getElementById('keyboard-btn');
1654
+ const keyboardModal = document.getElementById('keyboard-modal');
1655
+ const closeKeyboard = document.getElementById('close-keyboard');
1656
+ const cancelKeyboard = document.getElementById('cancel-keyboard');
1657
+ const sendText = document.getElementById('send-text');
1658
+ const textInput = document.getElementById('text-input');
1659
+ const darkModeToggle = document.getElementById('dark-mode-toggle');
1660
+
1661
+
1662
+
1663
+ // Speech recognition setup
1664
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
1665
+ const recognition = new SpeechRecognition();
1666
+ recognition.lang = 'ar-SA';
1667
+ recognition.interimResults = false;
1668
+ recognition.maxAlternatives = 1;
1669
+
1670
+ // Speech synthesis setup
1671
+ const synth = window.speechSynthesis;
1672
+
1673
+ // VITS Model Integration
1674
+ const voiceModels = {
1675
+ 'us': 'wasmdashai/vits-en-v1',
1676
+ 'SA1': 'wasmdashai/vits-ar-sa-huba-v1',
1677
+ 'SA2': 'wasmdashai/vits-ar-sa-huba-v2',
1678
+ 'SA3': 'wasmdashai/vits-ar-sa-A',
1679
+ };
1680
+
1681
+ // State variables
1682
+ let isListening = false;
1683
+ let conversationHistory = [];
1684
+ let isDarkMode = true;
1685
+
1686
+ // Event Listeners
1687
+ voiceBtn.addEventListener('click', toggleVoiceRecognition);
1688
+ settingsBtn.addEventListener('click', () => settingsModal.classList.remove('hidden'));
1689
+ closeSettings.addEventListener('click', () => settingsModal.classList.add('hidden'));
1690
+ saveSettings.addEventListener('click', saveSettingsHandler);
1691
+ cancelSettings.addEventListener('click', () => settingsModal.classList.add('hidden'));
1692
+ keyboardBtn.addEventListener('click', () => keyboardModal.classList.remove('hidden'));
1693
+ closeKeyboard.addEventListener('click', () => keyboardModal.classList.add('hidden'));
1694
+ cancelKeyboard.addEventListener('click', () => keyboardModal.classList.add('hidden'));
1695
+ sendText.addEventListener('click', sendTextMessage);
1696
+ textInput.addEventListener('keypress', (e) => {
1697
+ if (e.key === 'Enter' && !e.shiftKey) {
1698
+ e.preventDefault();
1699
+ sendTextMessage();
1700
+ }
1701
+ });
1702
+ darkModeToggle.addEventListener('click', toggleDarkMode);
1703
+
1704
+ // Functions
1705
+ function toggleVoiceRecognition() {
1706
+ if (isListening) {
1707
+ stopListening();
1708
+ } else {
1709
+ startListening();
1710
+ }
1711
+ }
1712
+
1713
+ function startListening() {
1714
+ isListening = true;
1715
+ voiceBtn.classList.add('pulse');
1716
+ voiceBtn.innerHTML = '<i class="fas fa-stop text-xl"></i>';
1717
+ voiceStatus.textContent = 'أنا أستمع لك...';
1718
+ waveform.classList.remove('hidden');
1719
+
1720
+ try {
1721
+ recognition.start();
1722
+ } catch (e) {
1723
+ console.error('Error starting recognition:', e);
1724
+ stopListening();
1725
+ showSystemMessage('حدث خطأ في تشغيل الميكروفون. يرجى التحقق من الإذن.');
1726
+ }
1727
+ }
1728
+
1729
+ function stopListening() {
1730
+ isListening = false;
1731
+ voiceBtn.classList.remove('pulse');
1732
+ voiceBtn.innerHTML = '<i class="fas fa-microphone text-xl"></i>';
1733
+ voiceStatus.textContent = 'اضغط على الميكروفون للتحدث';
1734
+ waveform.classList.add('hidden');
1735
+
1736
+ try {
1737
+ recognition.stop();
1738
+ } catch (e) {
1739
+ console.error('Error stopping recognition:', e);
1740
+ }
1741
+ }
1742
+
1743
+ function saveSettingsHandler() {
1744
+ // In a real app, you would save these settings to localStorage or a backend
1745
+ settingsModal.classList.add('hidden');
1746
+ showSystemMessage('تم حفظ الإعدادات بنجاح');
1747
+ }
1748
+
1749
+ function showSystemMessage(text) {
1750
+ const messageDiv = document.createElement('div');
1751
+ messageDiv.className = 'text-center text-xs text-slate-400 my-2';
1752
+ messageDiv.textContent = text;
1753
+ chatMessages.appendChild(messageDiv);
1754
+ chatMessages.scrollTop = chatMessages.scrollHeight;
1755
+ }
1756
+
1757
+ function addUserMessage(text) {
1758
+ const messageDiv = document.createElement('div');
1759
+ messageDiv.className = 'message-bubble user-message';
1760
+ messageDiv.innerHTML = `<p>${text}</p>`;
1761
+ chatMessages.appendChild(messageDiv);
1762
+ chatMessages.scrollTop = chatMessages.scrollHeight;
1763
+ }
1764
+
1765
+ function addAiMessage(text) {
1766
+ const messageDiv = document.createElement('div');
1767
+ messageDiv.className = 'message-bubble ai-message';
1768
+
1769
+ // Add typing indicator temporarily
1770
+ const typingDiv = document.createElement('div');
1771
+ typingDiv.className = 'typing-indicator';
1772
+ typingDiv.innerHTML = `
1773
+ <div class="typing-dot"></div>
1774
+ <div class="typing-dot"></div>
1775
+ <div class="typing-dot"></div>
1776
+ `;
1777
+ messageDiv.appendChild(typingDiv);
1778
+ chatMessages.appendChild(messageDiv);
1779
+ chatMessages.scrollTop = chatMessages.scrollHeight;
1780
+
1781
+ // Simulate AI thinking delay
1782
+ setTimeout(() => {
1783
+ typingDiv.remove();
1784
+ messageDiv.innerHTML = `<p>${text}</p>`;
1785
+ speakResponse(text);
1786
+ }, 1500 + Math.random() * 1000); // Random delay between 1.5-2.5s for more natural feel
1787
+ }
1788
+
1789
+ async function speakResponse(text) {
1790
+ const voiceSelect = document.getElementById('voiceSelect');
1791
+ const voice = voiceSelect.value;
1792
+
1793
+ try {
1794
+ const client = await Client.connect("wasmdashai/DemoLahja");
1795
+ const result = await client.predict("/predict", {
1796
+ text: text,
1797
+ name_model: voiceModels[voice],
1798
+ speaking_rate: 1.0
1799
+ });
1800
+
1801
+ const audioUrl = result.data?.[0]?.url;
1802
+ if (audioUrl) {
1803
+ const audio = new Audio(audioUrl);
1804
+ audio.play();
1805
+ } else {
1806
+ fallbackTTS(text);
1807
+ }
1808
+ } catch (err) {
1809
+ console.error("VITS model error:", err);
1810
+ fallbackTTS(text);
1811
+ }
1812
+ }
1813
+
1814
+ function fallbackTTS(text) {
1815
+ if (synth.speaking) {
1816
+ synth.cancel();
1817
+ }
1818
+
1819
+ const utterance = new SpeechSynthesisUtterance(text);
1820
+ utterance.lang = voiceSelect.value === 'us' ? 'en-US' : 'ar-SA';
1821
+ utterance.rate = 1.0;
1822
+ synth.speak(utterance);
1823
+ }
1824
+
1825
+ function processUserInput(text) {
1826
+ if (!text.trim()) return;
1827
+
1828
+ addUserMessage(text);
1829
+ conversationHistory.push({ role: 'user', content: text });
1830
+
1831
+ // In a real app, you would send this to your backend which connects to ChatGPT API
1832
+ // For this demo, we'll simulate a response
1833
+ simulateChatGPTResponse(text);
1834
+ }
1835
+
1836
+ function simulateChatGPTResponseg(userInput) {
1837
+ // Enhanced responses with more natural Arabic
1838
+ const responses = {
1839
+ "مرحبا": "مرحباً بك! 🌸 كيف يمكنني مساعدتك اليوم؟",
1840
+ "السلام عليكم": "وعليكم السلام ورحمة الله وبركاته 🌹 كيف حالك اليوم؟",
1841
+ "كيف حالك": "الحمد لله بخير، شكراً لسؤالك! 😊 كيف يمكنني مساعدتك؟",
1842
+ "ما هو اسمك": "أنا مساعدك الذكي 'لُحْجَة'، سعيد بتواصلك معي!",
1843
+ "من صممك": "تم تطويري باستخدام أحدث تقنيات الذكاء الاصطناعي لخدمتك بشكل أفضل.",
1844
+ "ماذا تستطيع ان تفعل": "أستطيع مساعدتك في:\n- الإجابة على أسئلتك\n- تقديم المعلومات\n- إجراء محادثات ذكية\n- وغير ذلك الكثير! جرب أن تسألني 😊",
1845
+ "شكرا": "العفو! 🌺 دائماً سعيد بمساعدتك. هل هناك شيء آخر تحتاجه؟",
1846
+ "شكراً": "على الرحب والسعة! 💐 لا تتردد في سؤالي عن أي شيء آخر.",
1847
+ "وداعا": "إلى اللقاء! 👋 أراك لاحقاً بإذن الله.",
1848
+ "مع السلامة": "مع ال��لامة 🌷 لا تنسى أن تعود إذا احتجت إلى أي مساعدة.",
1849
+ "ما هو تاريخ اليوم": `تاريخ اليوم هو: ${new Date().toLocaleDateString("ar-EG", { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}`,
1850
+ "ما هو الوقت الان": `الوقت الآن هو: ${new Date().toLocaleTimeString("ar-EG", { hour: 'numeric', minute: 'numeric', second: 'numeric' })}`,
1851
+ "من اين انت": "أنا مساعد افتراضي موجود في كل مكان 🌍 حيثما تكون أنت!",
1852
+ "ماهي عاصمه السعوديه": "عاصمة المملكة العربية السعودية هي الرياض 🏙️، وهي مدينة جميلة ومزدهرة.",
1853
+ "ماهي عاصمه اليمن": "عاصمة اليمن هي صنعاء 🕌، إحدى أقدم المدن المأهولة في العالم.",
1854
+ "اعطني نصيحه": "✨ من أفضل النصائح التي يمكنني تقديمها:\n1- لا تؤجل عمل اليوم إلى الغد\n2- ابدأ بخطوات صغيرة نحو أهدافك الكبيرة\n3- حافظ على توازنك بين العمل والحياة الشخصية",
1855
+ "كيف اتعلم البرمجة": "لتعلم البرمجة:\n1- ابدأ بلغة سهلة مثل Python\n2- تدرب يومياً ولو قليلاً\n3- انضم لمجتمعات المبرمجين\n4- نفذ مشاريع صغيرة\n5- لا تخف من الأخطاء، فهي جزء من التعلم 💻",
1856
+ "ما هو الذكاء الاصطناعي": "الذكاء الاصطناعي هو مجال في علوم الكمبيوتر يهدف إلى جعل الآلات قادرة على أداء مهام تتطلب ذكاءً بشرياً مثل:\n- فهم اللغة\n- التعلم\n- حل المشكلات\n- اتخاذ القرارات",
1857
+ "هل يمكنك الغناء": "للأسف لا أستطيع الغناء جيداً ، لكني أستطيع مساعدتك في العثور على الأغاني أو توفير كلماتها!",
1858
+ "ما هو الطقس اليوم": "للحصول على معلومات دقيقة عن الطقس، أحتاج إلى معرفة موقعك الجغرافي. يمكنك ذكر المدينة وسأساعدك في ذلك ☀️🌧️",
1859
+ "ما هي لغة البرمجة الافضل": "لا توجد لغة برمجة 'أفضل' بشكل مطلق، ولكن:\n- للويب: JavaScript\n- للبيانات: Python\n- للأنظمة: C++\n- للأجهزة المحمولة: Swift/Kotlin\nالاختيار يعتمد على احتياجاتك! 💻"
1860
+ };
1861
+
1862
+ const defaultResponse = "أعتذر، لم أفهم سؤالك بالكامل. هل يمكنك إعادة صياغته بطريقة أخرى؟";
1863
+
1864
+ // Find the best matching response (case insensitive)
1865
+ const normalizedInput = userInput.trim().toLowerCase();
1866
+ let response = defaultResponse;
1867
+
1868
+ for (const [key, value] of Object.entries(responses)) {
1869
+ if (normalizedInput.includes(key.toLowerCase())) {
1870
+ response = value;
1871
+ break;
1872
+ }
1873
+ }
1874
+
1875
+ setTimeout(() => {
1876
+ addAiMessage(response);
1877
+ conversationHistory.push({ role: 'assistant', content: response });
1878
+ }, 2000);
1879
+ }
1880
+
1881
+
1882
+ function sendTextMessage() {
1883
+ const text = textInput.value.trim();
1884
+ if (text) {
1885
+ processUserInput(text);
1886
+ textInput.value = '';
1887
+ keyboardModal.classList.add('hidden');
1888
+ }
1889
+ }
1890
+
1891
+ function toggleDarkMode() {
1892
+ isDarkMode = !isDarkMode;
1893
+ if (isDarkMode) {
1894
+ document.body.classList.add('bg-gradient-to-br', 'from-slate-900', 'to-slate-800');
1895
+ darkModeToggle.innerHTML = '<i class="fas fa-moon text-slate-300"></i>';
1896
+ } else {
1897
+ document.body.classList.remove('bg-gradient-to-br', 'from-slate-900', 'to-slate-800');
1898
+ document.body.classList.add('bg-gradient-to-br', 'from-slate-100', 'to-slate-200');
1899
+ darkModeToggle.innerHTML = '<i class="fas fa-sun text-yellow-400"></i>';
1900
+ }
1901
+ }
1902
+
1903
+ // Recognition event handlers
1904
+ recognition.onresult = (event) => {
1905
+ const speechResult = event.results[0][0].transcript;
1906
+ processUserInput(speechResult);
1907
+ stopListening();
1908
+ };
1909
+
1910
+ recognition.onerror = (event) => {
1911
+ console.error('Speech recognition error', event.error);
1912
+ stopListening();
1913
+
1914
+ if (event.error === 'not-allowed') {
1915
+ showSystemMessage('يجب السماح باستخدام الميكروفون لتفع��ل هذه الميزة. يرجى التحقق من إعدادات المتصفح.');
1916
+ } else {
1917
+ showSystemMessage('حدث خطأ في التعرف على الصوت. يرجى المحاولة مرة أخرى لاحقاً.');
1918
+ }
1919
+ };
1920
+
1921
+ recognition.onend = () => {
1922
+ if (isListening) {
1923
+ // If we're still supposed to be listening, restart recognition
1924
+ setTimeout(() => {
1925
+ try {
1926
+ recognition.start();
1927
+ } catch (e) {
1928
+ console.error('Error restarting recognition:', e);
1929
+ stopListening();
1930
+ }
1931
+ }, 500);
1932
+ }
1933
+ };
1934
+
1935
+ // Initialize voices when they become available
1936
+ if (speechSynthesis.onvoiceschanged !== undefined) {
1937
+ speechSynthesis.onvoiceschanged = () => {
1938
+ // Voices are now loaded
1939
+ };
1940
+ }
1941
+
1942
+ // Add some sample messages after a delay to simulate a more interactive experience
1943
+ setTimeout(() => {
1944
+ if (chatMessages.children.length <= 2) { // Only if no other messages have been added
1945
+ addAiMessage('هل لديك أي أسئلة محددة تريد أن أساعدك بها اليوم؟ 😊');
1946
+ }
1947
+ }, 8000);
1948
+ </script>
1949
+
1950
+ <div style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px; position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">
1951
+ Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle; display: inline-block; margin-right: 3px; filter: brightness(0) invert(1);">
1952
+ <a href="https://enzostvs-deepsite.hf.space" style="color: #fff; text-decoration: underline;" target="_blank">DeepSite</a> - 🧬
1953
+ <a href="https://enzostvs-deepsite.hf.space?remix=wasmdashai/wasmdashai-chatlhja" style="color: #fff; text-decoration: underline;" target="_blank">Remix</a>
1954
+ </div>
1955
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=wasmdashai/wasmdashai-wasmdashai-chatlhja" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1956
+ </html>