@memori.ai/memori-react 8.8.2 → 8.8.4

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/components/Header/Header.d.ts +3 -0
  3. package/dist/components/Header/Header.js +31 -17
  4. package/dist/components/Header/Header.js.map +1 -1
  5. package/dist/components/MediaWidget/MediaItemWidget.css +216 -39
  6. package/dist/components/MediaWidget/MediaItemWidget.js +10 -0
  7. package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
  8. package/dist/components/MemoriWidget/MemoriWidget.js +28 -45
  9. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  10. package/dist/components/Snippet/Snippet.css +89 -13
  11. package/dist/components/Snippet/Snippet.js +46 -27
  12. package/dist/components/Snippet/Snippet.js.map +1 -1
  13. package/dist/helpers/tts/useTTS.js +15 -5
  14. package/dist/helpers/tts/useTTS.js.map +1 -1
  15. package/esm/components/Header/Header.d.ts +3 -0
  16. package/esm/components/Header/Header.js +32 -18
  17. package/esm/components/Header/Header.js.map +1 -1
  18. package/esm/components/MediaWidget/MediaItemWidget.css +216 -39
  19. package/esm/components/MediaWidget/MediaItemWidget.js +10 -0
  20. package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
  21. package/esm/components/MemoriWidget/MemoriWidget.js +28 -45
  22. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  23. package/esm/components/Snippet/Snippet.css +89 -13
  24. package/esm/components/Snippet/Snippet.js +46 -27
  25. package/esm/components/Snippet/Snippet.js.map +1 -1
  26. package/esm/helpers/tts/useTTS.js +15 -5
  27. package/esm/helpers/tts/useTTS.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/components/Header/Header.tsx +58 -30
  30. package/src/components/Header/__snapshots__/Header.test.tsx.snap +0 -20
  31. package/src/components/MediaWidget/MediaItemWidget.css +216 -39
  32. package/src/components/MediaWidget/MediaItemWidget.stories.tsx +145 -58
  33. package/src/components/MediaWidget/MediaItemWidget.tsx +24 -1
  34. package/src/components/MediaWidget/__snapshots__/MediaItemWidget.test.tsx.snap +76 -12
  35. package/src/components/MemoriWidget/MemoriWidget.tsx +52 -78
  36. package/src/components/Snippet/Snippet.css +89 -13
  37. package/src/components/Snippet/Snippet.tsx +60 -28
  38. package/src/components/Snippet/__snapshots__/Snippet.test.tsx.snap +9 -0
  39. package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +0 -20
  40. package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +0 -40
  41. package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +0 -20
  42. package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +0 -20
  43. package/src/helpers/tts/useTTS.ts +23 -8
@@ -1,35 +1,111 @@
1
+ .memori-snippet {
2
+ position: relative;
3
+ overflow: hidden;
4
+ border: 1px solid #e5e7eb;
5
+ border-radius: 0.5rem;
6
+ background: #f8fafc;
7
+ }
8
+
1
9
  .memori-snippet--content {
2
10
  position: relative;
11
+ display: flex;
12
+ flex-direction: column;
13
+ }
14
+
15
+ .memori-snippet pre {
16
+ padding: 1rem;
17
+ border: none;
18
+ border-radius: 0;
19
+ margin: 0;
20
+ background: transparent;
21
+ font-family: 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
22
+ font-size: 0.875rem;
23
+ line-height: 1.6;
24
+ overflow-x: auto;
25
+ }
26
+
27
+ .memori-snippet code {
28
+ padding: 0;
29
+ border-radius: 0;
30
+ background: transparent;
31
+ color: #374151;
32
+ font-family: inherit;
3
33
  }
4
34
 
5
35
  button.memori-snippet--copy-button {
6
36
  position: absolute;
7
- top: 5px;
8
- right: 2px;
9
- bottom: 5px;
10
- width: 30px !important;
11
- height: calc(100% - 10px) !important;
37
+ z-index: 10;
38
+ top: 0.5rem;
39
+ right: 0.5rem;
40
+ width: 32px !important;
41
+ height: 32px !important;
12
42
  padding: 0;
13
- border-radius: 5px !important;
14
- background: #333;
43
+ border: 1px solid rgba(0, 0, 0, 0.1);
44
+ border-radius: 6px !important;
45
+ background: rgba(0, 0, 0, 0.05);
46
+ transition: all 0.2s ease;
15
47
  }
16
48
 
17
49
  button.memori-snippet--copy-button:hover,
18
50
  button.memori-snippet--copy-button:focus {
19
- background: #444;
51
+ border-color: rgba(0, 0, 0, 0.2);
52
+ background: rgba(0, 0, 0, 0.1);
53
+ transform: scale(1.05);
20
54
  }
21
55
 
22
56
  button.memori-snippet--copy-button:active {
23
- background: #666;
57
+ background: rgba(0, 0, 0, 0.15);
58
+ transform: scale(0.95);
24
59
  }
