@memori.ai/memori-react 2.10.0 â 2.10.2
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/CHANGELOG.md +24 -0
- package/dist/components/ChatBubble/ChatBubble.js +31 -31
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.d.ts +3 -2
- package/dist/components/MemoriWidget/MemoriWidget.js +213 -205
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/helpers/utils.d.ts +1 -0
- package/dist/helpers/utils.js +5 -1
- package/dist/helpers/utils.js.map +1 -1
- package/dist/helpers/utils.test.js +12 -0
- package/dist/helpers/utils.test.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.js +31 -31
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.d.ts +3 -2
- package/esm/components/MemoriWidget/MemoriWidget.js +214 -206
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/helpers/utils.d.ts +1 -0
- package/esm/helpers/utils.js +3 -0
- package/esm/helpers/utils.js.map +1 -1
- package/esm/helpers/utils.test.js +13 -1
- package/esm/helpers/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ChatBubble/ChatBubble.tsx +1 -1
- package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +3 -0
- package/src/components/MemoriWidget/MemoriWidget.tsx +291 -273
- package/src/helpers/utils.test.ts +15 -1
- package/src/helpers/utils.ts +4 -0
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
GamificationLevel,
|
|
14
14
|
Tenant,
|
|
15
15
|
Asset,
|
|
16
|
+
MemoriSession,
|
|
16
17
|
} from '@memori.ai/memori-api-client/src/types';
|
|
17
18
|
import {
|
|
18
19
|
SpeakerAudioDestination,
|
|
@@ -59,13 +60,16 @@ import ChatLayout from '../layouts/Chat';
|
|
|
59
60
|
// Helpers / Utils
|
|
60
61
|
import { getTranslation } from '../../helpers/translations';
|
|
61
62
|
import { setLocalConfig, getLocalConfig } from '../../helpers/configuration';
|
|
62
|
-
import {
|
|
63
|
+
import {
|
|
64
|
+
hasTouchscreen,
|
|
65
|
+
stripDuplicates,
|
|
66
|
+
stripEmojis,
|
|
67
|
+
} from '../../helpers/utils';
|
|
63
68
|
import { anonTag } from '../../helpers/constants';
|
|
64
69
|
import { getErrori18nKey } from '../../helpers/error';
|
|
65
70
|
import { getGamificationLevel } from '../../helpers/statistics';
|
|
66
71
|
import AgeVerificationModal from '../AgeVerificationModal/AgeVerificationModal';
|
|
67
72
|
import SettingsDrawer from '../SettingsDrawer/SettingsDrawer';
|
|
68
|
-
import { MemoriSession } from '@memori.ai/memori-api-client/dist/types';
|
|
69
73
|
|
|
70
74
|
// Widget utilities and helpers
|
|
71
75
|
const getMemoriState = (integrationId?: string): object | null => {
|
|
@@ -92,20 +96,27 @@ const getMemoriState = (integrationId?: string): object | null => {
|
|
|
92
96
|
|
|
93
97
|
type MemoriTextEnteredEvent = CustomEvent<{
|
|
94
98
|
text: string;
|
|
99
|
+
waitForPrevious?: boolean;
|
|
95
100
|
hidden?: boolean;
|
|
96
101
|
}>;
|
|
97
102
|
|
|
98
|
-
const typeMessage = (
|
|
103
|
+
const typeMessage = (
|
|
104
|
+
message: string,
|
|
105
|
+
waitForPrevious = true,
|
|
106
|
+
hidden = false
|
|
107
|
+
) => {
|
|
99
108
|
const e: MemoriTextEnteredEvent = new CustomEvent('MemoriTextEntered', {
|
|
100
109
|
detail: {
|
|
101
110
|
text: message,
|
|
111
|
+
waitForPrevious,
|
|
102
112
|
hidden,
|
|
103
113
|
},
|
|
104
114
|
});
|
|
105
115
|
|
|
106
116
|
document.dispatchEvent(e);
|
|
107
117
|
};
|
|
108
|
-
const typeMessageHidden = (message: string
|
|
118
|
+
const typeMessageHidden = (message: string, waitForPrevious = true) =>
|
|
119
|
+
typeMessage(message, waitForPrevious, true);
|
|
109
120
|
|
|
110
121
|
interface CustomEventMap {
|
|
111
122
|
MemoriTextEntered: MemoriTextEnteredEvent;
|
|
@@ -259,10 +270,12 @@ const MemoriWidget = ({
|
|
|
259
270
|
const [clickedStart, setClickedStart] = useState(false);
|
|
260
271
|
const [gotErrorInOpening, setGotErrorInOpening] = useState(false);
|
|
261
272
|
|
|
262
|
-
const language =
|
|
263
|
-
?.
|
|
264
|
-
|
|
265
|
-
|
|
273
|
+
const language =
|
|
274
|
+
memori.culture?.split('-')?.[0]?.toUpperCase()! ||
|
|
275
|
+
memoriConfigs
|
|
276
|
+
?.find(c => c.memoriConfigID === memori.memoriConfigurationID)
|
|
277
|
+
?.culture?.split('-')?.[0]
|
|
278
|
+
?.toUpperCase()!;
|
|
266
279
|
const integrationConfig = integration?.customData
|
|
267
280
|
? JSON.parse(integration.customData)
|
|
268
281
|
: null;
|
|
@@ -273,7 +286,6 @@ const MemoriWidget = ({
|
|
|
273
286
|
const [userLang, setUserLang] = useState(
|
|
274
287
|
memoriLang ??
|
|
275
288
|
integrationConfig?.lang ??
|
|
276
|
-
memori?.culture?.split('-')?.[0] ??
|
|
277
289
|
language ??
|
|
278
290
|
integrationConfig?.uiLang ??
|
|
279
291
|
i18n.language ??
|
|
@@ -372,6 +384,264 @@ const MemoriWidget = ({
|
|
|
372
384
|
applyPosition(venue);
|
|
373
385
|
};
|
|
374
386
|
|
|
387
|
+
/**
|
|
388
|
+
* History e gestione invio messaggi
|
|
389
|
+
*/
|
|
390
|
+
const [userMessage, setUserMessage] = useState<string>('');
|
|
391
|
+
const onChangeUserMessage = (value: string) => {
|
|
392
|
+
if (!value || value === '\n' || value.trim() === '') {
|
|
393
|
+
setUserMessage('');
|
|
394
|
+
resetInteractionTimeout();
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
setUserMessage(value);
|
|
398
|
+
clearInteractionTimeout();
|
|
399
|
+
};
|
|
400
|
+
const [listening, setListening] = useState(false);
|
|
401
|
+
const [history, setHistory] = useState<Message[]>([]);
|
|
402
|
+
const pushMessage = (message: Message) => {
|
|
403
|
+
setHistory(history => [...history, { ...message }]);
|
|
404
|
+
};
|
|
405
|
+
const sendMessage = async (
|
|
406
|
+
text: string,
|
|
407
|
+
media?: Medium[],
|
|
408
|
+
newSessionId?: string,
|
|
409
|
+
translate: boolean = true,
|
|
410
|
+
translatedText?: string,
|
|
411
|
+
hidden: boolean = false
|
|
412
|
+
) => {
|
|
413
|
+
const sessionID =
|
|
414
|
+
newSessionId ||
|
|
415
|
+
sessionId ||
|
|
416
|
+
(window.getMemoriState() as MemoriSession)?.sessionID;
|
|
417
|
+
if (!sessionID || !text?.length) return;
|
|
418
|
+
|
|
419
|
+
if (!hidden)
|
|
420
|
+
pushMessage({
|
|
421
|
+
text: text,
|
|
422
|
+
translatedText,
|
|
423
|
+
fromUser: true,
|
|
424
|
+
media: media ?? [],
|
|
425
|
+
initial: sessionId
|
|
426
|
+
? !!newSessionId && newSessionId !== sessionId
|
|
427
|
+
: !!newSessionId,
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
setMemoriTyping(true);
|
|
431
|
+
|
|
432
|
+
let msg = text;
|
|
433
|
+
|
|
434
|
+
if (
|
|
435
|
+
translate &&
|
|
436
|
+
!instruct &&
|
|
437
|
+
isMultilanguageEnabled &&
|
|
438
|
+
userLang.toUpperCase() !== language.toUpperCase()
|
|
439
|
+
) {
|
|
440
|
+
const translation = await getTranslation(
|
|
441
|
+
text,
|
|
442
|
+
language,
|
|
443
|
+
userLang,
|
|
444
|
+
baseUrl
|
|
445
|
+
);
|
|
446
|
+
msg = translation.text;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const { currentState, ...response } = await postTextEnteredEvent({
|
|
450
|
+
sessionId: sessionID,
|
|
451
|
+
text: msg,
|
|
452
|
+
});
|
|
453
|
+
if (response.resultCode === 0 && currentState) {
|
|
454
|
+
const emission = currentState.emission ?? currentDialogState?.emission;
|
|
455
|
+
if (currentState.state === 'X4' && memori.giverTag) {
|
|
456
|
+
const { currentState, ...resp } = await postTagChangedEvent(
|
|
457
|
+
sessionID,
|
|
458
|
+
memori.giverTag
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
if (resp.resultCode === 0) {
|
|
462
|
+
setCurrentDialogState(currentState);
|
|
463
|
+
|
|
464
|
+
if (currentState.emission) {
|
|
465
|
+
pushMessage({
|
|
466
|
+
text: currentState.emission,
|
|
467
|
+
media: currentState.media,
|
|
468
|
+
fromUser: false,
|
|
469
|
+
});
|
|
470
|
+
speak(currentState.emission);
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
console.error(response, resp);
|
|
474
|
+
message.error(t(getErrori18nKey(resp.resultCode)));
|
|
475
|
+
}
|
|
476
|
+
} else if (currentState.state === 'X2d' && memori.giverTag) {
|
|
477
|
+
const { currentState, ...resp } = await postTextEnteredEvent({
|
|
478
|
+
sessionId: sessionID,
|
|
479
|
+
text: Math.random().toString().substring(2, 8),
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
if (resp.resultCode === 0) {
|
|
483
|
+
const { currentState, ...resp } = await postTagChangedEvent(
|
|
484
|
+
sessionID,
|
|
485
|
+
memori.giverTag
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
if (resp.resultCode === 0) {
|
|
489
|
+
setCurrentDialogState(currentState);
|
|
490
|
+
|
|
491
|
+
if (currentState.emission) {
|
|
492
|
+
pushMessage({
|
|
493
|
+
text: currentState.emission,
|
|
494
|
+
media: currentState.media,
|
|
495
|
+
fromUser: false,
|
|
496
|
+
});
|
|
497
|
+
speak(currentState.emission);
|
|
498
|
+
}
|
|
499
|
+
} else {
|
|
500
|
+
console.error(response, resp);
|
|
501
|
+
message.error(t(getErrori18nKey(resp.resultCode)));
|
|
502
|
+
}
|
|
503
|
+
} else {
|
|
504
|
+
console.error(response, resp);
|
|
505
|
+
message.error(t(getErrori18nKey(resp.resultCode)));
|
|
506
|
+
}
|
|
507
|
+
} else if (
|
|
508
|
+
userLang.toLowerCase() !== language.toLowerCase() &&
|
|
509
|
+
emission &&
|
|
510
|
+
!instruct &&
|
|
511
|
+
isMultilanguageEnabled
|
|
512
|
+
) {
|
|
513
|
+
translateDialogState(currentState, userLang).then(ts => {
|
|
514
|
+
if (ts.emission) {
|
|
515
|
+
speak(ts.emission);
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
} else {
|
|
519
|
+
setCurrentDialogState({
|
|
520
|
+
...currentState,
|
|
521
|
+
emission,
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
if (emission) {
|
|
525
|
+
pushMessage({
|
|
526
|
+
text: emission,
|
|
527
|
+
media: currentState.media,
|
|
528
|
+
fromUser: false,
|
|
529
|
+
generatedByAI: !!currentState.completion,
|
|
530
|
+
});
|
|
531
|
+
speak(emission);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
} else if (response.resultCode === 404) {
|
|
535
|
+
// remove last sent message, will set it as initial
|
|
536
|
+
setHistory(h => [...h.slice(0, h.length - 1)]);
|
|
537
|
+
|
|
538
|
+
// post session timeout -> Z0/A0 -> restart session and re-send msg
|
|
539
|
+
reopenSession(
|
|
540
|
+
false,
|
|
541
|
+
memoriPwd || memori.secretToken,
|
|
542
|
+
memoriTokens,
|
|
543
|
+
instruct && memori.giverTag ? memori.giverTag : undefined,
|
|
544
|
+
instruct && memori.giverPIN ? memori.giverPIN : undefined,
|
|
545
|
+
initialContextVars,
|
|
546
|
+
initialQuestion
|
|
547
|
+
).then(state => {
|
|
548
|
+
console.info('session timeout');
|
|
549
|
+
if (state?.sessionID) {
|
|
550
|
+
setTimeout(() => {
|
|
551
|
+
sendMessage(text, media, state?.sessionID);
|
|
552
|
+
}, 500);
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
setMemoriTyping(false);
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Traduzioni istantanee
|
|
562
|
+
*/
|
|
563
|
+
const translateDialogState = async (state: DialogState, userLang: string) => {
|
|
564
|
+
const emission = state.emission ?? currentDialogState?.emission;
|
|
565
|
+
|
|
566
|
+
let translatedState = { ...state };
|
|
567
|
+
let translatedMsg = null;
|
|
568
|
+
|
|
569
|
+
if (
|
|
570
|
+
!emission ||
|
|
571
|
+
instruct ||
|
|
572
|
+
language.toUpperCase() === userLang.toUpperCase() ||
|
|
573
|
+
!isMultilanguageEnabled
|
|
574
|
+
) {
|
|
575
|
+
translatedState = { ...state, emission };
|
|
576
|
+
if (emission) {
|
|
577
|
+
translatedMsg = {
|
|
578
|
+
text: emission,
|
|
579
|
+
media: state.media,
|
|
580
|
+
fromUser: false,
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
} else {
|
|
584
|
+
const t = await getTranslation(emission, userLang, language, baseUrl);
|
|
585
|
+
if (state.hints && state.hints.length > 0) {
|
|
586
|
+
const translatedHints = await Promise.all(
|
|
587
|
+
(state.hints ?? []).map(async hint => {
|
|
588
|
+
const tHint = await getTranslation(
|
|
589
|
+
hint,
|
|
590
|
+
userLang,
|
|
591
|
+
language,
|
|
592
|
+
baseUrl
|
|
593
|
+
);
|
|
594
|
+
return {
|
|
595
|
+
text: tHint?.text ?? hint,
|
|
596
|
+
originalText: hint,
|
|
597
|
+
} as TranslatedHint;
|
|
598
|
+
})
|
|
599
|
+
);
|
|
600
|
+
translatedState = {
|
|
601
|
+
...state,
|
|
602
|
+
emission: t.text,
|
|
603
|
+
translatedHints,
|
|
604
|
+
};
|
|
605
|
+
} else {
|
|
606
|
+
translatedState = {
|
|
607
|
+
...state,
|
|
608
|
+
emission: t.text,
|
|
609
|
+
hints:
|
|
610
|
+
state.hints ??
|
|
611
|
+
(state.state === 'G1' ? currentDialogState?.hints : []),
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
if (t.text.length > 0)
|
|
616
|
+
translatedMsg = {
|
|
617
|
+
text: t.text,
|
|
618
|
+
media: state.media,
|
|
619
|
+
fromUser: false,
|
|
620
|
+
generatedByAI: !!state.completion,
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
setCurrentDialogState(translatedState);
|
|
625
|
+
if (translatedMsg) {
|
|
626
|
+
pushMessage(translatedMsg);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
return translatedState;
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Age verification
|
|
634
|
+
*/
|
|
635
|
+
const minAge = memori.ageRestriction
|
|
636
|
+
? memori.ageRestriction
|
|
637
|
+
: memori.nsfw
|
|
638
|
+
? 18
|
|
639
|
+
: memori.enableCompletions
|
|
640
|
+
? 14
|
|
641
|
+
: 0;
|
|
642
|
+
const [birthDate, setBirthDate] = useState<string | undefined>();
|
|
643
|
+
const [showAgeVerification, setShowAgeVerification] = useState(false);
|
|
644
|
+
|
|
375
645
|
/**
|
|
376
646
|
* Sessione
|
|
377
647
|
*/
|
|
@@ -684,264 +954,6 @@ const MemoriWidget = ({
|
|
|
684
954
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
685
955
|
}, []);
|
|
686
956
|
|
|
687
|
-
/**
|
|
688
|
-
* History e gestione invio messaggi
|
|
689
|
-
*/
|
|
690
|
-
const [userMessage, setUserMessage] = useState<string>('');
|
|
691
|
-
const onChangeUserMessage = (value: string) => {
|
|
692
|
-
if (!value || value === '\n' || value.trim() === '') {
|
|
693
|
-
setUserMessage('');
|
|
694
|
-
resetInteractionTimeout();
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
setUserMessage(value);
|
|
698
|
-
clearInteractionTimeout();
|
|
699
|
-
};
|
|
700
|
-
const [listening, setListening] = useState(false);
|
|
701
|
-
const [history, setHistory] = useState<Message[]>([]);
|
|
702
|
-
const pushMessage = (message: Message) => {
|
|
703
|
-
setHistory(history => [...history, { ...message }]);
|
|
704
|
-
};
|
|
705
|
-
const sendMessage = useCallback(
|
|
706
|
-
async (
|
|
707
|
-
text: string,
|
|
708
|
-
media?: Medium[],
|
|
709
|
-
newSessionId?: string,
|
|
710
|
-
translate: boolean = true,
|
|
711
|
-
translatedText?: string,
|
|
712
|
-
hidden: boolean = false
|
|
713
|
-
) => {
|
|
714
|
-
const sessionID = newSessionId || sessionId;
|
|
715
|
-
if (!sessionID || !text?.length) return;
|
|
716
|
-
|
|
717
|
-
if (!hidden)
|
|
718
|
-
pushMessage({
|
|
719
|
-
text: text,
|
|
720
|
-
translatedText,
|
|
721
|
-
fromUser: true,
|
|
722
|
-
media: media ?? [],
|
|
723
|
-
initial: !!newSessionId,
|
|
724
|
-
});
|
|
725
|
-
|
|
726
|
-
setMemoriTyping(true);
|
|
727
|
-
|
|
728
|
-
const language = memori.culture?.split('-')?.[0] ?? i18n.language ?? 'IT';
|
|
729
|
-
let msg = text;
|
|
730
|
-
|
|
731
|
-
if (
|
|
732
|
-
translate &&
|
|
733
|
-
!instruct &&
|
|
734
|
-
isMultilanguageEnabled &&
|
|
735
|
-
userLang.toUpperCase() !== language.toUpperCase()
|
|
736
|
-
) {
|
|
737
|
-
const translation = await getTranslation(
|
|
738
|
-
text,
|
|
739
|
-
language,
|
|
740
|
-
userLang,
|
|
741
|
-
baseUrl
|
|
742
|
-
);
|
|
743
|
-
msg = translation.text;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
const { currentState, ...response } = await postTextEnteredEvent({
|
|
747
|
-
sessionId: sessionID,
|
|
748
|
-
text: msg,
|
|
749
|
-
});
|
|
750
|
-
if (response.resultCode === 0 && currentState) {
|
|
751
|
-
const emission = currentState.emission ?? currentDialogState?.emission;
|
|
752
|
-
if (currentState.state === 'X4' && memori.giverTag) {
|
|
753
|
-
const { currentState, ...resp } = await postTagChangedEvent(
|
|
754
|
-
sessionID,
|
|
755
|
-
memori.giverTag
|
|
756
|
-
);
|
|
757
|
-
|
|
758
|
-
if (resp.resultCode === 0) {
|
|
759
|
-
setCurrentDialogState(currentState);
|
|
760
|
-
|
|
761
|
-
if (currentState.emission) {
|
|
762
|
-
pushMessage({
|
|
763
|
-
text: currentState.emission,
|
|
764
|
-
media: currentState.media,
|
|
765
|
-
fromUser: false,
|
|
766
|
-
});
|
|
767
|
-
speak(currentState.emission);
|
|
768
|
-
}
|
|
769
|
-
} else {
|
|
770
|
-
console.error(response, resp);
|
|
771
|
-
message.error(t(getErrori18nKey(resp.resultCode)));
|
|
772
|
-
}
|
|
773
|
-
} else if (currentState.state === 'X2d' && memori.giverTag) {
|
|
774
|
-
const { currentState, ...resp } = await postTextEnteredEvent({
|
|
775
|
-
sessionId: sessionID,
|
|
776
|
-
text: Math.random().toString().substring(2, 8),
|
|
777
|
-
});
|
|
778
|
-
|
|
779
|
-
if (resp.resultCode === 0) {
|
|
780
|
-
const { currentState, ...resp } = await postTagChangedEvent(
|
|
781
|
-
sessionID,
|
|
782
|
-
memori.giverTag
|
|
783
|
-
);
|
|
784
|
-
|
|
785
|
-
if (resp.resultCode === 0) {
|
|
786
|
-
setCurrentDialogState(currentState);
|
|
787
|
-
|
|
788
|
-
if (currentState.emission) {
|
|
789
|
-
pushMessage({
|
|
790
|
-
text: currentState.emission,
|
|
791
|
-
media: currentState.media,
|
|
792
|
-
fromUser: false,
|
|
793
|
-
});
|
|
794
|
-
speak(currentState.emission);
|
|
795
|
-
}
|
|
796
|
-
} else {
|
|
797
|
-
console.error(response, resp);
|
|
798
|
-
message.error(t(getErrori18nKey(resp.resultCode)));
|
|
799
|
-
}
|
|
800
|
-
} else {
|
|
801
|
-
console.error(response, resp);
|
|
802
|
-
message.error(t(getErrori18nKey(resp.resultCode)));
|
|
803
|
-
}
|
|
804
|
-
} else if (
|
|
805
|
-
userLang.toLowerCase() !== language.toLowerCase() &&
|
|
806
|
-
emission &&
|
|
807
|
-
!instruct &&
|
|
808
|
-
isMultilanguageEnabled
|
|
809
|
-
) {
|
|
810
|
-
translateDialogState(currentState, userLang).then(ts => {
|
|
811
|
-
if (ts.emission) {
|
|
812
|
-
speak(ts.emission);
|
|
813
|
-
}
|
|
814
|
-
});
|
|
815
|
-
} else {
|
|
816
|
-
setCurrentDialogState({
|
|
817
|
-
...currentState,
|
|
818
|
-
emission,
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
if (emission) {
|
|
822
|
-
pushMessage({
|
|
823
|
-
text: emission,
|
|
824
|
-
media: currentState.media,
|
|
825
|
-
fromUser: false,
|
|
826
|
-
generatedByAI: !!currentState.completion,
|
|
827
|
-
});
|
|
828
|
-
speak(emission);
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
} else if (response.resultCode === 404) {
|
|
832
|
-
// remove last sent message, will set it as initial
|
|
833
|
-
setHistory(h => [...h.slice(0, h.length - 1)]);
|
|
834
|
-
|
|
835
|
-
// post session timeout -> Z0/A0 -> restart session and re-send msg
|
|
836
|
-
reopenSession(
|
|
837
|
-
false,
|
|
838
|
-
memoriPwd || memori.secretToken,
|
|
839
|
-
memoriTokens,
|
|
840
|
-
instruct && memori.giverTag ? memori.giverTag : undefined,
|
|
841
|
-
instruct && memori.giverPIN ? memori.giverPIN : undefined,
|
|
842
|
-
initialContextVars,
|
|
843
|
-
initialQuestion
|
|
844
|
-
).then(state => {
|
|
845
|
-
console.info('session timeout');
|
|
846
|
-
if (state?.sessionID) {
|
|
847
|
-
setTimeout(() => {
|
|
848
|
-
sendMessage(text, media, state?.sessionID);
|
|
849
|
-
}, 500);
|
|
850
|
-
}
|
|
851
|
-
});
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
setMemoriTyping(false);
|
|
855
|
-
},
|
|
856
|
-
[sessionId]
|
|
857
|
-
);
|
|
858
|
-
|
|
859
|
-
/**
|
|
860
|
-
* Traduzioni istantanee
|
|
861
|
-
*/
|
|
862
|
-
const translateDialogState = async (state: DialogState, userLang: string) => {
|
|
863
|
-
const language = memori.culture?.split('-')?.[0] ?? i18n.language ?? 'IT';
|
|
864
|
-
const emission = state.emission ?? currentDialogState?.emission;
|
|
865
|
-
|
|
866
|
-
let translatedState = { ...state };
|
|
867
|
-
let translatedMsg = null;
|
|
868
|
-
|
|
869
|
-
if (
|
|
870
|
-
!emission ||
|
|
871
|
-
instruct ||
|
|
872
|
-
language.toUpperCase() === userLang.toUpperCase() ||
|
|
873
|
-
!isMultilanguageEnabled
|
|
874
|
-
) {
|
|
875
|
-
translatedState = { ...state, emission };
|
|
876
|
-
if (emission) {
|
|
877
|
-
translatedMsg = {
|
|
878
|
-
text: emission,
|
|
879
|
-
media: state.media,
|
|
880
|
-
fromUser: false,
|
|
881
|
-
};
|
|
882
|
-
}
|
|
883
|
-
} else {
|
|
884
|
-
const t = await getTranslation(emission, userLang, language, baseUrl);
|
|
885
|
-
if (state.hints && state.hints.length > 0) {
|
|
886
|
-
const translatedHints = await Promise.all(
|
|
887
|
-
(state.hints ?? []).map(async hint => {
|
|
888
|
-
const tHint = await getTranslation(
|
|
889
|
-
hint,
|
|
890
|
-
userLang,
|
|
891
|
-
language,
|
|
892
|
-
baseUrl
|
|
893
|
-
);
|
|
894
|
-
return {
|
|
895
|
-
text: tHint?.text ?? hint,
|
|
896
|
-
originalText: hint,
|
|
897
|
-
} as TranslatedHint;
|
|
898
|
-
})
|
|
899
|
-
);
|
|
900
|
-
translatedState = {
|
|
901
|
-
...state,
|
|
902
|
-
emission: t.text,
|
|
903
|
-
translatedHints,
|
|
904
|
-
};
|
|
905
|
-
} else {
|
|
906
|
-
translatedState = {
|
|
907
|
-
...state,
|
|
908
|
-
emission: t.text,
|
|
909
|
-
hints:
|
|
910
|
-
state.hints ??
|
|
911
|
-
(state.state === 'G1' ? currentDialogState?.hints : []),
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
if (t.text.length > 0)
|
|
916
|
-
translatedMsg = {
|
|
917
|
-
text: t.text,
|
|
918
|
-
media: state.media,
|
|
919
|
-
fromUser: false,
|
|
920
|
-
generatedByAI: !!state.completion,
|
|
921
|
-
};
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
setCurrentDialogState(translatedState);
|
|
925
|
-
if (translatedMsg) {
|
|
926
|
-
pushMessage(translatedMsg);
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
return translatedState;
|
|
930
|
-
};
|
|
931
|
-
|
|
932
|
-
/**
|
|
933
|
-
* Age verification
|
|
934
|
-
*/
|
|
935
|
-
const minAge = memori.ageRestriction
|
|
936
|
-
? memori.ageRestriction
|
|
937
|
-
: memori.nsfw
|
|
938
|
-
? 18
|
|
939
|
-
: memori.enableCompletions
|
|
940
|
-
? 14
|
|
941
|
-
: 0;
|
|
942
|
-
const [birthDate, setBirthDate] = useState<string | undefined>();
|
|
943
|
-
const [showAgeVerification, setShowAgeVerification] = useState(false);
|
|
944
|
-
|
|
945
957
|
/**
|
|
946
958
|
* Timeout conversazione
|
|
947
959
|
*/
|
|
@@ -1410,7 +1422,7 @@ const MemoriWidget = ({
|
|
|
1410
1422
|
`<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" xml:lang="${getCultureCodeByLanguage(
|
|
1411
1423
|
userLang
|
|
1412
1424
|
)}"><voice name="${getTTSVoice(userLang)}"><s>${replaceTextWithPhonemes(
|
|
1413
|
-
escapeHTML(text),
|
|
1425
|
+
escapeHTML(stripEmojis(text)),
|
|
1414
1426
|
userLang.toLowerCase()
|
|
1415
1427
|
)}</s></voice></speak>`,
|
|
1416
1428
|
result => {
|
|
@@ -1942,23 +1954,29 @@ const MemoriWidget = ({
|
|
|
1942
1954
|
// to use in integrations or snippets
|
|
1943
1955
|
const memoriTextEnteredHandler = useCallback(
|
|
1944
1956
|
(e: MemoriTextEnteredEvent) => {
|
|
1945
|
-
const { text, hidden } = e.detail;
|
|
1957
|
+
const { text, waitForPrevious, hidden } = e.detail;
|
|
1946
1958
|
|
|
1947
1959
|
const sessionID =
|
|
1948
1960
|
sessionId || (window.getMemoriState() as MemoriSession)?.sessionID;
|
|
1949
1961
|
|
|
1950
1962
|
if (text) {
|
|
1951
1963
|
// wait to finish reading previous emission
|
|
1952
|
-
if (
|
|
1964
|
+
if (
|
|
1965
|
+
waitForPrevious &&
|
|
1966
|
+
!speakerMuted &&
|
|
1967
|
+
(memoriSpeaking || memoriTyping)
|
|
1968
|
+
) {
|
|
1953
1969
|
setTimeout(() => {
|
|
1954
1970
|
memoriTextEnteredHandler(e);
|
|
1955
1971
|
}, 1000);
|
|
1956
1972
|
} else {
|
|
1957
|
-
|
|
1973
|
+
stopListening();
|
|
1974
|
+
stopAudio();
|
|
1975
|
+
sendMessage(text, undefined, undefined, undefined, undefined, hidden);
|
|
1958
1976
|
}
|
|
1959
1977
|
}
|
|
1960
1978
|
},
|
|
1961
|
-
[sessionId, isPlayingAudio, memoriTyping]
|
|
1979
|
+
[sessionId, isPlayingAudio, memoriTyping, userLang]
|
|
1962
1980
|
);
|
|
1963
1981
|
useEffect(() => {
|
|
1964
1982
|
document.addEventListener('MemoriTextEntered', memoriTextEnteredHandler);
|
|
@@ -1969,7 +1987,7 @@ const MemoriWidget = ({
|
|
|
1969
1987
|
memoriTextEnteredHandler
|
|
1970
1988
|
);
|
|
1971
1989
|
};
|
|
1972
|
-
}, []);
|
|
1990
|
+
}, [sessionId, userLang]);
|
|
1973
1991
|
|
|
1974
1992
|
const onClickStart = useCallback(
|
|
1975
1993
|
async (session?: { dialogState: DialogState; sessionID: string }) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { difference } from './utils';
|
|
1
|
+
import { difference, stripEmojis } from './utils';
|
|
2
2
|
|
|
3
3
|
describe('Utils/difference', () => {
|
|
4
4
|
it('should return the difference between two objects with numeric values', () => {
|
|
@@ -29,3 +29,17 @@ describe('Utils/difference', () => {
|
|
|
29
29
|
expect(result).toEqual({ a: ['alpha', 'beta', 'gamma'] });
|
|
30
30
|
});
|
|
31
31
|
});
|
|
32
|
+
|
|
33
|
+
describe('utils/stripEmojis', () => {
|
|
34
|
+
it('should strip emojis from a string', () => {
|
|
35
|
+
const text = 'Hello ððŧ';
|
|
36
|
+
const result = stripEmojis(text);
|
|
37
|
+
expect(result).toEqual('Hello');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should strip emojis from a string with multiple emojis', () => {
|
|
41
|
+
const text = 'ð Hello ððĪŠâĨïļ';
|
|
42
|
+
const result = stripEmojis(text);
|
|
43
|
+
expect(result).toEqual('Hello');
|
|
44
|
+
});
|
|
45
|
+
});
|
package/src/helpers/utils.ts
CHANGED
|
@@ -106,6 +106,10 @@ export const stripDuplicates = (text: string) => {
|
|
|
106
106
|
return text;
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
+
export const stripEmojis = (text: string) => {
|
|
110
|
+
return text.replaceAll(/[^\p{L}\p{N}\p{P}\p{Z}^$\n]/gu, '').trim();
|
|
111
|
+
};
|
|
112
|
+
|
|
109
113
|
export const getFieldFromCustomData = (
|
|
110
114
|
fieldName: string,
|
|
111
115
|
data: string | undefined
|