@chat21/chat21-web-widget 5.1.32-rc1 → 5.1.32-rc14
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 +55 -0
- package/deploy_amazon_beta.sh +17 -7
- package/nginx.conf +22 -2
- package/package.json +1 -1
- package/src/app/app.module.ts +2 -0
- package/src/app/component/conversation-detail/conversation/conversation.component.html +2 -1
- package/src/app/component/conversation-detail/conversation/conversation.component.scss +10 -0
- package/src/app/component/conversation-detail/conversation/conversation.component.ts +13 -1
- package/src/app/component/conversation-detail/conversation-content/conversation-content.component.html +7 -3
- package/src/app/component/conversation-detail/conversation-content/conversation-content.component.scss +18 -0
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +24 -41
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +37 -51
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +37 -26
- package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.html +43 -0
- package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.scss +79 -0
- package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.ts +192 -0
- package/src/app/component/message/audio-sync/audio-sync.component.html +0 -1
- package/src/app/component/message/audio-sync/audio-sync.component.scss +0 -1
- package/src/app/component/message/audio-sync/audio-sync.component.ts +378 -17
- package/src/app/providers/tts-audio-playback-coordinator.service.ts +93 -0
- package/src/app/providers/voice/voice.service.ts +117 -5
- package/src/app/sass/_variables.scss +2 -0
- package/src/launch.js +41 -32
- package/src/launch_template.js +41 -32
- package/deploy_amazon_prod.sh +0 -41
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,61 @@
|
|
|
6
6
|
### **Copyrigth**:
|
|
7
7
|
*Tiledesk SRL*
|
|
8
8
|
|
|
9
|
+
# 5.1.32-rc14
|
|
10
|
+
- **changed**: minor ui fixed
|
|
11
|
+
|
|
12
|
+
# 5.1.32-rc13
|
|
13
|
+
- **added**: VAD speech state events (`speechStart$`, `speechEnd$`) to improve UI/state transitions around user speech
|
|
14
|
+
- **changed**: stream audio footer UI — stream button expands into a “Terminate” pill with animated level bars driven by mic intensity; recorder icon hidden while streaming; textarea width adjusted while streaming
|
|
15
|
+
- **changed**: `StreamAudioSpectrum` — consolidated stream spectrum + stream button visuals into a single component with improved silence vs speaking handling and volume-driven bar heights
|
|
16
|
+
- **changed**: conversation layout while streaming — adjusted received bubble sizing (`fullSizeMessage`) and loading spinner spacing (`fullSize`) for full-width stream mode
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# 5.1.32-rc12
|
|
21
|
+
- **changed**: voice acquisition blocking during TTS response — pause VAD after user speech ends until the TTS response cycle completes; added safety timeout and `isAcquisitionBlocked$` to drive UI (e.g. greyed spectrum)
|
|
22
|
+
- **chore**: version bump to `5.1.32-rc12`
|
|
23
|
+
|
|
24
|
+
# 5.1.32-rc11
|
|
25
|
+
- **added**: global TTS stop — `TtsAudioPlaybackCoordinator.stopAll()` + `stopAllPlayback$` to abort current and queued TTS playback and reveal full message text
|
|
26
|
+
- **changed**: stop TTS playback when closing stream audio
|
|
27
|
+
- **chore**: version bump to `5.1.32-rc11`
|
|
28
|
+
|
|
29
|
+
# 5.1.32-rc10
|
|
30
|
+
- **added**: TTS playback state (`isTTSPlaying$`) to coordinate voice UI and suppress mic segment emission while the bot is speaking
|
|
31
|
+
- **changed**: stream spectrum theme color turns grey while TTS is playing
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# 5.1.32-rc9
|
|
35
|
+
- **added**: mic-triggered TTS interruption — when VAD detects user speech, stop current TTS playback, clear the queue, and reveal the full message text
|
|
36
|
+
- **added**: global TTS stop API (`TtsAudioPlaybackCoordinator.stopAll()` + `stopAllPlayback$`) to stop current + queued TTS playback from UI/events (e.g. close stream)
|
|
37
|
+
- **changed**: `chat-audio-sync` TTS playback now streams audio via authenticated POST to `message.metadata.src`, sending `voiceSettings` + `text` and `streaming: true`
|
|
38
|
+
- **changed**: stream UI spectrum — removed circular orb and stretched the spectrum line to fill the `#streamAudioAlert` width with 10px side padding
|
|
39
|
+
- **changed**: conversation content layout while streaming — adjusted received bubble left margin and loading spinner margins for full-size mode
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# 5.1.32-rc8
|
|
43
|
+
- **changed**: updated the dev environment defaults to align with the stage setup (remote config URL, API endpoints, logging level, storage prefix, and related settings)
|
|
44
|
+
|
|
45
|
+
# 5.1.32-rc7
|
|
46
|
+
- **added**: `StreamAudioSpectrum` component for audio visualization in the streaming footer UI
|
|
47
|
+
- **added**: TTS playback coordinator queue — ensures TTS messages play sequentially without interrupting the previous one
|
|
48
|
+
- **changed**: `chat-audio-sync` — updated TTS audio handling to support streaming playback and improved autoplay/animation timing
|
|
49
|
+
- **changed**: iframe loader (`launch.js`, `launch_template.js`) — streamlined loading logic and improved error handling, with fixes for localhost environments
|
|
50
|
+
|
|
51
|
+
# 5.1.32-rc4
|
|
52
|
+
- **added**: “Close stream” control (`.close-stream-button`) — content and sheet bottom offset in fullscreen using `--chat-footer-stream-button-height` only while the stream is listening (`isStreamAudioActive`); variables in `_variables.scss`.
|
|
53
|
+
- **added**: `VoiceService.discardCurrentRecordingSegment()` — when a message arrives from another sender during streaming, the current WebM segment is discarded (no upload) without stopping mic/VAD; `interruptStreamDueToPeerMessage()` in the footer no longer clears `isStreamAudioActive`.
|
|
54
|
+
- **changed**: `#streamAudioAlert` — band above the footer with a frosted-glass look (`backdrop-filter`, semi-transparent `color-mix`).
|
|
55
|
+
|
|
56
|
+
# 5.1.32-rc3
|
|
57
|
+
- **changed**: `nginx.conf` (Docker image) — explicit MIME types for `.mjs`, `.wasm`, `.onnx` and `default_type` at `http` level (avoids `text/plain` on ONNX/VAD modules behind containerized deploys).
|
|
58
|
+
- **chore**: removed deprecated Amazon beta/prod deploy scripts from the repository.
|
|
59
|
+
|
|
60
|
+
# 5.1.32-rc2
|
|
61
|
+
- **bug fixed**: minor streaming icon UI fixed
|
|
62
|
+
- **changed**: Refactor stream audio button UI in the conversation footer (layout / classes).
|
|
63
|
+
|
|
9
64
|
# 5.1.32-rc1
|
|
10
65
|
- **added**: Voice pipeline — VAD (`@ricky0123/vad-web`) with ONNX Runtime WASM served from `/assets/onnx` (`copy-onnx-wasm`), `VoiceService` with `audioSegment$` (WebM segments) and optional STT/TTS via unified OpenAI provider using `HttpClient`, transcript / error fields on segment payloads.
|
|
11
66
|
- **added**: Stream audio UI in conversation footer — toggle, real-time volume stream and animated waveform (`volume$`); mic session lifecycle wired to upload segments on speech end.
|
package/deploy_amazon_beta.sh
CHANGED
|
@@ -2,8 +2,16 @@
|
|
|
2
2
|
version=`node -e 'console.log(require("./package.json").version)'`
|
|
3
3
|
echo "version $version"
|
|
4
4
|
|
|
5
|
+
npm i
|
|
6
|
+
|
|
7
|
+
cp src/environments/real_data/environment.pre.ts src/environments/environment.pre.ts
|
|
8
|
+
|
|
5
9
|
ng build --configuration="pre" --aot=true --base-href
|
|
6
10
|
|
|
11
|
+
### SET HASHING : START ###
|
|
12
|
+
cp ./src/launch_template.js ./dist/browser/launch.js
|
|
13
|
+
node ./src/build_launch.js
|
|
14
|
+
### SET HASHING : END ###
|
|
7
15
|
|
|
8
16
|
# ########## --->>>> NATIVE-MQTT folder START <<<<<------ ########## #
|
|
9
17
|
|
|
@@ -23,15 +31,17 @@ ng build --configuration="pre" --aot=true --base-href
|
|
|
23
31
|
|
|
24
32
|
|
|
25
33
|
# ########## --->>>> FIREBASE folder START <<<<<------ ########## #
|
|
26
|
-
cd dist
|
|
27
|
-
aws s3 sync . s3://tiledesk-widget-pre/v5/$version/ --cache-control max-age=300
|
|
28
|
-
aws s3 sync . s3://tiledesk-widget-pre/v5/ --cache-control
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
cd ..
|
|
34
|
+
cd dist/browser
|
|
35
|
+
aws s3 sync . s3://tiledesk-widget-pre/v5/$version/ --cache-control max-age=300 --exclude='launch.js' #7days
|
|
36
|
+
aws s3 sync . s3://tiledesk-widget-pre/v5/$version/ --cache-control "no-store,no-cache,private" --exclude='*' --include='launch.js'
|
|
37
|
+
aws s3 sync . s3://tiledesk-widget-pre/v5/ --cache-control max-age=300 --exclude='launch.js' #7days
|
|
38
|
+
aws s3 sync . s3://tiledesk-widget-pre/v5/ --cache-control "no-store,no-cache,private" --exclude='*' --include='launch.js'
|
|
39
|
+
cd ../..
|
|
33
40
|
|
|
34
41
|
aws cloudfront create-invalidation --distribution-id E2V5O0YPR61V8P --paths "/*"
|
|
42
|
+
|
|
43
|
+
git restore src/environments/environment.pre.ts
|
|
44
|
+
|
|
35
45
|
# echo new version deployed $NEW_VER/$NEW_BUILD/ on s3://tiledesk-widget-pre/v2
|
|
36
46
|
echo new version deployed $version/ on s3://tiledesk-widget-pre/v5 and s3://tiledesk-widget-pre/v5/$version/
|
|
37
47
|
echo available on https://s3.eu-west-1.amazonaws.com/tiledesk-widget-pre/v5/index.html
|
package/nginx.conf
CHANGED
|
@@ -5,18 +5,38 @@ events {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
http {
|
|
8
|
+
include /etc/nginx/mime.types;
|
|
9
|
+
default_type application/octet-stream;
|
|
10
|
+
|
|
8
11
|
server {
|
|
9
12
|
listen 80;
|
|
10
13
|
server_name localhost;
|
|
11
14
|
|
|
12
15
|
root /usr/share/nginx/html;
|
|
13
16
|
index index.html index.htm;
|
|
14
|
-
include /etc/nginx/mime.types;
|
|
15
17
|
|
|
16
18
|
gzip on;
|
|
17
19
|
gzip_min_length 1000;
|
|
18
20
|
gzip_proxied expired no-cache no-store private auth;
|
|
19
|
-
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
|
21
|
+
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/wasm;
|
|
22
|
+
|
|
23
|
+
# ONNX Runtime (.mjs), WASM e modelli VAD: il browser rifiuta moduli ES con Content-Type: text/plain
|
|
24
|
+
location ~* \.mjs$ {
|
|
25
|
+
root /usr/share/nginx/html;
|
|
26
|
+
default_type application/javascript;
|
|
27
|
+
charset utf-8;
|
|
28
|
+
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
29
|
+
}
|
|
30
|
+
location ~* \.wasm$ {
|
|
31
|
+
root /usr/share/nginx/html;
|
|
32
|
+
default_type application/wasm;
|
|
33
|
+
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
34
|
+
}
|
|
35
|
+
location ~* \.onnx$ {
|
|
36
|
+
root /usr/share/nginx/html;
|
|
37
|
+
default_type application/octet-stream;
|
|
38
|
+
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
39
|
+
}
|
|
20
40
|
|
|
21
41
|
location / {
|
|
22
42
|
try_files $uri $uri/ /index.html;
|
package/package.json
CHANGED
package/src/app/app.module.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { ConversationFooterComponent } from './component/conversation-detail/con
|
|
|
16
16
|
import { ConversationInternalFrameComponent } from './component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component';
|
|
17
17
|
import { ConversationPreviewComponent } from './component/conversation-detail/conversation-preview/conversation-preview.component';
|
|
18
18
|
import { ConversationAudioRecorderComponent } from './component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component';
|
|
19
|
+
import { StreamAudioSpectrumComponent } from './component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component';
|
|
19
20
|
/** CONVERSATION-DETAIL COMPONENTS */
|
|
20
21
|
import { BubbleMessageComponent } from './component/message/bubble-message/bubble-message.component';
|
|
21
22
|
import { AvatarComponent } from './component/message/avatar/avatar.component';
|
|
@@ -294,6 +295,7 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
|
|
|
294
295
|
ConversationPreviewComponent,
|
|
295
296
|
ConversationInternalFrameComponent,
|
|
296
297
|
ConversationAudioRecorderComponent,
|
|
298
|
+
StreamAudioSpectrumComponent,
|
|
297
299
|
BubbleMessageComponent,
|
|
298
300
|
AvatarComponent,
|
|
299
301
|
FrameComponent,
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
<div id="chat21-conversation-component"
|
|
5
5
|
#afConversationComponent
|
|
6
6
|
tabindex="1500"
|
|
7
|
-
aria-modal="true"
|
|
7
|
+
aria-modal="true"
|
|
8
|
+
[class.chat21-conversation--close-stream-active]="closeStreamButtonActiveForSheetBottom()">
|
|
8
9
|
|
|
9
10
|
<!-- HEADER -->
|
|
10
11
|
<chat-conversation-header
|
|
@@ -242,6 +242,16 @@ dialog:-internal-dialog-in-top-layer{
|
|
|
242
242
|
::ng-deep .chat21-sheet-content{
|
|
243
243
|
bottom: calc(var(--chat-footer-logo-height) + var(--chat-footer-height) + var(--chat-footer-close-button-height) + 34px)!important;
|
|
244
244
|
}
|
|
245
|
+
|
|
246
|
+
/* Con `.close-stream-button` (stream in ascolto): spazio per alert stream sopra il footer */
|
|
247
|
+
#chat21-conversation-component.chat21-conversation--close-stream-active ::ng-deep .chat21-sheet-content {
|
|
248
|
+
bottom: calc(
|
|
249
|
+
var(--chat-footer-logo-height) +
|
|
250
|
+
var(--chat-footer-height) +
|
|
251
|
+
var(--chat-footer-stream-button-height) +
|
|
252
|
+
34px
|
|
253
|
+
) !important;
|
|
254
|
+
}
|
|
245
255
|
|
|
246
256
|
}
|
|
247
257
|
|
|
@@ -251,7 +251,8 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
251
251
|
'EMOJI_NOT_ELLOWED',
|
|
252
252
|
'ATTACHMENT',
|
|
253
253
|
'EMOJI',
|
|
254
|
-
'CLOSE_CHAT'
|
|
254
|
+
'CLOSE_CHAT',
|
|
255
|
+
'CLOSE'
|
|
255
256
|
];
|
|
256
257
|
|
|
257
258
|
const keysContent = [
|
|
@@ -827,6 +828,10 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
827
828
|
this.showThinkingMessage = false;
|
|
828
829
|
}
|
|
829
830
|
|
|
831
|
+
if (this.isStreamAudioActive && msg.sender !== this.senderId) {
|
|
832
|
+
this.conversationFooter?.interruptStreamDueToPeerMessage();
|
|
833
|
+
}
|
|
834
|
+
|
|
830
835
|
that.newMessageAdded(msg);
|
|
831
836
|
// Update badge based on the latest message received from the server.
|
|
832
837
|
// We rely on `messages` being kept in-sync by the conversation handler.
|
|
@@ -1414,6 +1419,13 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
1414
1419
|
}
|
|
1415
1420
|
// =========== END: event emitter function ====== //
|
|
1416
1421
|
|
|
1422
|
+
/**
|
|
1423
|
+
* True quando è visibile il pulsante chiudi stream (`.close-stream-button`, `isStreamAudioActive`).
|
|
1424
|
+
* Solo in quel caso il bottom del foglio include `--chat-footer-stream-button-height`.
|
|
1425
|
+
*/
|
|
1426
|
+
closeStreamButtonActiveForSheetBottom(): boolean {
|
|
1427
|
+
return !!(this.g?.showAudioStreamFooterButton && this.isStreamAudioActive);
|
|
1428
|
+
}
|
|
1417
1429
|
|
|
1418
1430
|
openInputFiles() {
|
|
1419
1431
|
alert('ok');
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
<!-- message RECIPIENT:: -->
|
|
50
50
|
<div role="messaggio" *ngIf="messageType(MESSAGE_TYPE_OTHERS, message)" class="msg_container base_receive">
|
|
51
51
|
|
|
52
|
-
<chat-avatar-image *ngIf="!isSameSender(message?.sender, i)"
|
|
52
|
+
<chat-avatar-image *ngIf="!isSameSender(message?.sender, i) && !isStreamAudioActive"
|
|
53
53
|
[ngClass]="{'slide-in-left': false}"
|
|
54
54
|
[senderID]="message?.sender"
|
|
55
55
|
[senderFullname]="message?.sender_fullname"
|
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
[ngClass]="{'slide-in-left': false}"
|
|
63
63
|
[class.no-background]="(isImage(message) || isFrame(message) || isCarousel(message)) && ((message?.text && message?.text.trim() === '') || !message?.text)"
|
|
64
64
|
[class.emoticon]="isEmojii(message?.text)"
|
|
65
|
-
[
|
|
65
|
+
[class.fullSizeMessage]="isStreamAudioActive"
|
|
66
|
+
[style.margin-left]="isSameSender(message?.sender, i) ? 'calc(var(--avatar-width) + 10px)' : null"
|
|
66
67
|
[ngStyle]="{'background': stylesMap.get('bubbleReceivedBackground'), 'color': stylesMap.get('bubbleReceivedTextColor'), 'width':isFrame(message) ?'100%' : null}"
|
|
67
68
|
[isSameSender]="isSameSender(message?.sender, i)"
|
|
68
69
|
[message]="message"
|
|
@@ -134,9 +135,10 @@
|
|
|
134
135
|
[senderFullname]="nameUserTypingNow"
|
|
135
136
|
[baseLocation]="baseLocation">
|
|
136
137
|
</chat-avatar-image>
|
|
138
|
+
|
|
137
139
|
<user-typing
|
|
138
|
-
[ngClass]="{'userTypingNowExist': !idUserTypingNow}"
|
|
139
140
|
[color]="stylesMap?.get('iconColor')"
|
|
141
|
+
[ngClass]="{'userTypingNowExist': !idUserTypingNow}"
|
|
140
142
|
[translationMap]="translationMap"
|
|
141
143
|
[idUserTypingNow]="idUserTypingNow"
|
|
142
144
|
[nameUserTypingNow]="nameUserTypingNow">
|
|
@@ -145,7 +147,9 @@
|
|
|
145
147
|
|
|
146
148
|
<div *ngIf="showThinkingMessage && lastServerSenderKind === 'bot'" class="msg_container base_receive thinking_receive">
|
|
147
149
|
<user-typing class="loading thinking-dots"
|
|
150
|
+
[class.fullSize]="isStreamAudioActive"
|
|
148
151
|
[color]="stylesMap?.get('iconColor')"
|
|
152
|
+
[class.fullSize]="isStreamAudioActive"
|
|
149
153
|
[translationMap]="translationMap"
|
|
150
154
|
[idUserTypingNow]="idUserTypingNow"
|
|
151
155
|
[nameUserTypingNow]="nameUserTypingNow">
|
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
margin: 25px 50px
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
:host .loading.fullSize ::ng-deep > div.spinner{
|
|
31
|
+
margin: 15px 0px !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
// ============= CSS c21-body ================= //
|
|
31
35
|
.c21-body {
|
|
32
36
|
// -webkit-box-shadow: inset 0 10px 10px -10px rgba(0,0,0,0.4);
|
|
@@ -236,6 +240,11 @@
|
|
|
236
240
|
height: fit-content;
|
|
237
241
|
width: auto;
|
|
238
242
|
|
|
243
|
+
&.fullSizeMessage {
|
|
244
|
+
max-width: 100%;
|
|
245
|
+
margin: auto 0 auto 0 !important;
|
|
246
|
+
}
|
|
247
|
+
|
|
239
248
|
}
|
|
240
249
|
|
|
241
250
|
|
|
@@ -270,6 +279,15 @@
|
|
|
270
279
|
}// end c21-body-container
|
|
271
280
|
}// end c21-body
|
|
272
281
|
|
|
282
|
+
/* Solo con pulsante chiudi stream (stream in ascolto): altezza extra come #streamAudioAlert */
|
|
283
|
+
:host-context(#chat21-conversation-component.chat21-conversation--close-stream-active) .c21-body .c21-body-container .c21-body-content .chat21-sheet-content {
|
|
284
|
+
bottom: calc(
|
|
285
|
+
var(--chat-footer-logo-height) +
|
|
286
|
+
var(--chat-footer-height) +
|
|
287
|
+
var(--chat-footer-stream-button-height)
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
273
291
|
@keyframes thinking-dot {
|
|
274
292
|
0%, 80%, 100% {
|
|
275
293
|
opacity: 0.2;
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html
CHANGED
|
@@ -13,26 +13,12 @@
|
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
15
|
<!-- STREAM AUDIO: cerchio con onde animate -->
|
|
16
|
-
<div id="streamAudioAlert" *ngIf="!hideTextAreaContent && isStreamAudioActive" class="fade-in-bottom stream-audio-alert" [class.hideTextReply]="hideTextReply" role="status" [attr.aria-label]="translationMap?.get('STREAM_AUDIO_LISTENING') || 'Stream audio attivo'">
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
<path [attr.d]="wavePath1"></path>
|
|
23
|
-
</g>
|
|
24
|
-
|
|
25
|
-
<g class="stream-audio-alert__wave-layer stream-audio-alert__wave-layer--2">
|
|
26
|
-
<path [attr.d]="wavePath2"></path>
|
|
27
|
-
</g>
|
|
28
|
-
|
|
29
|
-
<g class="stream-audio-alert__wave-layer stream-audio-alert__wave-layer--3">
|
|
30
|
-
<path [attr.d]="wavePath3"></path>
|
|
31
|
-
</g>
|
|
32
|
-
</g>
|
|
33
|
-
</svg>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
16
|
+
<!-- <div id="streamAudioAlert" *ngIf="!hideTextAreaContent && isStreamAudioActive" class="fade-in-bottom stream-audio-alert" [class.hideTextReply]="hideTextReply" role="status" [attr.aria-label]="translationMap?.get('STREAM_AUDIO_LISTENING') || 'Stream audio attivo'">
|
|
17
|
+
<chat-stream-audio-spectrum
|
|
18
|
+
[volume]="currentVolume"
|
|
19
|
+
[accentColor]="isBotSpeaking ? '#b0b0b0' : stylesMap?.get('themeColor')">
|
|
20
|
+
</chat-stream-audio-spectrum>
|
|
21
|
+
</div> -->
|
|
36
22
|
|
|
37
23
|
</div>
|
|
38
24
|
|
|
@@ -85,7 +71,7 @@
|
|
|
85
71
|
|
|
86
72
|
|
|
87
73
|
|
|
88
|
-
<div *ngIf="!isStopRec" class="visible-text-area" [class.hasError]="showAlertEmoji" [class.disabled] = "( isConversationArchived || hideTextReply)? true : null">
|
|
74
|
+
<div *ngIf="!isStopRec" class="visible-text-area" [class.stream-active]="isStreamAudioActive" [class.hasError]="showAlertEmoji" [class.disabled] = "( isConversationArchived || hideTextReply)? true : null">
|
|
89
75
|
<!-- isFilePendingToUpload || -->
|
|
90
76
|
<textarea
|
|
91
77
|
[attr.disabled] = "(hideTextReply)? true : null"
|
|
@@ -117,7 +103,7 @@
|
|
|
117
103
|
</div>
|
|
118
104
|
|
|
119
105
|
<!-- ICON REC -->
|
|
120
|
-
<div *ngIf="showAudioRecorderFooterButton && !textInputTextArea" tabindex="-1" class="chat21-audio-button" [class.active]="isStopRec" id="chat21-button-rec">
|
|
106
|
+
<div *ngIf="showAudioRecorderFooterButton && !textInputTextArea && !isStreamAudioActive" tabindex="-1" class="chat21-audio-button" [class.active]="isStopRec" id="chat21-button-rec">
|
|
121
107
|
<chat-audio-recorder
|
|
122
108
|
(startRecordingEvent)="onStartRecording()"
|
|
123
109
|
(deleteRecordingEvent)="onDeleteRecording()"
|
|
@@ -126,8 +112,24 @@
|
|
|
126
112
|
[stylesMap]="stylesMap">
|
|
127
113
|
</chat-audio-recorder>
|
|
128
114
|
</div>
|
|
115
|
+
|
|
116
|
+
<!-- ICON STREAM / CHIUDI STREAM (cerchio, icone bianche su iconColor) -->
|
|
117
|
+
<div *ngIf="showAudioStreamFooterButton" tabindex="-1" id="chat21-button-stream"
|
|
118
|
+
class="chat21-textarea-button chat21-stream-button"
|
|
119
|
+
[class.active]="isStreamAudioActive || (!textInputTextArea && !hideTextReply)"
|
|
120
|
+
[class.chat21-stream-button--expanded]="isStreamAudioActive"
|
|
121
|
+
(click)="onStreamPressed($event)" [attr.aria-label]="isStreamAudioActive ? (translationMap?.get('CLOSE') || 'Chiudi stream') : (translationMap?.get('STREAM_AUDIO') || 'Stream audio')"
|
|
122
|
+
[ngStyle]="{ 'background-color': stylesMap?.get('iconColor') || stylesMap?.get('themeColor') }">
|
|
123
|
+
<chat-stream-audio-spectrum
|
|
124
|
+
mode="button"
|
|
125
|
+
[active]="isStreamAudioActive"
|
|
126
|
+
[volume]="currentVolume"
|
|
127
|
+
[translationMap]="translationMap">
|
|
128
|
+
</chat-stream-audio-spectrum>
|
|
129
|
+
</div>
|
|
129
130
|
</div>
|
|
130
131
|
|
|
132
|
+
|
|
131
133
|
<div class="close-chat-container" *ngIf="closeChatInConversation">
|
|
132
134
|
<button tabindex="1040" aflistconv #aflistconv class="c21-button-primary c21-close" (click)="onCloseChat($event)" [ngStyle]="{'background-color': stylesMap.get('themeColor'), 'border-color': stylesMap.get('themeColor'), 'color': stylesMap?.get('foregroundColor')}">
|
|
133
135
|
<span class="v-align-center">
|
|
@@ -149,25 +151,6 @@
|
|
|
149
151
|
</button>
|
|
150
152
|
</div>
|
|
151
153
|
|
|
152
|
-
<!-- ICON STREAM / CHIUDI STREAM (cerchio, icone bianche su iconColor) -->
|
|
153
|
-
<div *ngIf="showAudioStreamFooterButton" tabindex="-1" id="chat21-button-stream"
|
|
154
|
-
class="chat21-textarea-button chat21-stream-button" [class.active]="isStreamAudioActive || (!textInputTextArea && !hideTextReply)"
|
|
155
|
-
(click)="onStreamPressed($event)" [attr.aria-label]="isStreamAudioActive ? (translationMap?.get('CLOSE') || 'Chiudi stream') : (translationMap?.get('STREAM_AUDIO') || 'Stream audio')"
|
|
156
|
-
[ngStyle]="{ 'background-color': stylesMap?.get('iconColor') || stylesMap?.get('themeColor') }">
|
|
157
|
-
<span class="v-align-center chat21-stream-button__icon" *ngIf="!isStreamAudioActive">
|
|
158
|
-
<svg role="img" xmlns="http://www.w3.org/2000/svg" version="1.1" width="24" height="24" viewBox="0 0 30 30" fill="#ffffff" aria-hidden="true" preserveAspectRatio="xMidYMid meet">
|
|
159
|
-
<path class="s0" d="m5.21 7.41c-1.21 0-2.21 0.99-2.21 2.21v8.14c0 1.21 0.99 2.21 2.21 2.21 1.22 0 2.21-0.99 2.21-2.21v-8.14c0-1.21-0.99-2.21-2.21-2.21z"/>
|
|
160
|
-
<path class="s0" d="m11.64 3.01c-1.22 0-2.21 0.99-2.21 2.2v16.94c0 1.21 0.99 2.2 2.21 2.2 1.22 0 2.21-0.98 2.21-2.2v-16.94c0-1.21-0.99-2.21-2.21-2.21z"/>
|
|
161
|
-
<path class="s0" d="m15.86 9.25v8.88c0 1.21 0.99 2.21 2.21 2.21 1.22 0 2.21-0.99 2.21-2.21v-8.88c0-1.22-0.99-2.21-2.21-2.21-1.22 0-2.21 0.99-2.21 2.21z"/>
|
|
162
|
-
<path class="s0" d="m24.5 8.97c-1.22 0-2.21 0.99-2.21 2.21v5.02c0 1.22 0.99 2.21 2.21 2.21 1.22 0 2.21-0.99 2.21-2.21v-5.02c0-1.21-0.99-2.21-2.21-2.21z"/>
|
|
163
|
-
</svg>
|
|
164
|
-
</span>
|
|
165
|
-
<span class="v-align-center chat21-stream-button__icon" *ngIf="isStreamAudioActive">
|
|
166
|
-
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#ffffff" aria-hidden="true">
|
|
167
|
-
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>
|
|
168
|
-
</svg>
|
|
169
|
-
</span>
|
|
170
|
-
</div>
|
|
171
154
|
</div>
|
|
172
155
|
|
|
173
156
|
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
justify-content: space-between;
|
|
10
10
|
gap: 8px;
|
|
11
11
|
}
|
|
12
|
+
|
|
12
13
|
.close-chat-container{
|
|
13
14
|
display: flex;
|
|
14
15
|
flex-direction: column;
|
|
@@ -42,6 +43,10 @@
|
|
|
42
43
|
&.hasError{
|
|
43
44
|
box-shadow: 0 0 0 1px var(--chat-footer-border-color-error) inset;
|
|
44
45
|
}
|
|
46
|
+
|
|
47
|
+
&.stream-active {
|
|
48
|
+
width: 50%;
|
|
49
|
+
}
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
.chat21-textarea-button {
|
|
@@ -93,6 +98,10 @@
|
|
|
93
98
|
box-sizing: border-box;
|
|
94
99
|
flex-shrink: 0;
|
|
95
100
|
color: #ffffff;
|
|
101
|
+
transition:
|
|
102
|
+
width 180ms ease,
|
|
103
|
+
border-radius 180ms ease,
|
|
104
|
+
padding 180ms ease;
|
|
96
105
|
|
|
97
106
|
.chat21-stream-button__icon svg {
|
|
98
107
|
width: 20px;
|
|
@@ -106,6 +115,22 @@
|
|
|
106
115
|
background: rgba(255, 255, 255, 0.2) !important;
|
|
107
116
|
border-radius: 50%;
|
|
108
117
|
}
|
|
118
|
+
|
|
119
|
+
&.chat21-stream-button--expanded {
|
|
120
|
+
width: auto;
|
|
121
|
+
// min-width: 150px;
|
|
122
|
+
max-width: 100%;
|
|
123
|
+
border-radius: 999px;
|
|
124
|
+
padding: 0 14px;
|
|
125
|
+
gap: 12px;
|
|
126
|
+
justify-content: center;
|
|
127
|
+
|
|
128
|
+
// stop the circle-hover background from looking odd on pill
|
|
129
|
+
&.chat21-textarea-button span svg:hover {
|
|
130
|
+
background: transparent !important;
|
|
131
|
+
border-radius: 0;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
109
134
|
}
|
|
110
135
|
|
|
111
136
|
textarea,
|
|
@@ -393,67 +418,28 @@ textarea:active{
|
|
|
393
418
|
#streamAudioAlert {
|
|
394
419
|
bottom: 100%;
|
|
395
420
|
width: 100%;
|
|
396
|
-
min-height:
|
|
421
|
+
min-height: var(--chat-footer-stream-button-height);
|
|
397
422
|
display: flex;
|
|
398
423
|
align-items: center;
|
|
399
424
|
justify-content: center;
|
|
400
|
-
background-color: var(--content-background-color);
|
|
401
425
|
position: absolute;
|
|
402
|
-
padding:
|
|
426
|
+
padding: var(--chat-footer-stream-button-padding);
|
|
427
|
+
/* Satinato / vetro: più trasparenza, blur più marcato */
|
|
428
|
+
background-color: color-mix(in srgb, var(--content-background-color) 34%, transparent);
|
|
429
|
+
backdrop-filter: blur(20px) saturate(1.2);
|
|
430
|
+
-webkit-backdrop-filter: blur(20px) saturate(1.2);
|
|
431
|
+
box-shadow:
|
|
432
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.28),
|
|
433
|
+
0 1px 0 rgba(0, 0, 0, 0.05);
|
|
403
434
|
|
|
404
435
|
&.hideTextReply {
|
|
405
436
|
position: unset;
|
|
406
437
|
min-height: auto;
|
|
407
438
|
padding: 16px 0;
|
|
408
439
|
box-shadow: none;
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
.stream-audio-alert__orb {
|
|
413
|
-
display: flex;
|
|
414
|
-
align-items: center;
|
|
415
|
-
justify-content: center;
|
|
416
|
-
width: 88px;
|
|
417
|
-
height: 88px;
|
|
418
|
-
border-radius: 50%;
|
|
419
|
-
border: 2px solid currentColor;
|
|
420
|
-
background: var(--content-background-color);
|
|
421
|
-
box-shadow: inset 0 0 24px rgba(0, 0, 0, 0.04);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
.stream-audio-alert__svg {
|
|
425
|
-
width: 72px;
|
|
426
|
-
height: 72px;
|
|
427
|
-
display: block;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
.stream-audio-alert__wave-layer {
|
|
431
|
-
transform-origin: 50px 50px;
|
|
432
|
-
transform-box: fill-box;
|
|
433
|
-
animation: stream-wave-float 1.35s ease-in-out infinite;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
.stream-audio-alert__wave-layer--1 {
|
|
437
|
-
animation-delay: 0s;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
.stream-audio-alert__wave-layer--2 {
|
|
441
|
-
animation-delay: 0.18s;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
.stream-audio-alert__wave-layer--3 {
|
|
445
|
-
animation-delay: 0.36s;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
@keyframes stream-wave-float {
|
|
449
|
-
0%,
|
|
450
|
-
100% {
|
|
451
|
-
transform: translateY(0);
|
|
452
|
-
opacity: 0.85;
|
|
453
|
-
}
|
|
454
|
-
50% {
|
|
455
|
-
transform: translateY(-6px);
|
|
456
|
-
opacity: 1;
|
|
440
|
+
backdrop-filter: none;
|
|
441
|
+
-webkit-backdrop-filter: none;
|
|
442
|
+
background-color: var(--content-background-color);
|
|
457
443
|
}
|
|
458
444
|
}
|
|
459
445
|
|