25
60
 
26
61
  button.memori-snippet--copy-button svg {
27
- color: #fff;
62
+ width: 14px;
63
+ height: 14px;
64
+ color: #6b7280;
28
65
  }
29
66
 
30
67
  .memori-snippet--caption {
31
68
  width: 100%;
32
- margin-bottom: 1rem;
33
- font-style: italic;
34
- text-align: center;
69
+ padding: 0.75rem 1rem;
70
+ border-top: 1px solid rgba(0, 0, 0, 0.05);
71
+ margin: 0;
72
+ background: rgba(0, 0, 0, 0.02);
73
+ color: #6b7280;
74
+ font-size: 0.8rem;
75
+ font-style: normal;
76
+ font-weight: 500;
77
+ text-align: left;
78
+ }
79
+
80
+ /* Dark theme support */
81
+ @media (prefers-color-scheme: dark) {
82
+ .memori-snippet {
83
+ border-color: #374151;
84
+ background: #1e1e1e;
85
+ }
86
+
87
+ .memori-snippet code {
88
+ color: #e5e7eb;
89
+ }
90
+
91
+ .memori-snippet--copy-button {
92
+ border-color: rgba(255, 255, 255, 0.2);
93
+ background: rgba(255, 255, 255, 0.1);
94
+ }
95
+
96
+ .memori-snippet--copy-button:hover,
97
+ .memori-snippet--copy-button:focus {
98
+ border-color: rgba(255, 255, 255, 0.3);
99
+ background: rgba(255, 255, 255, 0.2);
100
+ }
101
+
102
+ .memori-snippet--copy-button svg {
103
+ color: #fff;
104
+ }
105
+
106
+ .memori-snippet--caption {
107
+ border-top-color: rgba(255, 255, 255, 0.1);
108
+ background: rgba(0, 0, 0, 0.1);
109
+ color: #ccc;
110
+ }
35
111
  }
@@ -13,32 +13,47 @@ export interface Props {
13
13
  showCopyButton?: boolean;
14
14
  }
15
15
 
