Docfile commited on
Commit
dfc76ba
·
verified ·
1 Parent(s): 9723415

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +187 -134
templates/index.html CHANGED
@@ -159,158 +159,211 @@
159
  </div>
160
 
161
  <script>
162
- document.addEventListener('DOMContentLoaded', () => {
163
- const form = document.getElementById('problemForm');
164
- const imageInput = document.getElementById('imageInput');
165
- const loader = document.getElementById('loader');
166
- const solutionDiv = document.getElementById('solution');
167
- const thoughtsContent = document.getElementById('thoughtsContent');
168
- const answerContent = document.getElementById('answerContent');
169
- const thoughtsToggle = document.getElementById('thoughtsToggle');
170
- const thoughtsBox = document.getElementById('thoughtsBox');
171
- const imagePreview = document.getElementById('imagePreview');
172
- const previewImage = document.getElementById('previewImage');
173
-
174
- thoughtsToggle.addEventListener('click', () => {
175
- thoughtsBox.classList.toggle('open');
176
- thoughtsToggle.querySelector('svg').classList.toggle('rotate-180');
177
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
- // Image preview handling
180
- imageInput.addEventListener('change', function(e) {
181
- const file = this.files[0];
182
- if (file) {
183
- const reader = new FileReader();
184
- reader.onload = function(e) {
185
- previewImage.src = e.target.result;
186
- imagePreview.classList.remove('hidden');
187
- }
188
- reader.readAsDataURL(file);
189
- } else {
190
- previewImage.src = "";
191
- imagePreview.classList.add('hidden');
192
- }
193
- });
194
 
195
- // Drag and drop handling
196
- const dropZone = document.querySelector('.uploadArea');
 
197
 
198
- ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
199
- dropZone.addEventListener(eventName, preventDefaults, false);
200
- });
 
201
 
202
- function preventDefaults(e) {
203
- e.preventDefault();
204
- e.stopPropagation();
205
- }
206
 
207
- ['dragenter', 'dragover'].forEach(eventName => {
208
- dropZone.addEventListener(eventName, highlight, false);
209
- });
210
 
211
- ['dragleave', 'drop'].forEach(eventName => {
212
- dropZone.addEventListener(eventName, unhighlight, false);
213
- });
214
 
215
- function highlight(e) {
216
- dropZone.classList.add('border-blue-400');
217
- }
218
 
219
- function unhighlight(e) {
220
- dropZone.classList.remove('border-blue-400');
 
 
 
 
 
 
 
 
 
 
 
221
  }
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
- dropZone.addEventListener('drop', handleDrop, false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
- function handleDrop(e) {
226
- const dt = e.dataTransfer;
227
- const files = dt.files;
228
 
229
- if (files.length) {
230
- imageInput.files = files;
231
- const file = files[0];
232
- const reader = new FileReader();
233
- reader.onload = function(e) {
234
- previewImage.src = e.target.result;
235
- imagePreview.classList.remove('hidden');
236
- }
237
- reader.readAsDataURL(file);
238
- }
239
- }
240
 
241
- // Form submission and streaming
242
- form.addEventListener('submit', async (event) => {
243
- event.preventDefault();
244
- const file = imageInput.files[0];
245
- if (!file) {
246
- alert('Veuillez sélectionner une image.');
247
- return;
248
- }
249
 
250
- // Reset UI
251
- loader.classList.remove('hidden');
252
- solutionDiv.classList.add('hidden');
253
- thoughtsContent.innerHTML = '';
254
- answerContent.innerHTML = '';
255
- thoughtsBox.classList.add('open');
256
-
257
- const formData = new FormData();
258
- formData.append('image', file);
259
-
260
- try {
261
- let currentMode = null;
262
- const response = await fetch('/solve', {
263
- method: 'POST',
264
- body: formData
265
- });
266
-
267
- const reader = response.body.getReader();
268
- const decoder = new TextDecoder();
269
- let buffer = '';
270
-
271
- while (true) {
272
- const { done, value } = await reader.read();
273
- if (done) break;
274
-
275
- buffer += decoder.decode(value, { stream: true });
276
- let eolIndex;
277
-
278
- while ((eolIndex = buffer.indexOf('\n\n')) >= 0) {
279
- const line = buffer.slice(0, eolIndex).trim();
280
- buffer = buffer.slice(eolIndex + 2);
281
-
282
- if (line.startsWith('data:')) {
283
- const data = JSON.parse(line.slice(5));
284
-
285
- if (data.mode) {
286
- currentMode = data.mode;
287
- loader.classList.add('hidden');
288
- solutionDiv.classList.remove('hidden');
289
- }
290
-
291
- if (data.content) {
292
- const content = data.content;
293
- if (currentMode === 'thinking') {
294
- thoughtsContent.innerHTML += `<p>${content}</p>`;
295
- thoughtsContent.scrollTop = thoughtsContent.scrollHeight;
296
- } else if (currentMode === 'answering') {
297
- answerContent.innerHTML += content;
298
- if (window.MathJax) {
299
- MathJax.Hub.Queue(["Typeset", MathJax.Hub, answerContent]);
300
- }
301
- }
302
  }
303
  }
304
  }
305
- }
306
 
307
- } catch (error) {
308
- console.error('Erreur:', error);
309
- alert('Une erreur est survenue lors du traitement de la requête.');
310
- loader.classList.add('hidden');
 
311
  }
312
- });
313
- });
314
- </script>
 
 
 
 
 
 
 
315
  </body>
316
  </html>
 
159
  </div>
160
 
161
  <script>
162
+ document.addEventListener('DOMContentLoaded', () => {
163
+ // Configuration de MathJax pour un meilleur support LaTeX
164
+ window.MathJax = {
165
+ tex: {
166
+ inlineMath: [['$', '$'], ['\\(', '\\)']],
167
+ displayMath: [['$$', '$$'], ['\\[', '\\]']],
168
+ processEscapes: true,
169
+ processEnvironments: true,
170
+ packages: ['base', 'ams', 'noerrors', 'noundefined']
171
+ },
172
+ options: {
173
+ ignoreHtmlClass: 'tex2jax_ignore',
174
+ processHtmlClass: 'tex2jax_process'
175
+ },
176
+ svg: {
177
+ fontCache: 'global'
178
+ }
179
+ };
180
+
181
+ const form = document.getElementById('problemForm');
182
+ const imageInput = document.getElementById('imageInput');
183
+ const loader = document.getElementById('loader');
184
+ const solutionDiv = document.getElementById('solution');
185
+ const thoughtsContent = document.getElementById('thoughtsContent');
186
+ const answerContent = document.getElementById('answerContent');
187
+ const thoughtsToggle = document.getElementById('thoughtsToggle');
188
+ const thoughtsBox = document.getElementById('thoughtsBox');
189
+ const imagePreview = document.getElementById('imagePreview');
190
+ const previewImage = document.getElementById('previewImage');
191
+
192
+ // Fonction pour formater le temps écoulé
193
+ function formatElapsedTime(seconds) {
194
+ return `${seconds}s`;
195
+ }
196
+
197
+ // Fonction pour nettoyer et préparer le texte LaTeX
198
+ function prepareMathContent(content) {
199
+ // Protège les expressions LaTeX déjà correctement formatées
200
+ content = content.replace(/\$\$(.*?)\$\$/g, '[[DISPLAY_MATH_$1]]');
201
+ content = content.replace(/\$(.*?)\$/g, '[[INLINE_MATH_$1]]');
202
+
203
+ // Convertit les expressions potentiellement non formatées
204
+ content = content.replace(/\\boxed\{(.*?)\}/g, '$\\boxed{$1}$');
205
+ content = content.replace(/\\frac\{(.*?)\}\{(.*?)\}/g, '$\\frac{$1}{$2}$');
206
+ content = content.replace(/\\cos/g, '$\\cos$');
207
+ content = content.replace(/\\sin/g, '$\\sin$');
208
+ content = content.replace(/\\theta/g, '$\\theta$');
209
+ content = content.replace(/\\alpha/g, '$\\alpha$');
210
+ content = content.replace(/e\^{([^}]+)}/g, '$e^{$1}$');
211
+
212
+ // Restaure les expressions protégées
213
+ content = content.replace(/\[\[DISPLAY_MATH_(.*?)\]\]/g, '$$$$1$$');
214
+ content = content.replace(/\[\[INLINE_MATH_(.*?)\]\]/g, '$$$1$');
215
+
216
+ return content;
217
+ }
218
+
219
+ // Gestion du toggle des pensées
220
+ thoughtsToggle.addEventListener('click', () => {
221
+ thoughtsBox.classList.toggle('open');
222
+ thoughtsToggle.querySelector('svg').classList.toggle('rotate-180');
223
+ });
224
+
225
+ // Gestion de la prévisualisation des images
226
+ imageInput.addEventListener('change', function(e) {
227
+ const file = this.files[0];
228
+ if (file) {
229
+ const reader = new FileReader();
230
+ reader.onload = function(e) {
231
+ previewImage.src = e.target.result;
232
+ imagePreview.classList.remove('hidden');
233
+ }
234
+ reader.readAsDataURL(file);
235
+ } else {
236
+ previewImage.src = "";
237
+ imagePreview.classList.add('hidden');
238
+ }
239
+ });
240
 
241
+ // Gestion du drag & drop
242
+ const dropZone = document.querySelector('.uploadArea');
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
245
+ dropZone.addEventListener(eventName, preventDefaults, false);
246
+ });
247
 
