reneco-advanced-input-module 0.0.22 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/voice-input-module.cjs.entry.js +208 -93
- package/dist/cjs/voice-input-module.cjs.entry.js.map +1 -1
- package/dist/cjs/voice-input-module.cjs.js +1 -1
- package/dist/cjs/voice-input-module.entry.cjs.js.map +1 -1
- package/dist/collection/components/voice-input-module/voice-input-module.js +209 -93
- package/dist/collection/components/voice-input-module/voice-input-module.js.map +1 -1
- package/dist/components/voice-input-module.js +209 -93
- package/dist/components/voice-input-module.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/voice-input-module.entry.js +208 -93
- package/dist/esm/voice-input-module.entry.js.map +1 -1
- package/dist/esm/voice-input-module.js +1 -1
- package/dist/types/components/voice-input-module/voice-input-module.d.ts +3 -0
- package/dist/voice-input-module/{p-0e2b9ca0.entry.js → p-920964b2.entry.js} +3 -3
- package/dist/voice-input-module/p-920964b2.entry.js.map +1 -0
- package/dist/voice-input-module/voice-input-module.entry.esm.js.map +1 -1
- package/dist/voice-input-module/voice-input-module.esm.js +1 -1
- package/package.json +1 -1
- package/www/build/{p-0e2b9ca0.entry.js → p-920964b2.entry.js} +3 -3
- package/www/build/p-920964b2.entry.js.map +1 -0
- package/www/build/{p-812b92c7.js → p-cbf8974a.js} +1 -1
- package/www/build/voice-input-module.entry.esm.js.map +1 -1
- package/www/build/voice-input-module.esm.js +1 -1
- package/www/index.html +1 -1
- package/dist/voice-input-module/p-0e2b9ca0.entry.js.map +0 -1
- package/www/build/p-0e2b9ca0.entry.js.map +0 -1
|
@@ -4365,6 +4365,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4365
4365
|
this.isRecording = false;
|
|
4366
4366
|
this.isProcessing = false;
|
|
4367
4367
|
this.hasError = false;
|
|
4368
|
+
this.hasTransientError = false;
|
|
4368
4369
|
this.transcription = '';
|
|
4369
4370
|
this.filledData = null;
|
|
4370
4371
|
this.debugInfo = {};
|
|
@@ -4377,7 +4378,21 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4377
4378
|
if (!input.files || input.files.length === 0)
|
|
4378
4379
|
return;
|
|
4379
4380
|
const file = input.files[0];
|
|
4380
|
-
this.
|
|
4381
|
+
const isEn = this.language === 'en';
|
|
4382
|
+
// Validate file type
|
|
4383
|
+
const validAudioTypes = /^audio\//;
|
|
4384
|
+
const validAudioExtensions = /\.(mp3|wav|webm|m4a|ogg|flac|aac|opus)$/i;
|
|
4385
|
+
if (!validAudioTypes.test(file.type) && !validAudioExtensions.test(file.name)) {
|
|
4386
|
+
this.hasTransientError = true;
|
|
4387
|
+
this.statusMessage = isEn
|
|
4388
|
+
? `Invalid file type: "${file.name}". Please select an audio file.`
|
|
4389
|
+
: `Type de fichier invalide : "${file.name}". Veuillez sélectionner un fichier audio.`;
|
|
4390
|
+
input.value = '';
|
|
4391
|
+
return;
|
|
4392
|
+
}
|
|
4393
|
+
// Reset the input so the same file can be re-selected after an error
|
|
4394
|
+
input.value = '';
|
|
4395
|
+
await this.processAudioContent(file);
|
|
4381
4396
|
};
|
|
4382
4397
|
this.audioRecorder = new AudioRecorderService();
|
|
4383
4398
|
}
|
|
@@ -4437,6 +4452,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4437
4452
|
config: this.parsedConfig
|
|
4438
4453
|
});
|
|
4439
4454
|
this.hasError = false;
|
|
4455
|
+
this.hasTransientError = false;
|
|
4440
4456
|
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.idle) || (this.language == 'en' ? 'Select an input method' : 'Sélectionner une méthode de saisie');
|
|
4441
4457
|
if (this.parsedInputTypes.length === 0) {
|
|
4442
4458
|
this.inputTypes = 'voice';
|
|
@@ -4457,6 +4473,91 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4457
4473
|
} });
|
|
4458
4474
|
}
|
|
4459
4475
|
}
|
|
4476
|
+
getMicErrorMessage(error) {
|
|
4477
|
+
var _a, _b;
|
|
4478
|
+
const isEn = this.language === 'en';
|
|
4479
|
+
const errorName = error.name || '';
|
|
4480
|
+
if (errorName === 'NotAllowedError' || errorName === 'PermissionDeniedError') {
|
|
4481
|
+
return isEn
|
|
4482
|
+
? 'Microphone access denied. Allow microphone access in your browser settings and try again.'
|
|
4483
|
+
: "Accès au microphone refusé. Autorisez l'accès au microphone dans les paramètres du navigateur et réessayez.";
|
|
4484
|
+
}
|
|
4485
|
+
if (errorName === 'NotFoundError' || errorName === 'DevicesNotFoundError') {
|
|
4486
|
+
return isEn
|
|
4487
|
+
? 'No microphone found. Please connect a microphone and try again.'
|
|
4488
|
+
: 'Aucun microphone trouvé. Connectez un microphone et réessayez.';
|
|
4489
|
+
}
|
|
4490
|
+
if (errorName === 'NotReadableError' || errorName === 'TrackStartError') {
|
|
4491
|
+
return isEn
|
|
4492
|
+
? 'Microphone is busy or unavailable. Close other apps using the microphone and try again.'
|
|
4493
|
+
: 'Le microphone est occupé ou indisponible. Fermez les autres applications utilisant le microphone et réessayez.';
|
|
4494
|
+
}
|
|
4495
|
+
if (errorName === 'AbortError') {
|
|
4496
|
+
return isEn
|
|
4497
|
+
? 'Microphone access was interrupted. Please try again.'
|
|
4498
|
+
: "L'accès au microphone a été interrompu. Veuillez réessayer.";
|
|
4499
|
+
}
|
|
4500
|
+
if (errorName === 'OverconstrainedError') {
|
|
4501
|
+
return isEn
|
|
4502
|
+
? 'Microphone does not support the required audio settings.'
|
|
4503
|
+
: 'Le microphone ne supporte pas les paramètres audio requis.';
|
|
4504
|
+
}
|
|
4505
|
+
if (((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('HTTPS')) || ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('not supported'))) {
|
|
4506
|
+
return isEn
|
|
4507
|
+
? 'Microphone access requires HTTPS or localhost.'
|
|
4508
|
+
: "L'accès au microphone nécessite HTTPS ou localhost.";
|
|
4509
|
+
}
|
|
4510
|
+
return isEn ? `Microphone error: ${error.message}` : `Erreur microphone : ${error.message}`;
|
|
4511
|
+
}
|
|
4512
|
+
getReadableErrorMessage(error, phase) {
|
|
4513
|
+
const isEn = this.language === 'en';
|
|
4514
|
+
const msg = error.message || '';
|
|
4515
|
+
if (/401|unauthorized|invalid.{0,20}(api )?key|authentication failed/i.test(msg)) {
|
|
4516
|
+
return isEn
|
|
4517
|
+
? 'Authentication failed: invalid API key. Check your configuration.'
|
|
4518
|
+
: "Échec d'authentification : clé API invalide. Vérifiez votre configuration.";
|
|
4519
|
+
}
|
|
4520
|
+
if (/403|forbidden/i.test(msg)) {
|
|
4521
|
+
return isEn
|
|
4522
|
+
? 'Access denied: check your API permissions.'
|
|
4523
|
+
: 'Accès refusé : vérifiez vos permissions API.';
|
|
4524
|
+
}
|
|
4525
|
+
if (/429|rate.{0,10}limit|too many requests/i.test(msg)) {
|
|
4526
|
+
return isEn
|
|
4527
|
+
? 'Rate limit exceeded. Please wait a moment and try again.'
|
|
4528
|
+
: 'Limite de requêtes dépassée. Veuillez attendre quelques secondes et réessayer.';
|
|
4529
|
+
}
|
|
4530
|
+
if (/404|not found/i.test(msg)) {
|
|
4531
|
+
return isEn
|
|
4532
|
+
? 'API endpoint not found. Check your proxy URL configuration.'
|
|
4533
|
+
: "Endpoint API introuvable. Vérifiez l'URL de votre proxy.";
|
|
4534
|
+
}
|
|
4535
|
+
if (/5\d\d|server error|internal server|bad gateway|service unavailable/i.test(msg)) {
|
|
4536
|
+
return isEn
|
|
4537
|
+
? 'Server error. Please try again in a moment.'
|
|
4538
|
+
: 'Erreur serveur. Veuillez réessayer dans un instant.';
|
|
4539
|
+
}
|
|
4540
|
+
if (/network|failed to fetch|err_connection|connection refused/i.test(msg)) {
|
|
4541
|
+
return isEn
|
|
4542
|
+
? 'Network error: check your connection and proxy server.'
|
|
4543
|
+
: 'Erreur réseau : vérifiez votre connexion et le serveur proxy.';
|
|
4544
|
+
}
|
|
4545
|
+
if (/json|parse error|unexpected token|invalid response/i.test(msg)) {
|
|
4546
|
+
return isEn
|
|
4547
|
+
? 'Unexpected response from AI service. Please try again.'
|
|
4548
|
+
: 'Réponse inattendue du service IA. Veuillez réessayer.';
|
|
4549
|
+
}
|
|
4550
|
+
if (phase === 'transcription') {
|
|
4551
|
+
return isEn ? `Transcription failed: ${msg}` : `Échec de la transcription : ${msg}`;
|
|
4552
|
+
}
|
|
4553
|
+
if (phase === 'llm') {
|
|
4554
|
+
return isEn ? `Form filling failed: ${msg}` : `Échec du remplissage du formulaire : ${msg}`;
|
|
4555
|
+
}
|
|
4556
|
+
if (phase === 'ocr') {
|
|
4557
|
+
return isEn ? `OCR processing failed: ${msg}` : `Échec du traitement OCR : ${msg}`;
|
|
4558
|
+
}
|
|
4559
|
+
return isEn ? `Processing error: ${msg}` : `Erreur de traitement : ${msg}`;
|
|
4560
|
+
}
|
|
4460
4561
|
async handleRecordClick() {
|
|
4461
4562
|
if (this.isProcessing)
|
|
4462
4563
|
return;
|
|
@@ -4470,7 +4571,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4470
4571
|
async startRecording() {
|
|
4471
4572
|
var _a;
|
|
4472
4573
|
try {
|
|
4473
|
-
this.
|
|
4574
|
+
this.hasTransientError = false;
|
|
4474
4575
|
this.statusMessage = (this.language == 'en' ? 'Starting recording...' : `Enregistrement ...`);
|
|
4475
4576
|
this.updateDebugInfo('Start Recording Attempt', {});
|
|
4476
4577
|
await this.audioRecorder.startRecording();
|
|
@@ -4483,8 +4584,8 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4483
4584
|
});
|
|
4484
4585
|
}
|
|
4485
4586
|
catch (error) {
|
|
4486
|
-
this.
|
|
4487
|
-
this.statusMessage =
|
|
4587
|
+
this.hasTransientError = true;
|
|
4588
|
+
this.statusMessage = this.getMicErrorMessage(error);
|
|
4488
4589
|
this.updateDebugInfo('Recording Error', { error: error.message });
|
|
4489
4590
|
this.formFilled.emit({
|
|
4490
4591
|
success: false,
|
|
@@ -4494,40 +4595,36 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4494
4595
|
}
|
|
4495
4596
|
async processJsonForm(ocrData) {
|
|
4496
4597
|
var _a, _b, _c;
|
|
4598
|
+
this.isProcessing = true;
|
|
4599
|
+
this.hasTransientError = false;
|
|
4600
|
+
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing document...' : 'Traitement du document ...');
|
|
4497
4601
|
try {
|
|
4498
|
-
this.isProcessing = true;
|
|
4499
|
-
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing json...' : `Traitement du json ...`);
|
|
4500
|
-
// Extract content from OCR format
|
|
4501
4602
|
const extractedData = (ocrData === null || ocrData === void 0 ? void 0 : ocrData.content) || ocrData;
|
|
4502
4603
|
const jsonForm = JSON.stringify(extractedData);
|
|
4503
|
-
|
|
4604
|
+
if (!extractedData) {
|
|
4605
|
+
throw Object.assign(new Error('OCR returned no data'), { phase: 'ocr' });
|
|
4606
|
+
}
|
|
4504
4607
|
this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
|
|
4505
4608
|
const trimmedSchema = await this.trimSchemaForAI(this.parsedSchema);
|
|
4506
|
-
|
|
4507
|
-
|
|
4609
|
+
let filledSchema;
|
|
4610
|
+
try {
|
|
4611
|
+
filledSchema = await this.llmService.fillFormFromJson(jsonForm, trimmedSchema);
|
|
4612
|
+
}
|
|
4613
|
+
catch (llmError) {
|
|
4614
|
+
throw Object.assign(new Error(llmError.message), { phase: 'llm' });
|
|
4615
|
+
}
|
|
4508
4616
|
this.filledData = this.extractFilledData(filledSchema);
|
|
4509
|
-
this.updateDebugInfo('Form Filled', {
|
|
4510
|
-
filledSchema,
|
|
4511
|
-
extractedData: this.filledData
|
|
4512
|
-
});
|
|
4617
|
+
this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
|
|
4513
4618
|
this.parsedSchema = this.filledData;
|
|
4514
|
-
this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire
|
|
4515
|
-
this.
|
|
4516
|
-
// Emit success event
|
|
4517
|
-
this.formFilled.emit({
|
|
4518
|
-
success: true,
|
|
4519
|
-
data: this.filledData,
|
|
4520
|
-
jsonForm: jsonForm
|
|
4521
|
-
});
|
|
4619
|
+
this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
|
|
4620
|
+
this.formFilled.emit({ success: true, data: this.filledData, jsonForm });
|
|
4522
4621
|
}
|
|
4523
4622
|
catch (error) {
|
|
4524
|
-
|
|
4525
|
-
this.
|
|
4526
|
-
this.
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
jsonForm: JSON.stringify(ocrData)
|
|
4530
|
-
});
|
|
4623
|
+
console.error('OCR processing error:', error);
|
|
4624
|
+
this.hasTransientError = true;
|
|
4625
|
+
this.statusMessage = this.getReadableErrorMessage(error, error.phase || 'llm');
|
|
4626
|
+
this.updateDebugInfo('OCR Processing Error', { phase: error.phase, error: error.message });
|
|
4627
|
+
this.formFilled.emit({ success: false, error: error.message, jsonForm: JSON.stringify(ocrData) });
|
|
4531
4628
|
}
|
|
4532
4629
|
finally {
|
|
4533
4630
|
this.isProcessing = false;
|
|
@@ -4535,83 +4632,100 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4535
4632
|
}
|
|
4536
4633
|
async processAudioContent(audioFile) {
|
|
4537
4634
|
var _a, _b, _c;
|
|
4538
|
-
this.
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
});
|
|
4635
|
+
this.isProcessing = true;
|
|
4636
|
+
this.hasTransientError = false;
|
|
4637
|
+
this.updateDebugInfo('Audio Captured', { size: audioFile.size, type: audioFile.type });
|
|
4542
4638
|
try {
|
|
4543
|
-
//
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4639
|
+
// Validate audio file before sending to API
|
|
4640
|
+
const MAX_AUDIO_SIZE = 25 * 1024 * 1024; // 25MB (API limit)
|
|
4641
|
+
if (audioFile.size <= 44) { // WAV header alone is 44 bytes; effectively empty
|
|
4642
|
+
this.hasTransientError = true;
|
|
4643
|
+
this.statusMessage = this.language == 'en'
|
|
4644
|
+
? 'Recording is empty or too short. Please try again.'
|
|
4645
|
+
: "L'enregistrement est vide ou trop court. Veuillez réessayer.";
|
|
4646
|
+
this.formFilled.emit({ success: false, error: 'Empty or too short audio' });
|
|
4647
|
+
return;
|
|
4648
|
+
}
|
|
4649
|
+
if (audioFile.size > MAX_AUDIO_SIZE) {
|
|
4650
|
+
this.hasTransientError = true;
|
|
4651
|
+
this.statusMessage = this.language == 'en'
|
|
4652
|
+
? `File too large (${Math.round(audioFile.size / 1024 / 1024)}MB). Maximum is 25MB.`
|
|
4653
|
+
: `Fichier trop volumineux (${Math.round(audioFile.size / 1024 / 1024)}Mo). Maximum : 25Mo.`;
|
|
4654
|
+
this.formFilled.emit({ success: false, error: 'Audio file too large' });
|
|
4655
|
+
return;
|
|
4656
|
+
}
|
|
4657
|
+
// Step 1: Transcription
|
|
4658
|
+
let transcription;
|
|
4659
|
+
try {
|
|
4660
|
+
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.transcribing) || (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
|
|
4661
|
+
transcription = await this.speechToTextService.transcribe(audioFile, this.language);
|
|
4662
|
+
this.transcription = transcription;
|
|
4663
|
+
this.updateDebugInfo('Transcription Complete', { transcription });
|
|
4664
|
+
}
|
|
4665
|
+
catch (transcriptionError) {
|
|
4666
|
+
throw Object.assign(new Error(transcriptionError.message), { phase: 'transcription' });
|
|
4667
|
+
}
|
|
4548
4668
|
if (!transcription.trim()) {
|
|
4549
|
-
|
|
4669
|
+
this.hasTransientError = true;
|
|
4670
|
+
this.statusMessage = this.language == 'en'
|
|
4671
|
+
? 'No speech detected. Please speak clearly and try again.'
|
|
4672
|
+
: 'Aucune parole détectée. Parlez clairement et réessayez.';
|
|
4673
|
+
this.formFilled.emit({ success: false, error: 'No speech detected', transcription: '' });
|
|
4674
|
+
return;
|
|
4675
|
+
}
|
|
4676
|
+
// Step 2: LLM form filling
|
|
4677
|
+
let filledSchema;
|
|
4678
|
+
try {
|
|
4679
|
+
this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
|
|
4680
|
+
const trimmedSchema = await this.trimSchemaForAI(this.parsedSchema);
|
|
4681
|
+
filledSchema = await this.llmService.fillFormFromTranscription(transcription, trimmedSchema);
|
|
4682
|
+
}
|
|
4683
|
+
catch (llmError) {
|
|
4684
|
+
throw Object.assign(new Error(llmError.message), { phase: 'llm' });
|
|
4550
4685
|
}
|
|
4551
|
-
// Fill form using LLM
|
|
4552
|
-
this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
|
|
4553
|
-
const trimmedSchema = await this.trimSchemaForAI(this.parsedSchema);
|
|
4554
|
-
const filledSchema = await this.llmService.fillFormFromTranscription(transcription, trimmedSchema);
|
|
4555
|
-
// Extract filled data
|
|
4556
4686
|
this.filledData = this.extractFilledData(filledSchema);
|
|
4557
|
-
this.updateDebugInfo('Form Filled', {
|
|
4558
|
-
filledSchema,
|
|
4559
|
-
extractedData: this.filledData
|
|
4560
|
-
});
|
|
4687
|
+
this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
|
|
4561
4688
|
this.parsedSchema = this.filledData;
|
|
4562
|
-
this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire
|
|
4563
|
-
this.
|
|
4564
|
-
// Emit success event
|
|
4565
|
-
this.formFilled.emit({
|
|
4566
|
-
success: true,
|
|
4567
|
-
data: this.filledData,
|
|
4568
|
-
transcription: transcription
|
|
4569
|
-
});
|
|
4689
|
+
this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
|
|
4690
|
+
this.formFilled.emit({ success: true, data: this.filledData, transcription });
|
|
4570
4691
|
}
|
|
4571
4692
|
catch (error) {
|
|
4572
|
-
console.error('
|
|
4573
|
-
this.
|
|
4574
|
-
this.statusMessage =
|
|
4575
|
-
this.updateDebugInfo('
|
|
4576
|
-
this.formFilled.emit({
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
});
|
|
4693
|
+
console.error('Audio processing error:', error);
|
|
4694
|
+
this.hasTransientError = true;
|
|
4695
|
+
this.statusMessage = this.getReadableErrorMessage(error, error.phase || 'audio-upload');
|
|
4696
|
+
this.updateDebugInfo('Audio Processing Error', { phase: error.phase, error: error.message });
|
|
4697
|
+
this.formFilled.emit({ success: false, error: error.message, transcription: this.transcription });
|
|
4698
|
+
}
|
|
4699
|
+
finally {
|
|
4700
|
+
this.isProcessing = false;
|
|
4581
4701
|
}
|
|
4582
4702
|
}
|
|
4583
4703
|
async stopRecordingAndProcess() {
|
|
4584
4704
|
var _a;
|
|
4705
|
+
this.isRecording = false;
|
|
4706
|
+
this.isProcessing = true;
|
|
4707
|
+
this.hasTransientError = false;
|
|
4708
|
+
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing audio...' : `Traitement de l'audio ...`);
|
|
4709
|
+
this.updateDebugInfo('Stop Recording', {});
|
|
4710
|
+
this.recordingStateChanged.emit({ isRecording: false, state: 'processing' });
|
|
4585
4711
|
try {
|
|
4586
|
-
this.isRecording = false;
|
|
4587
|
-
this.isProcessing = true;
|
|
4588
|
-
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing audio...' : `Traitement de l'audio ...`);
|
|
4589
|
-
this.updateDebugInfo('Stop Recording', {});
|
|
4590
|
-
this.recordingStateChanged.emit({
|
|
4591
|
-
isRecording: false,
|
|
4592
|
-
state: 'processing'
|
|
4593
|
-
});
|
|
4594
|
-
// Stop recording and get audio blob
|
|
4595
4712
|
const audioBlob = await this.audioRecorder.stopRecording();
|
|
4596
4713
|
const audioContent = new File([audioBlob], 'audio.wav', { type: 'audio/wav' });
|
|
4597
|
-
|
|
4714
|
+
// processAudioContent manages isProcessing itself; await ensures we don't return early
|
|
4715
|
+
await this.processAudioContent(audioContent);
|
|
4598
4716
|
}
|
|
4599
4717
|
catch (error) {
|
|
4600
|
-
|
|
4601
|
-
this.
|
|
4602
|
-
this.
|
|
4603
|
-
this.
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
});
|
|
4718
|
+
// Only reached if audioRecorder.stopRecording() itself throws
|
|
4719
|
+
this.hasTransientError = true;
|
|
4720
|
+
this.isProcessing = false;
|
|
4721
|
+
this.statusMessage = (this.language == 'en'
|
|
4722
|
+
? `Failed to stop recording: ${error.message}`
|
|
4723
|
+
: `Impossible d'arrêter l'enregistrement : ${error.message}`);
|
|
4724
|
+
this.updateDebugInfo('Stop Recording Error', { error: error.message });
|
|
4725
|
+
this.formFilled.emit({ success: false, error: error.message, transcription: this.transcription });
|
|
4608
4726
|
}
|
|
4609
4727
|
finally {
|
|
4610
|
-
this.
|
|
4611
|
-
this.recordingStateChanged.emit({
|
|
4612
|
-
isRecording: false,
|
|
4613
|
-
state: 'idle'
|
|
4614
|
-
});
|
|
4728
|
+
this.recordingStateChanged.emit({ isRecording: false, state: 'idle' });
|
|
4615
4729
|
}
|
|
4616
4730
|
}
|
|
4617
4731
|
extractFilledData(filledData) {
|
|
@@ -4919,12 +5033,14 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
4919
5033
|
return (h$1("button", { class: buttonClass, style: buttonStyle, onClick: () => this.handleRecordClick(), disabled: isDisabled, "aria-label": this.isRecording ? 'Stop recording' : 'Start recording' }, this.isProcessing ? (h$1("svg", { class: "record-icon", viewBox: "0 0 24 24" }, h$1("circle", { cx: "12", cy: "12", r: "3" }, h$1("animate", { attributeName: "r", values: "3;6;3", dur: "1s", repeatCount: "indefinite" }), h$1("animate", { attributeName: "opacity", values: "1;0.3;1", dur: "1s", repeatCount: "indefinite" })))) : this.isRecording ? (h$1("svg", { class: "record-icon", viewBox: "0 0 24 24" }, h$1("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }))) : (h$1("svg", { class: "record-icon", viewBox: "0 0 24 24" }, h$1("circle", { cx: "12", cy: "12", r: "8" })))));
|
|
4920
5034
|
}
|
|
4921
5035
|
renderStatusMessage() {
|
|
5036
|
+
const hasAnyError = this.hasError || this.hasTransientError;
|
|
4922
5037
|
const statusClass = [
|
|
4923
5038
|
'status-text',
|
|
4924
|
-
|
|
4925
|
-
this.filledData && !
|
|
5039
|
+
hasAnyError && 'error',
|
|
5040
|
+
this.filledData && !hasAnyError && 'success'
|
|
4926
5041
|
].filter(Boolean).join(' ');
|
|
4927
|
-
|
|
5042
|
+
const statusStyle = this.getStatusStyle();
|
|
5043
|
+
return h$1("div", { class: statusClass, style: statusStyle }, this.statusMessage);
|
|
4928
5044
|
}
|
|
4929
5045
|
renderFormPreview() {
|
|
4930
5046
|
if (!this.parsedSchema)
|
|
@@ -5097,8 +5213,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
5097
5213
|
}
|
|
5098
5214
|
render() {
|
|
5099
5215
|
const containerStyle = this.getContainerStyle();
|
|
5100
|
-
|
|
5101
|
-
return (h$1("div", { key: '8378e98f02e5b7482929d255c5ec12ff8c2731e4' }, h$1("div", { key: 'b8a0d873bd4e1b4c8936747c0919ac8c4c15301b', class: "voice-recorder-container" + (this.debug || this.renderForm ? "-debug" : ""), style: containerStyle }, h$1("div", { key: '86e7783e3686db378ee16aa91a640f33c3255923', class: "row-audio-area" }, this.renderRecordButton(), this.renderUploadRecordButton(), this.renderUploadButton()), this.displayStatus ? h$1("div", { class: "status-text", style: statusStyle }, this.statusMessage) : "", this.renderForm ? this.renderFormPreview() : "", this.debug ? this.renderDebugPanel() : "")));
|
|
5216
|
+
return (h$1("div", { key: 'd2eb6b74840a57809920b3dbba3fd7dfbeef8531' }, h$1("div", { key: 'e66e1d4fc23176f9024ca20413535440a8be3ce8', class: "voice-recorder-container" + (this.debug || this.renderForm ? "-debug" : ""), style: containerStyle }, h$1("div", { key: '57dd7b882771d1f0bd56a97bfd0a06ffee09428e', class: "row-audio-area" }, this.renderRecordButton(), this.renderUploadRecordButton(), this.renderUploadButton()), this.displayStatus ? this.renderStatusMessage() : "", this.renderForm ? this.renderFormPreview() : "", this.debug ? this.renderDebugPanel() : "")));
|
|
5102
5217
|
}
|
|
5103
5218
|
static get watchers() { return {
|
|
5104
5219
|
"formJson": ["initializeServices"],
|
|
@@ -5131,6 +5246,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
|
|
|
5131
5246
|
"isProcessing": [32],
|
|
5132
5247
|
"statusMessage": [32],
|
|
5133
5248
|
"hasError": [32],
|
|
5249
|
+
"hasTransientError": [32],
|
|
5134
5250
|
"transcription": [32],
|
|
5135
5251
|
"filledData": [32],
|
|
5136
5252
|
"debugInfo": [32],
|