16
- const loadPrismScripts = () => {
17
- const existingScript = document.getElementById('memori-prism-script');
18
- if (existingScript) {
19
- return;
20
- }
16
+ const loadPrismScripts = (): Promise<void> => {
17
+ return new Promise((resolve) => {
18
+ const existingScript = document.getElementById('memori-prism-script');
19
+ if (existingScript) {
20
+ resolve();
21
+ return;
22
+ }
21
23
 
22
- const script = document.createElement('script');
23
- script.src = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js';
24
- script.async = true;
25
- script.id = 'memori-prism-script';
24
+ const script = document.createElement('script');
25
+ script.src = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js';
26
+ script.async = true;
27
+ script.id = 'memori-prism-script';
28
+ script.onload = () => {
29
+ // Load autoloader after main Prism script is loaded
30
+ const autoloaderScript = document.createElement('script');
31
+ autoloaderScript.src =
32
+ 'https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/plugins/autoloader/prism-autoloader.min.js';
33
+ autoloaderScript.async = true;
34
+ autoloaderScript.id = 'memori-prism-autoloader-script';
35
+ autoloaderScript.onload = () => {
36
+ // Configure autoloader to use the same CDN
37
+ // @ts-ignore
38
+ // eslint-disable-next-line no-undef
39
+ if (window.Prism && window.Prism.plugins && window.Prism.plugins.autoloader) {
40
+ // @ts-ignore
41
+ // eslint-disable-next-line no-undef
42
+ window.Prism.plugins.autoloader.languages_path = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/';
43
+ }
44
+ resolve();
45
+ };
46
+ document.head.appendChild(autoloaderScript);
47
+ };
26
48
 
27
- const autoloaderScript = document.createElement('script');
28
- autoloaderScript.src =
29
- 'https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/plugins/autoloader/prism-autoloader.min.js';
30
- autoloaderScript.async = true;
31
- autoloaderScript.id = 'memori-prism-autoloader-script';
49
+ const prismCss = document.createElement('link');
50
+ prismCss.rel = 'stylesheet';
51
+ prismCss.href =
52
+ 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-tomorrow.min.css';
32
53
 
33
- const prismCss = document.createElement('link');
34
- prismCss.rel = 'stylesheet';
35
- prismCss.href =
36
- 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-tomorrow.min.css';
37
-
38
- document.head.appendChild(prismCss);
39
-
40
- document.head.appendChild(script);
41
- document.head.appendChild(autoloaderScript);
54
+ document.head.appendChild(prismCss);
55
+ document.head.appendChild(script);
56
+ });
42
57
  };
43
58
 
44
59
  const Snippet = ({
@@ -49,15 +64,28 @@ const Snippet = ({
49
64
  }: Props) => {
50
65
  const { t } = useTranslation();
51
66
 
67
+ const highlightCode = () => {
68
+ // @ts-ignore
69
+ // eslint-disable-next-line no-undef
70
+ if ('Prism' in window && window.Prism.highlightAll) {
71
+ // Small delay to ensure DOM is updated
72
+ setTimeout(() => {
73
+ // @ts-ignore
74
+ // eslint-disable-next-line no-undef
75
+ Prism.highlightAll();
76
+ }, 100);
77
+ }
78
+ };
79
+
52
80
  useEffect(() => {
53
- loadPrismScripts();
81
+ loadPrismScripts().then(() => {
82
+ highlightCode();
83
+ });
54
84
  }, []);
55
85
 
56
86
  useEffect(() => {
57
- // @ts-ignore
58
- // eslint-disable-next-line no-undef
59
- if ('Prism' in window && window.Prism.highlightAll) Prism.highlightAll();
60
- }, [medium.content]);
87
+ highlightCode();
88
+ }, [medium.content, medium.mimeType]);
61
89
 
62
90
  return (
63
91
  <div className="memori-snippet">
@@ -73,6 +101,10 @@ const Snippet = ({
73
101
  prismSyntaxLangs.find(l => medium.mimeType === l.mimeType)
74
102
  ?.lang ?? 'text'
75
103
  }`}
104
+ data-language={
105
+ prismSyntaxLangs.find(l => medium.mimeType === l.mimeType)
106
+ ?.lang ?? 'text'
107
+ }
76
108
  >
77
109
  {medium.content?.length && medium.content.length > 200 && preview
78
110
  ? `${medium.content.slice(0, 200)}\n...`
@@ -14,6 +14,7 @@ exports[`renders SnippetUpload with css code 1`] = `
14
14
  >
15
15
  <code
16
16
  class="language-scss"
17
+ data-language="scss"
17
18
  >
18
19
  body {
19
20
  background-color: #f00;
@@ -78,6 +79,7 @@ exports[`renders SnippetUpload with html code 1`] = `
78
79
  >
79
80
  <code
80
81
  class="language-tsx"
82
+ data-language="tsx"
81
83
  >
82
84
  &lt;p&gt;ciao&lt;/p&gt;
83
85
  </code>
@@ -140,6 +142,7 @@ exports[`renders SnippetUpload with js code 1`] = `
140
142
  >
141
143
  <code
142
144
  class="language-jsx"
145
+ data-language="jsx"
143
146
  >
144
147
  console.log("Hello World!");
145
148
  </code>
@@ -202,6 +205,7 @@ exports[`renders SnippetUpload with js code without copy button 1`] = `
202
205
  >
203
206
  <code
204
207
  class="language-jsx"
208
+ data-language="jsx"
205
209
  >
206
210
  console.log("Hello World!");
207
211
  </code>
@@ -231,6 +235,7 @@ exports[`renders SnippetUpload with js code without line numbers 1`] = `
231
235
  >
232
236
  <code
233
237
  class="language-jsx"
238
+ data-language="jsx"
234
239
  >
235
240
  console.log("Hello World!");
236
241
  </code>
@@ -293,6 +298,7 @@ exports[`renders SnippetUpload with preview mode (clamping) 1`] = `
293
298
  >
294
299
  <code
295
300
  class="language-jsx"
301
+ data-language="jsx"
296
302
  >
297
303
 
298
304
  import type { Medium } from 'types';
@@ -360,6 +366,7 @@ exports[`renders SnippetUpload with react/tsx code 1`] = `
360
366
  >
361
367
  <code
362
368
  class="language-jsx"
369
+ data-language="jsx"
363
370
  >
364
371
 
365
372
  import type { Medium } from 'types';
@@ -466,6 +473,7 @@ exports[`renders SnippetUpload with text 1`] = `
466
473
  >
467
474
  <code
468
475
  class="language-text"
476
+ data-language="text"
469
477
  >
470
478
  &lt;p&gt;ciao&lt;/p&gt;
471
479
  </code>
@@ -528,6 +536,7 @@ exports[`renders SnippetUpload with text as fallback 1`] = `
528
536
  >
529
537
  <code
530
538
  class="language-text"
539
+ data-language="text"
531
540
  >
532
541
  &lt;p&gt;ciao&lt;/p&gt;
533
542
  </code>
@@ -86,26 +86,6 @@ exports[`renders Chat layout unchanged 1`] = `
86
86
  </svg>
87
87
  </span>
88
88
  </button>
89
- <button
90
- class="memori-button memori-button--primary memori-button--circle memori-button--padded memori-button--icon-only memori-header--button memori-header--button-settings"
91
- title="Impostazioni"
92
- >
93
- <span
94
- class="memori-button--icon"
95
- >
96
- <svg
97
- aria-hidden="true"
98
- focusable="false"
99
- role="img"
100
- viewBox="0 0 1024 1024"
101
- xmlns="http://www.w3.org/2000/svg"
102
- >
103
- <path
104
- d="M924.8 625.7l-65.5-56c3.1-19 4.7-38.4 4.7-57.8s-1.6-38.8-4.7-57.8l65.5-56a32.03 32.03 0 009.3-35.2l-.9-2.6a443.74 443.74 0 00-79.7-137.9l-1.8-2.1a32.12 32.12 0 00-35.1-9.5l-81.3 28.9c-30-24.6-63.5-44-99.7-57.6l-15.7-85a32.05 32.05 0 00-25.8-25.7l-2.7-.5c-52.1-9.4-106.9-9.4-159 0l-2.7.5a32.05 32.05 0 00-25.8 25.7l-15.8 85.4a351.86 351.86 0 00-99 57.4l-81.9-29.1a32 32 0 00-35.1 9.5l-1.8 2.1a446.02 446.02 0 00-79.7 137.9l-.9 2.6c-4.5 12.5-.8 26.5 9.3 35.2l66.3 56.6c-3.1 18.8-4.6 38-4.6 57.1 0 19.2 1.5 38.4 4.6 57.1L99 625.5a32.03 32.03 0 00-9.3 35.2l.9 2.6c18.1 50.4 44.9 96.9 79.7 137.9l1.8 2.1a32.12 32.12 0 0035.1 9.5l81.9-29.1c29.8 24.5 63.1 43.9 99 57.4l15.8 85.4a32.05 32.05 0 0025.8 25.7l2.7.5a449.4 449.4 0 00159 0l2.7-.5a32.05 32.05 0 0025.8-25.7l15.7-85a350 350 0 0099.7-57.6l81.3 28.9a32 32 0 0035.1-9.5l1.8-2.1c34.8-41.1 61.6-87.5 79.7-137.9l.9-2.6c4.5-12.3.8-26.3-9.3-35zM788.3 465.9c2.5 15.1 3.8 30.6 3.8 46.1s-1.3 31-3.8 46.1l-6.6 40.1 74.7 63.9a370.03 370.03 0 01-42.6 73.6L721 702.8l-31.4 25.8c-23.9 19.6-50.5 35-79.3 45.8l-38.1 14.3-17.9 97a377.5 377.5 0 01-85 0l-17.9-97.2-37.8-14.5c-28.5-10.8-55-26.2-78.7-45.7l-31.4-25.9-93.4 33.2c-17-22.9-31.2-47.6-42.6-73.6l75.5-64.5-6.5-40c-2.4-14.9-3.7-30.3-3.7-45.5 0-15.3 1.2-30.6 3.7-45.5l6.5-40-75.5-64.5c11.3-26.1 25.6-50.7 42.6-73.6l93.4 33.2 31.4-25.9c23.7-19.5 50.2-34.9 78.7-45.7l37.9-14.3 17.9-97.2c28.1-3.2 56.8-3.2 85 0l17.9 97 38.1 14.3c28.7 10.8 55.4 26.2 79.3 45.8l31.4 25.8 92.8-32.9c17 22.9 31.2 47.6 42.6 73.6L781.8 426l6.5 39.9zM512 326c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm79.2 255.2A111.6 111.6 0 01512 614c-29.9 0-58-11.7-79.2-32.8A111.6 111.6 0 01400 502c0-29.9 11.7-58 32.8-79.2C454 401.6 482.1 390 512 390c29.9 0 58 11.6 79.2 32.8A111.6 111.6 0 01624 502c0 29.9-11.7 58-32.8 79.2z"
105
- />
106
- </svg>
107
- </span>
108
- </button>
109
89
  <div
110
90
  class="memori-share-button memori-share-button--align-left"
111
91
  data-headlessui-state=""
@@ -64,26 +64,6 @@ exports[`renders FullPage layout unchanged 1`] = `
64
64
  </svg>
65
65
  </span>
66
66
  </button>
67
- <button
68
- class="memori-button memori-button--primary memori-button--circle memori-button--padded memori-button--icon-only memori-header--button memori-header--button-settings"
69
- title="Impostazioni"
70
- >
71
- <span
72
- class="memori-button--icon"
73
- >
74
- <svg
75
- aria-hidden="true"
76
- focusable="false"
77
- role="img"
78
- viewBox="0 0 1024 1024"
79
- xmlns="http://www.w3.org/2000/svg"
80
- >
81
- <path
82
- d="M924.8 625.7l-65.5-56c3.1-19 4.7-38.4 4.7-57.8s-1.6-38.8-4.7-57.8l65.5-56a32.03 32.03 0 009.3-35.2l-.9-2.6a443.74 443.74 0 00-79.7-137.9l-1.8-2.1a32.12 32.12 0 00-35.1-9.5l-81.3 28.9c-30-24.6-63.5-44-99.7-57.6l-15.7-85a32.05 32.05 0 00-25.8-25.7l-2.7-.5c-52.1-9.4-106.9-9.4-159 0l-2.7.5a32.05 32.05 0 00-25.8 25.7l-15.8 85.4a351.86 351.86 0 00-99 57.4l-81.9-29.1a32 32 0 00-35.1 9.5l-1.8 2.1a446.02 446.02 0 00-79.7 137.9l-.9 2.6c-4.5 12.5-.8 26.5 9.3 35.2l66.3 56.6c-3.1 18.8-4.6 38-4.6 57.1 0 19.2 1.5 38.4 4.6 57.1L99 625.5a32.03 32.03 0 00-9.3 35.2l.9 2.6c18.1 50.4 44.9 96.9 79.7 137.9l1.8 2.1a32.12 32.12 0 0035.1 9.5l81.9-29.1c29.8 24.5 63.1 43.9 99 57.4l15.8 85.4a32.05 32.05 0 0025.8 25.7l2.7.5a449.4 449.4 0 00159 0l2.7-.5a32.05 32.05 0 0025.8-25.7l15.7-85a350 350 0 0099.7-57.6l81.3 28.9a32 32 0 0035.1-9.5l1.8-2.1c34.8-41.1 61.6-87.5 79.7-137.9l.9-2.6c4.5-12.3.8-26.3-9.3-35zM788.3 465.9c2.5 15.1 3.8 30.6 3.8 46.1s-1.3 31-3.8 46.1l-6.6 40.1 74.7 63.9a370.03 370.03 0 01-42.6 73.6L721 702.8l-31.4 25.8c-23.9 19.6-50.5 35-79.3 45.8l-38.1 14.3-17.9 97a377.5 377.5 0 01-85 0l-17.9-97.2-37.8-14.5c-28.5-10.8-55-26.2-78.7-45.7l-31.4-25.9-93.4 33.2c-17-22.9-31.2-47.6-42.6-73.6l75.5-64.5-6.5-40c-2.4-14.9-3.7-30.3-3.7-45.5 0-15.3 1.2-30.6 3.7-45.5l6.5-40-75.5-64.5c11.3-26.1 25.6-50.7 42.6-73.6l93.4 33.2 31.4-25.9c23.7-19.5 50.2-34.9 78.7-45.7l37.9-14.3 17.9-97.2c28.1-3.2 56.8-3.2 85 0l17.9 97 38.1 14.3c28.7 10.8 55.4 26.2 79.3 45.8l31.4 25.8 92.8-32.9c17 22.9 31.2 47.6 42.6 73.6L781.8 426l6.5 39.9zM512 326c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm79.2 255.2A111.6 111.6 0 01512 614c-29.9 0-58-11.7-79.2-32.8A111.6 111.6 0 01400 502c0-29.9 11.7-58 32.8-79.2C454 401.6 482.1 390 512 390c29.9 0 58 11.6 79.2 32.8A111.6 111.6 0 01624 502c0 29.9-11.7 58-32.8 79.2z"
83
- />
84
- </svg>
85
- </span>
86
- </button>
87
67
  <div
88
68
  class="memori-share-button memori-share-button--align-left"
89
69
  data-headlessui-state=""
@@ -601,26 +581,6 @@ exports[`renders FullPage layout with root css properties unchanged 1`] = `
601
581
  </svg>
602
582
  </span>
603
583
  </button>
604
- <button
605
- class="memori-button memori-button--primary memori-button--circle memori-button--padded memori-button--icon-only memori-header--button memori-header--button-settings"
606
- title="Impostazioni"
607
- >
608
- <span
609
- class="memori-button--icon"
610
- >
611
- <svg
612
- aria-hidden="true"
613
- focusable="false"
614
- role="img"
615
- viewBox="0 0 1024 1024"
616
- xmlns="http://www.w3.org/2000/svg"
617
- >
618
- <path
619
- d="M924.8 625.7l-65.5-56c3.1-19 4.7-38.4 4.7-57.8s-1.6-38.8-4.7-57.8l65.5-56a32.03 32.03 0 009.3-35.2l-.9-2.6a443.74 443.74 0 00-79.7-137.9l-1.8-2.1a32.12 32.12 0 00-35.1-9.5l-81.3 28.9c-30-24.6-63.5-44-99.7-57.6l-15.7-85a32.05 32.05 0 00-25.8-25.7l-2.7-.5c-52.1-9.4-106.9-9.4-159 0l-2.7.5a32.05 32.05 0 00-25.8 25.7l-15.8 85.4a351.86 351.86 0 00-99 57.4l-81.9-29.1a32 32 0 00-35.1 9.5l-1.8 2.1a446.02 446.02 0 00-79.7 137.9l-.9 2.6c-4.5 12.5-.8 26.5 9.3 35.2l66.3 56.6c-3.1 18.8-4.6 38-4.6 57.1 0 19.2 1.5 38.4 4.6 57.1L99 625.5a32.03 32.03 0 00-9.3 35.2l.9 2.6c18.1 50.4 44.9 96.9 79.7 137.9l1.8 2.1a32.12 32.12 0 0035.1 9.5l81.9-29.1c29.8 24.5 63.1 43.9 99 57.4l15.8 85.4a32.05 32.05 0 0025.8 25.7l2.7.5a449.4 449.4 0 00159 0l2.7-.5a32.05 32.05 0 0025.8-25.7l15.7-85a350 350 0 0099.7-57.6l81.3 28.9a32 32 0 0035.1-9.5l1.8-2.1c34.8-41.1 61.6-87.5 79.7-137.9l.9-2.6c4.5-12.3.8-26.3-9.3-35zM788.3 465.9c2.5 15.1 3.8 30.6 3.8 46.1s-1.3 31-3.8 46.1l-6.6 40.1 74.7 63.9a370.03 370.03 0 01-42.6 73.6L721 702.8l-31.4 25.8c-23.9 19.6-50.5 35-79.3 45.8l-38.1 14.3-17.9 97a377.5 377.5 0 01-85 0l-17.9-97.2-37.8-14.5c-28.5-10.8-55-26.2-78.7-45.7l-31.4-25.9-93.4 33.2c-17-22.9-31.2-47.6-42.6-73.6l75.5-64.5-6.5-40c-2.4-14.9-3.7-30.3-3.7-45.5 0-15.3 1.2-30.6 3.7-45.5l6.5-40-75.5-64.5c11.3-26.1 25.6-50.7 42.6-73.6l93.4 33.2 31.4-25.9c23.7-19.5 50.2-34.9 78.7-45.7l37.9-14.3 17.9-97.2c28.1-3.2 56.8-3.2 85 0l17.9 97 38.1 14.3c28.7 10.8 55.4 26.2 79.3 45.8l31.4 25.8 92.8-32.9c17 22.9 31.2 47.6 42.6 73.6L781.8 426l6.5 39.9zM512 326c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm79.2 255.2A111.6 111.6 0 01512 614c-29.9 0-58-11.7-79.2-32.8A111.6 111.6 0 01400 502c0-29.9 11.7-58 32.8-79.2C454 401.6 482.1 390 512 390c29.9 0 58 11.6 79.2 32.8A111.6 111.6 0 01624 502c0 29.9-11.7 58-32.8 79.2z"
620
- />
621
- </svg>
622
- </span>
623
- </button>
624
584
  <div
625
585
  class="memori-share-button memori-share-button--align-left"
626
586
  data-headlessui-state=""
@@ -103,26 +103,6 @@ exports[`renders HIDDEN_CHAT layout unchanged 1`] = `
103
103
  </svg>
104
104
  </span>
105
105
  </button>
106
- <button
107
- class="memori-button memori-button--primary memori-button--circle memori-button--padded memori-button--icon-only memori-header--button memori-header--button-settings"
108
- title="Impostazioni"
109
- >
110
- <span
111
- class="memori-button--icon"
112
- >
113
- <svg
114
- aria-hidden="true"
115
- focusable="false"
116
- role="img"
117
- viewBox="0 0 1024 1024"
118
- xmlns="http://www.w3.org/2000/svg"
119
- >
120
- <path
121
- d="M924.8 625.7l-65.5-56c3.1-19 4.7-38.4 4.7-57.8s-1.6-38.8-4.7-57.8l65.5-56a32.03 32.03 0 009.3-35.2l-.9-2.6a443.74 443.74 0 00-79.7-137.9l-1.8-2.1a32.12 32.12 0 00-35.1-9.5l-81.3 28.9c-30-24.6-63.5-44-99.7-57.6l-15.7-85a32.05 32.05 0 00-25.8-25.7l-2.7-.5c-52.1-9.4-106.9-9.4-159 0l-2.7.5a32.05 32.05 0 00-25.8 25.7l-15.8 85.4a351.86 351.86 0 00-99 57.4l-81.9-29.1a32 32 0 00-35.1 9.5l-1.8 2.1a446.02 446.02 0 00-79.7 137.9l-.9 2.6c-4.5 12.5-.8 26.5 9.3 35.2l66.3 56.6c-3.1 18.8-4.6 38-4.6 57.1 0 19.2 1.5 38.4 4.6 57.1L99 625.5a32.03 32.03 0 00-9.3 35.2l.9 2.6c18.1 50.4 44.9 96.9 79.7 137.9l1.8 2.1a32.12 32.12 0 0035.1 9.5l81.9-29.1c29.8 24.5 63.1 43.9 99 57.4l15.8 85.4a32.05 32.05 0 0025.8 25.7l2.7.5a449.4 449.4 0 00159 0l2.7-.5a32.05 32.05 0 0025.8-25.7l15.7-85a350 350 0 0099.7-57.6l81.3 28.9a32 32 0 0035.1-9.5l1.8-2.1c34.8-41.1 61.6-87.5 79.7-137.9l.9-2.6c4.5-12.3.8-26.3-9.3-35zM788.3 465.9c2.5 15.1 3.8 30.6 3.8 46.1s-1.3 31-3.8 46.1l-6.6 40.1 74.7 63.9a370.03 370.03 0 01-42.6 73.6L721 702.8l-31.4 25.8c-23.9 19.6-50.5 35-79.3 45.8l-38.1 14.3-17.9 97a377.5 377.5 0 01-85 0l-17.9-97.2-37.8-14.5c-28.5-10.8-55-26.2-78.7-45.7l-31.4-25.9-93.4 33.2c-17-22.9-31.2-47.6-42.6-73.6l75.5-64.5-6.5-40c-2.4-14.9-3.7-30.3-3.7-45.5 0-15.3 1.2-30.6 3.7-45.5l6.5-40-75.5-64.5c11.3-26.1 25.6-50.7 42.6-73.6l93.4 33.2 31.4-25.9c23.7-19.5 50.2-34.9 78.7-45.7l37.9-14.3 17.9-97.2c28.1-3.2 56.8-3.2 85 0l17.9 97 38.1 14.3c28.7 10.8 55.4 26.2 79.3 45.8l31.4 25.8 92.8-32.9c17 22.9 31.2 47.6 42.6 73.6L781.8 426l6.5 39.9zM512 326c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm79.2 255.2A111.6 111.6 0 01512 614c-29.9 0-58-11.7-79.2-32.8A111.6 111.6 0 01400 502c0-29.9 11.7-58 32.8-79.2C454 401.6 482.1 390 512 390c29.9 0 58 11.6 79.2 32.8A111.6 111.6 0 01624 502c0 29.9-11.7 58-32.8 79.2z"
122
- />
123
- </svg>
124
- </span>
125
- </button>
126
106
  <div
127
107
  class="memori-share-button memori-share-button--align-left"
128
108
  data-headlessui-state=""
@@ -64,26 +64,6 @@ exports[`renders ZOOMED_FULL_BODY layout unchanged 1`] = `
64
64
  </svg>
65
65
  </span>
66
66
  </button>
67
- <button
68
- class="memori-button memori-button--primary memori-button--circle memori-button--padded memori-button--icon-only memori-header--button memori-header--button-settings"
69
- title="Impostazioni"
70
- >
71
- <span
72
- class="memori-button--icon"
73
- >
74
- <svg
75
- aria-hidden="true"
76
- focusable="false"
77
- role="img"
78
- viewBox="0 0 1024 1024"
79
- xmlns="http://www.w3.org/2000/svg"
80
- >
81
- <path
82
- d="M924.8 625.7l-65.5-56c3.1-19 4.7-38.4 4.7-57.8s-1.6-38.8-4.7-57.8l65.5-56a32.03 32.03 0 009.3-35.2l-.9-2.6a443.74 443.74 0 00-79.7-137.9l-1.8-2.1a32.12 32.12 0 00-35.1-9.5l-81.3 28.9c-30-24.6-63.5-44-99.7-57.6l-15.7-85a32.05 32.05 0 00-25.8-25.7l-2.7-.5c-52.1-9.4-106.9-9.4-159 0l-2.7.5a32.05 32.05 0 00-25.8 25.7l-15.8 85.4a351.86 351.86 0 00-99 57.4l-81.9-29.1a32 32 0 00-35.1 9.5l-1.8 2.1a446.02 446.02 0 00-79.7 137.9l-.9 2.6c-4.5 12.5-.8 26.5 9.3 35.2l66.3 56.6c-3.1 18.8-4.6 38-4.6 57.1 0 19.2 1.5 38.4 4.6 57.1L99 625.5a32.03 32.03 0 00-9.3 35.2l.9 2.6c18.1 50.4 44.9 96.9 79.7 137.9l1.8 2.1a32.12 32.12 0 0035.1 9.5l81.9-29.1c29.8 24.5 63.1 43.9 99 57.4l15.8 85.4a32.05 32.05 0 0025.8 25.7l2.7.5a449.4 449.4 0 00159 0l2.7-.5a32.05 32.05 0 0025.8-25.7l15.7-85a350 350 0 0099.7-57.6l81.3 28.9a32 32 0 0035.1-9.5l1.8-2.1c34.8-41.1 61.6-87.5 79.7-137.9l.9-2.6c4.5-12.3.8-26.3-9.3-35zM788.3 465.9c2.5 15.1 3.8 30.6 3.8 46.1s-1.3 31-3.8 46.1l-6.6 40.1 74.7 63.9a370.03 370.03 0 01-42.6 73.6L721 702.8l-31.4 25.8c-23.9 19.6-50.5 35-79.3 45.8l-38.1 14.3-17.9 97a377.5 377.5 0 01-85 0l-17.9-97.2-37.8-14.5c-28.5-10.8-55-26.2-78.7-45.7l-31.4-25.9-93.4 33.2c-17-22.9-31.2-47.6-42.6-73.6l75.5-64.5-6.5-40c-2.4-14.9-3.7-30.3-3.7-45.5 0-15.3 1.2-30.6 3.7-45.5l6.5-40-75.5-64.5c11.3-26.1 25.6-50.7 42.6-73.6l93.4 33.2 31.4-25.9c23.7-19.5 50.2-34.9 78.7-45.7l37.9-14.3 17.9-97.2c28.1-3.2 56.8-3.2 85 0l17.9 97 38.1 14.3c28.7 10.8 55.4 26.2 79.3 45.8l31.4 25.8 92.8-32.9c17 22.9 31.2 47.6 42.6 73.6L781.8 426l6.5 39.9zM512 326c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm79.2 255.2A111.6 111.6 0 01512 614c-29.9 0-58-11.7-79.2-32.8A111.6 111.6 0 01400 502c0-29.9 11.7-58 32.8-79.2C454 401.6 482.1 390 512 390c29.9 0 58 11.6 79.2 32.8A111.6 111.6 0 01624 502c0 29.9-11.7 58-32.8 79.2z"
83
- />
84
- </svg>
85
- </span>
86
- </button>
87
67
  <div
88
68
  class="memori-share-button memori-share-button--align-left"
89
69
  data-headlessui-state=""
@@ -59,11 +59,24 @@ export function useTTS(
59
59
  !defaultEnableAudio || !defaultSpeakerActive || autoStart
60
60
  )
61
61
  );
62
+
62
63
  // Get viseme methods from your context
63
64
  const { addViseme, resetVisemeQueue, startProcessing, stopProcessing } =
64
65
  useViseme();
65
66
  const [hasUserActivatedSpeak, setHasUserActivatedSpeak] = useState(false);
66
67
 
68
+ // Helper function to check if audio should be played
69
+ const shouldPlayAudio = (text?: string) => {
70
+ const currentSpeakerMuted = getLocalConfig('muteSpeaker', false);
71
+ return (
72
+ text &&
73
+ text.trim() &&
74
+ !options.preview &&
75
+ !currentSpeakerMuted &&
76
+ defaultEnableAudio
77
+ );
78
+ };
79
+
67
80
  // Riferimenti
68
81
  const audioRef = useRef<HTMLAudioElement | null>(null);
69
82
  const audioWrapperRef = useRef<SimpleAudioWrapper | null>(null);
@@ -288,6 +301,12 @@ export function useTTS(
288
301
  const audioBlob = await response.blob();
289
302
  const audioUrl = URL.createObjectURL(audioBlob);
290
303
 
304
+ // Check if speaker is muted after receiving TTS result
305
+ if (!shouldPlayAudio(chunkText)) {
306
+ URL.revokeObjectURL(audioUrl);
307
+ return;
308
+ }
309
+
291
310
  // Clean up if speaking was cancelled
292
311
  if (!isSpeakingRef.current || !isMountedRef.current) {
293
312
  URL.revokeObjectURL(audioUrl);
@@ -409,6 +428,7 @@ export function useTTS(
409
428
  startProcessing,
410
429
  isSpeakingRef,
411
430
  isMountedRef,
431
+ speakerMuted,
412
432
  ]
413
433
  );
414
434
 
@@ -422,13 +442,7 @@ export function useTTS(
422
442
  }
423
443
 
424
444
  // Early exit conditions before setting speaking flag
425
- if (!text || !text.trim() || options.preview) {
426
- emitEndSpeakEvent();
427
- return;
428
- }
429
-
430
- // If speaker is muted, completely disable TTS functionality
431
- if (speakerMuted) {
445
+ if (!shouldPlayAudio(text)) {
432
446
  // Still set hasUserActivatedSpeak to true when audio is disabled
433
447
  // so the chat can start properly
434
448
  if (!hasUserActivatedSpeak) {
@@ -493,6 +507,7 @@ export function useTTS(
493
507
  const e = new CustomEvent('MemoriAudioEnded');
494
508
  document.dispatchEvent(e);
495
509
  } catch (err) {
510
+ console.error('[speak] Error during playback:', err);
496
511
  setIsPlaying(false);
497
512
  isSpeakingRef.current = false;
498
513
 
@@ -538,7 +553,7 @@ export function useTTS(
538
553
  stop();
539
554
  }
540
555
 
541
- // ADD: Always clean up viseme state when toggling mute
556
+ // Always clean up viseme state when toggling mute
542
557
  // This ensures fresh start when unmuting
543
558
  if (newMuteState) {
544
559
  resetVisemeQueue();