248
+ function preventDefaults(e) {
249
+ e.preventDefault();
250
+ e.stopPropagation();
251
+ }
252
 
253
+ ['dragenter', 'dragover'].forEach(eventName => {
254
+ dropZone.addEventListener(eventName, highlight, false);
255
+ });
 
256
 
257
+ ['dragleave', 'drop'].forEach(eventName => {
258
+ dropZone.addEventListener(eventName, unhighlight, false);
259
+ });
260
 
261
+ function highlight(e) {
262
+ dropZone.classList.add('border-blue-400');
263
+ }
264
 
265
+ function unhighlight(e) {
266
+ dropZone.classList.remove('border-blue-400');
267
+ }
268
 
269
+ dropZone.addEventListener('drop', handleDrop, false);
270
+
271
+ function handleDrop(e) {
272
+ const dt = e.dataTransfer;
273
+ const files = dt.files;
274
+
275
+ if (files.length) {
276
+ imageInput.files = files;
277
+ const file = files[0];
278
+ const reader = new FileReader();
279
+ reader.onload = function(e) {
280
+ previewImage.src = e.target.result;
281
+ imagePreview.classList.remove('hidden');
282
  }
283
+ reader.readAsDataURL(file);
284
+ }
285
+ }
286
+
287
+ // Gestion de la soumission du formulaire et du streaming
288
+ form.addEventListener('submit', async (event) => {
289
+ event.preventDefault();
290
+ const file = imageInput.files[0];
291
+ if (!file) {
292
+ alert('Veuillez sélectionner une image.');
293
+ return;
294
+ }
295
 
296
+ // Reset UI
297
+ loader.classList.remove('hidden');
298
+ solutionDiv.classList.add('hidden');
299
+ thoughtsContent.innerHTML = '';
300
+ answerContent.innerHTML = '';
301
+ thoughtsBox.classList.add('open');
302
+
303
+ const formData = new FormData();
304
+ formData.append('image', file);
305
+
306
+ try {
307
+ let currentMode = null;
308
+ const response = await fetch('/solve', {
309
+ method: 'POST',
310
+ body: formData
311
+ });
312
 
313
+ const reader = response.body.getReader();
314
+ const decoder = new TextDecoder();
315
+ let buffer = '';
316
 
317
+ while (true) {
318
+ const { done, value } = await reader.read();
319
+ if (done) break;
 
 
 
 
 
 
 
 
320
 
321
+ buffer += decoder.decode(value, { stream: true });
322
+ let eolIndex;
 
 
 
 
 
 
323
 
324
+ while ((eolIndex = buffer.indexOf('\n\n')) >= 0) {
325
+ const line = buffer.slice(0, eolIndex).trim();
326
+ buffer = buffer.slice(eolIndex + 2);
327
+
328
+ if (line.startsWith('data:')) {
329
+ const data = JSON.parse(line.slice(5));
330
+
331
+ if (data.mode) {
332
+ currentMode = data.mode;
333
+ loader.classList.add('hidden');
334
+ solutionDiv.classList.remove('hidden');
335
+ }
336
+
337
+ if (data.content) {
338
+ const content = prepareMathContent(data.content);
339
+ const timeString = data.elapsed_time ? ` <span class="text-blue-400">(${formatElapsedTime(data.elapsed_time)})</span> ` : '';
340
+
341
+ if (currentMode === 'thinking') {
342
+ thoughtsContent.innerHTML += `<p>${timeString}${content}</p>`;
343
+ thoughtsContent.scrollTop = thoughtsContent.scrollHeight;
344
+ } else if (currentMode === 'answering') {
345
+ answerContent.innerHTML += content;
346
+ if (window.MathJax) {
347
+ MathJax.Hub.Queue(["Typeset", MathJax.Hub, answerContent]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  }
349
  }
350
  }
 
351
 
352
+ // Mettre à jour MathJax pour le contenu des pensées aussi
353
+ if (window.MathJax) {
354
+ MathJax.Hub.Queue(["Typeset", MathJax.Hub, thoughtsContent]);
355
+ }
356
+ }
357
  }
358
+ }
359
+
360
+ } catch (error) {
361
+ console.error('Erreur:', error);
362
+ alert('Une erreur est survenue lors du traitement de la requête.');
363
+ loader.classList.add('hidden');
364
+ }
365
+ });
366
+ });
367
+ </script>
368
  </body>
369
  </html>