@adatechnology/conversations-ui 0.1.0-rc.5 → 0.1.0-rc.7
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/chunk-TGTBMMFC.js +1707 -0
- package/dist/index.d.ts +209 -22
- package/dist/index.js +243 -590
- package/dist/preview/index.d.ts +153 -9
- package/dist/preview/index.js +520 -38
- package/dist/{types-C2Yexi8A.d.ts → types-B5C1DLu1.d.ts} +70 -2
- package/package.json +2 -2
- package/src/Avatar.tsx +13 -2
- package/src/ConversationHeader.tsx +18 -0
- package/src/ConversationListItem.tsx +18 -2
- package/src/DocumentsLibrary.tsx +322 -0
- package/src/EmojiPicker.tsx +69 -55
- package/src/FileIcon.test.ts +46 -1
- package/src/FileIcon.tsx +76 -10
- package/src/InteractiveMessage.tsx +126 -0
- package/src/Lightbox.tsx +18 -3
- package/src/MessageBubble.tsx +31 -4
- package/src/MessageComposer.tsx +36 -5
- package/src/WhatsAppMessageEditor.tsx +28 -4
- package/src/emojiCatalog.test.ts +35 -0
- package/src/emojiCatalog.ts +189 -0
- package/src/index.ts +25 -12
- package/src/lib/createMediaUrlResolver.ts +33 -0
- package/src/preview/AudioRecorderButton.tsx +117 -0
- package/src/preview/ConversationPreview.tsx +184 -15
- package/src/preview/MediaTypesPreview.tsx +87 -0
- package/src/preview/audioRecorderFormat.test.ts +67 -0
- package/src/preview/conversationPreviewFailures.test.ts +64 -0
- package/src/preview/createMockConversationsApi.ts +62 -8
- package/src/preview/createPreviewWebhookClient.ts +28 -1
- package/src/preview/index.ts +16 -2
- package/src/preview/mediaTypeOf.test.ts +15 -0
- package/src/preview/mockDocumentsSearch.test.ts +57 -0
- package/src/preview/previewFileSamples.test.ts +151 -0
- package/src/preview/previewFileSamples.ts +74 -0
- package/src/preview/previewFixtures.ts +140 -8
- package/src/preview/previewMediaSource.test.ts +62 -0
- package/src/preview/previewMediaSource.ts +91 -0
- package/src/providers/types.ts +17 -0
- package/src/settings/WhatsAppCreateTemplateForm.tsx +3 -1
- package/src/types.ts +38 -1
- package/dist/chunk-YWITIIHD.js +0 -728
package/dist/preview/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ConversationDocumentsPanel,
|
|
2
3
|
ConversationWallpaper,
|
|
4
|
+
ConversationsProvider,
|
|
3
5
|
DateDivider,
|
|
6
|
+
DocumentsLibrary,
|
|
4
7
|
MessageBubble,
|
|
5
8
|
MessageComposer
|
|
6
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-TGTBMMFC.js";
|
|
7
10
|
import "../chunk-OGRRHQQW.js";
|
|
8
11
|
|
|
9
12
|
// src/preview/previewStore.ts
|
|
@@ -399,8 +402,7 @@ var PREVIEW_MESSAGES = {
|
|
|
399
402
|
timestamp: at("15:09:00")
|
|
400
403
|
},
|
|
401
404
|
{
|
|
402
|
-
|
|
403
|
-
id: "fixture-doc-generic",
|
|
405
|
+
id: "fixture-doc-txt",
|
|
404
406
|
type: "document",
|
|
405
407
|
uploadId: "preview/documentos/lista-compras.txt",
|
|
406
408
|
filename: "lista-compras.txt",
|
|
@@ -409,13 +411,140 @@ var PREVIEW_MESSAGES = {
|
|
|
409
411
|
direction: "inbound",
|
|
410
412
|
sender: "customer",
|
|
411
413
|
timestamp: at("15:10:00")
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
id: "fixture-doc-csv",
|
|
417
|
+
type: "document",
|
|
418
|
+
uploadId: "preview/documentos/planilha-do-pedido.csv",
|
|
419
|
+
filename: "planilha-do-pedido.csv",
|
|
420
|
+
mimeType: "text/csv",
|
|
421
|
+
sizeBytes: 2048,
|
|
422
|
+
direction: "inbound",
|
|
423
|
+
sender: "customer",
|
|
424
|
+
timestamp: at("15:11:00")
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
id: "fixture-doc-pptx",
|
|
428
|
+
type: "document",
|
|
429
|
+
uploadId: "preview/documentos/apresentacao.pptx",
|
|
430
|
+
filename: "apresentacao.pptx",
|
|
431
|
+
mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
432
|
+
sizeBytes: 512e3,
|
|
433
|
+
direction: "inbound",
|
|
434
|
+
sender: "customer",
|
|
435
|
+
timestamp: at("15:12:00")
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
id: "fixture-doc-ppt",
|
|
439
|
+
type: "document",
|
|
440
|
+
uploadId: "preview/documentos/antiga.ppt",
|
|
441
|
+
filename: "antiga.ppt",
|
|
442
|
+
mimeType: "application/vnd.ms-powerpoint",
|
|
443
|
+
sizeBytes: 348160,
|
|
444
|
+
direction: "inbound",
|
|
445
|
+
sender: "customer",
|
|
446
|
+
timestamp: at("15:13:00")
|
|
447
|
+
},
|
|
448
|
+
// Mídia enviada COMO arquivo: aí a Meta manda o nome, então é onde a extensão de música e de
|
|
449
|
+
// vídeo aparece na lista. Mandada como `image`/`audio`/`video` (acima e abaixo) ela chega sem
|
|
450
|
+
// nome nenhum, e o rótulo vira o id da mídia — como em produção.
|
|
451
|
+
{
|
|
452
|
+
id: "fixture-doc-mp3",
|
|
453
|
+
type: "document",
|
|
454
|
+
uploadId: "preview/documentos/musica-do-anuncio.mp3",
|
|
455
|
+
filename: "musica-do-anuncio.mp3",
|
|
456
|
+
mimeType: "audio/mpeg",
|
|
457
|
+
sizeBytes: 3145728,
|
|
458
|
+
direction: "inbound",
|
|
459
|
+
sender: "customer",
|
|
460
|
+
timestamp: at("15:14:00")
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
id: "fixture-doc-m4a",
|
|
464
|
+
type: "document",
|
|
465
|
+
uploadId: "preview/documentos/recado.m4a",
|
|
466
|
+
filename: "recado.m4a",
|
|
467
|
+
mimeType: "audio/mp4",
|
|
468
|
+
sizeBytes: 486400,
|
|
469
|
+
direction: "inbound",
|
|
470
|
+
sender: "customer",
|
|
471
|
+
timestamp: at("15:15:00")
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
id: "fixture-doc-mp4-file",
|
|
475
|
+
type: "document",
|
|
476
|
+
uploadId: "preview/documentos/video-do-produto.mp4",
|
|
477
|
+
filename: "video-do-produto.mp4",
|
|
478
|
+
mimeType: "video/mp4",
|
|
479
|
+
sizeBytes: 8388608,
|
|
480
|
+
direction: "inbound",
|
|
481
|
+
sender: "customer",
|
|
482
|
+
timestamp: at("15:16:00")
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
id: "fixture-doc-jpg",
|
|
486
|
+
type: "document",
|
|
487
|
+
uploadId: "preview/documentos/foto-do-recibo.jpg",
|
|
488
|
+
filename: "foto-do-recibo.jpg",
|
|
489
|
+
mimeType: "image/jpeg",
|
|
490
|
+
sizeBytes: 262144,
|
|
491
|
+
direction: "inbound",
|
|
492
|
+
sender: "customer",
|
|
493
|
+
timestamp: at("15:17:00")
|
|
494
|
+
},
|
|
495
|
+
// As espécies restantes que a Meta aceita, sem nome de arquivo — fecham a lista de tipos
|
|
496
|
+
// aceitos e exercitam o fallback de ícone pela família do mimeType.
|
|
497
|
+
{
|
|
498
|
+
id: "fixture-media-jpeg",
|
|
499
|
+
type: "image",
|
|
500
|
+
mediaId: "preview-image-jpeg",
|
|
501
|
+
mimeType: "image/jpeg",
|
|
502
|
+
sizeBytes: 138240,
|
|
503
|
+
direction: "inbound",
|
|
504
|
+
sender: "customer",
|
|
505
|
+
timestamp: at("15:18:00")
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
id: "fixture-media-3gp",
|
|
509
|
+
type: "video",
|
|
510
|
+
mediaId: "preview-video-3gp",
|
|
511
|
+
mimeType: "video/3gp",
|
|
512
|
+
sizeBytes: 921600,
|
|
513
|
+
direction: "inbound",
|
|
514
|
+
sender: "customer",
|
|
515
|
+
timestamp: at("15:19:00")
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
id: "fixture-media-aac",
|
|
519
|
+
type: "audio",
|
|
520
|
+
mediaId: "preview-audio-aac",
|
|
521
|
+
mimeType: "audio/aac",
|
|
522
|
+
sizeBytes: 76800,
|
|
523
|
+
direction: "inbound",
|
|
524
|
+
sender: "customer",
|
|
525
|
+
timestamp: at("15:20:00")
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
id: "fixture-media-amr",
|
|
529
|
+
type: "audio",
|
|
530
|
+
mediaId: "preview-audio-amr",
|
|
531
|
+
mimeType: "audio/amr",
|
|
532
|
+
sizeBytes: 24576,
|
|
533
|
+
direction: "inbound",
|
|
534
|
+
sender: "customer",
|
|
535
|
+
timestamp: at("15:21:00")
|
|
412
536
|
}
|
|
413
537
|
]
|
|
414
538
|
};
|
|
539
|
+
var LIBRARY_MEDIA_TYPES = /* @__PURE__ */ new Set(["document", "image", "video", "audio", "sticker"]);
|
|
415
540
|
var PREVIEW_DOCUMENTS = {
|
|
416
|
-
"5511944443333": (PREVIEW_MESSAGES["5511944443333"] ?? []).filter((message) => message.type
|
|
417
|
-
|
|
418
|
-
|
|
541
|
+
"5511944443333": (PREVIEW_MESSAGES["5511944443333"] ?? []).filter((message) => LIBRARY_MEDIA_TYPES.has(message.type)).map((message) => ({
|
|
542
|
+
// Mídia não tem `uploadId` na mensagem: o backend deriva a key do id da mídia na Meta, e o
|
|
543
|
+
// caminho abaixo imita esse formato para o download assinado receber algo do mesmo feitio.
|
|
544
|
+
id: message.uploadId ?? (message.mediaId ? `preview/inbound/${message.mediaId}` : message.id),
|
|
545
|
+
// Só documento chega nomeado. Para os outros o backend salva o id da mídia como rótulo —
|
|
546
|
+
// manter isso aqui é o que faz o ícone por família do mimeType ser exercitado de verdade.
|
|
547
|
+
filename: message.filename ?? message.mediaId ?? message.id,
|
|
419
548
|
mimeType: message.mimeType ?? "application/octet-stream",
|
|
420
549
|
sizeBytes: message.sizeBytes ?? 0,
|
|
421
550
|
source: message.sender,
|
|
@@ -423,8 +552,85 @@ var PREVIEW_DOCUMENTS = {
|
|
|
423
552
|
}))
|
|
424
553
|
};
|
|
425
554
|
|
|
555
|
+
// src/preview/previewFileSamples.ts
|
|
556
|
+
var PREVIEW_FILE_SAMPLES = {
|
|
557
|
+
"application/pdf": "data:application/pdf;base64,JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgMjYwIDExMF0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNjI+PnN0cmVhbQpCVCAvRjEgMTMgVGYgMTggNTUgVGQgKERvY3VtZW50byBkZSBleGVtcGxvIGRvIHByZXZpZXcpIFRqIEVUCmVuZHN0cmVhbWVuZG9iago1IDAgb2JqPDwvVHlwZS9Gb250L1N1YnR5cGUvVHlwZTEvQmFzZUZvbnQvSGVsdmV0aWNhPj5lbmRvYmoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDA5IDAwMDAwIG4gCjAwMDAwMDAwNTIgMDAwMDAgbiAKMDAwMDAwMDEwMSAwMDAwMCBuIAowMDAwMDAwMjExIDAwMDAwIG4gCjAwMDAwMDAzMTcgMDAwMDAgbiAKdHJhaWxlcjw8L1NpemUgNi9Sb290IDEgMCBSPj4Kc3RhcnR4cmVmCjM3OAolJUVPRgo=",
|
|
558
|
+
"image/png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAAACXBIWXMAAAABAAAAAQBPJcTWAAAATElEQVR4nO3OMRHAIAAAMbhDWo2hCYPdu/xIh0RB5rPP+JN1O/AlVISKUBEqQkWoCBWhIlSEilARKkJFqAgVoSJUhIpQESpCRagIlRcgDwI25HmPQAAAAABJRU5ErkJggg==",
|
|
559
|
+
"image/jpeg": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD//gAQTGF2YzYyLjExLjEwMAD/2wBDAAgEBAQEBAUFBQUFBQYGBgYGBgYGBgYGBgYHBwcICAgHBwcGBgcHCAgICAkJCQgICAgJCQoKCgwMCwsODg4RERT/xABMAAEBAAAAAAAAAAAAAAAAAAAABAEBAQAAAAAAAAAAAAAAAAAAAAYQAQAAAAAAAAAAAAAAAAAAAAARAQAAAAAAAAAAAAAAAAAAAAD/wAARCAAwADADASIAAhEAAxEA/9oADAMBAAIRAxEAPwCUBRpwAAAAAAAAAAAAAAAB/9k=",
|
|
560
|
+
"image/webp": "data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
|
|
561
|
+
"video/mp4": "data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAANdbW9vdgAAAGxtdmhkAAAAAAAAAAAAAAAAAAAD6AAAASwAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAoh0cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAABAAAAAAAAASwAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAEAAAABAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAEsAAAIAAABAAAAAAIAbWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAAoAAAAEABVxAAAAAAALWhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABWaWRlb0hhbmRsZXIAAAABq21pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAWtzdGJsAAAAv3N0c2QAAAAAAAAAAQAAAK9hdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAEAAQABIAAAASAAAAAAAAAABFUxhdmM2Mi4xMS4xMDAgbGlieDI2NAAAAAAAAAAAAAAAGP//AAAANWF2Y0MBZAAK/+EAGGdkAAqs2UQmwEQAAAMABAAAAwBQPEiWWAEABmjr48siwP34+AAAAAAQcGFzcAAAAAEAAAABAAAAFGJ0cnQAAAAAAABO2gAAAAAAAAAYc3R0cwAAAAAAAAABAAAAAwAABAAAAAAUc3RzcwAAAAAAAAABAAAAAQAAAChjdHRzAAAAAAAAAAMAAAABAAAIAAAAAAEAAAwAAAAAAQAABAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAMAAAABAAAAIHN0c3oAAAAAAAAAAAAAAAMAAALbAAAADgAAAAwAAAAUc3RjbwAAAAAAAAABAAADjQAAAGF1ZHRhAAAAWW1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALGlsc3QAAAAkqXRvbwAAABxkYXRhAAAAAQAAAABMYXZmNjIuMy4xMDAAAAAIZnJlZQAAAv1tZGF0AAACrgYF//+q3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2NSByMzIyMiBiMzU2MDVhIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAyNSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTIgbG9va2FoZWFkX3RocmVhZHM9MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50PTI1MCBrZXlpbnRfbWluPTEwIHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAJWWIhAA///7mdfgUoKykhh+DdK6xVynnAWznTQ4fVSgMZ1FwY28AAAAKQZoibEN//qePiAAAAAgBnkF5Df8HfQ==",
|
|
562
|
+
"audio/mpeg": "data:audio/mpeg;base64,SUQzBAAAAAAAIlRTU0UAAAAOAAADTGF2ZjYyLjMuMTAwAAAAAAAAAAAAAAD/40jAAAAAAAAAAAAASW5mbwAAAA8AAAAFAAAGwABVVVVVVVVVVVVVVVVVVVVVVVVVgICAgICAgICAgICAgICAgICAgICqqqqqqqqqqqqqqqqqqqqqqqqqqtXV1dXV1dXV1dXV1dXV1dXV1dXV//////////////////////////8AAAAATGF2YzYyLjExAAAAAAAAAAAAAAAAJALAAAAAAAAABsDR4nNFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/40jEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/40jEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/40jEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/40jEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/40jEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=",
|
|
563
|
+
"audio/ogg": "data:audio/ogg;base64,T2dnUwACAAAAAAAAAABXDTmmAAAAAKMnDKEBE09wdXNIZWFkAQE4AYC7AAAAAABPZ2dTAAAAAAAAAAAAAFcNOaYBAAAAZlPuKwE9T3B1c1RhZ3MMAAAATGF2ZjYyLjMuMTAwAQAAAB0AAABlbmNvZGVyPUxhdmM2Mi4xMS4xMDAgbGlib3B1c09nZ1MABLgmAAAAAAAAVw05pgIAAAA3uL6lCw8REhISEhISEhISeAvkwTbsxY2MSUaZpCaweAfJcifhROpV8fDA1d3pUmB4B8l5yMlXwKISI/rvZ/NkwOB4B8l5yMlXwKISI/rvZ/NkwOB4B8l5yMlXwKISI/rvZ/NkwOB4B8l5yMlXwKISI/rvZ/NkwOB4B8l5yMlXwKISI/rvZ/NkwOB4B8l5yMlXwKISI/rvZ/NkwOB4B8l5yMlXwKISI/rvZ/NkwOB4B8l5yMlXwKISI/rvZ/NkwOB4B8l5yMlXwKISI/rvZ/NkwOA=",
|
|
564
|
+
"audio/mp4": "data:audio/mp4;base64,AAAAHGZ0eXBNNEEgAAACAE00QSBpc29taXNvMgAAAAhmcmVlAAAAQW1kYXTeAgBMYXZjNjIuMTEuMTAwAAIwQA4BGCAHARggBwEYIAcBGCAHARggBwEYIAcBGCAHARggBwEYIAcAAAMibW9vdgAAAGxtdmhkAAAAAAAAAAAAAAAAAAAD6AAAAMgAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAk10cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAABAAAAAAAAAMgAAAAAAAAAAAAAAAEBAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAADIAAAEAAABAAAAAAHFbWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAACsRAAAJnRVxAAAAAAALWhkbHIAAAAAAAAAAHNvdW4AAAAAAAAAAAAAAABTb3VuZEhhbmRsZXIAAAABcG1pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABNHN0YmwAAABqc3RzZAAAAAAAAAABAAAAWm1wNGEAAAAAAAAAAQAAAAAAAAAAAAEAEAAAAACsRAAAAAAANmVzZHMAAAAAA4CAgCUAAQAEgICAF0AVAAAAAAB9AAAAB/oFgICABRIIVuUABoCAgAECAAAAIHN0dHMAAAAAAAAAAgAAAAkAAAQAAAAAAQAAAnQAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAoAAAABAAAAPHN0c3oAAAAAAAAAAAAAAAoAAAAVAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAFHN0Y28AAAAAAAAAAQAAACwAAAAac2dwZAEAAAByb2xsAAAAAgAAAAH//wAAABxzYmdwAAAAAHJvbGwAAAABAAAACgAAAAEAAABhdWR0YQAAAFltZXRhAAAAAAAAACFoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAACxpbHN0AAAAJKl0b28AAAAcZGF0YQAAAAEAAAAATGF2ZjYyLjMuMTAw",
|
|
565
|
+
"audio/aac": "data:audio/aac;base64,//FQQAOf/N4CAExhdmM2Mi4xMS4xMDAAAjBADv/xUEABf/wBGCAH//FQQAF//AEYIAf/8VBAAX/8ARggB//xUEABf/wBGCAH//FQQAF//AEYIAf/8VBAAX/8ARggB//xUEABf/wBGCAH//FQQAF//AEYIAf/8VBAAX/8ARggBw==",
|
|
566
|
+
"text/plain": "data:text/plain;base64,TGlzdGEgZGUgY29tcHJhcwotIGFycm96IDJrZwotIG9sZW8gMXVuCg==",
|
|
567
|
+
"text/csv": "data:text/csv;base64,cHJvZHV0byxxdWFudGlkYWRlLHByZWNvCmFycm96LDIsMjQuOTAKb2xlbywxLDcuNTAK",
|
|
568
|
+
"application/zip": "data:application/zip;base64,UEsDBBQAAAAIANFO/FwtmGOxGwAAABkAAAARAAAAY29tcHJvdmFudGUtMS50eHRLzs8tKMovS8wrSVVISVUoSExPzE3NK8nnAgBQSwMEFAAAAAgA0U78XCftV8YWAAAAFAAAABEAAABjb21wcm92YW50ZS0yLnR4dCtOTS/NS8lXSM7PLSjKL0vMK0nlAgBQSwECFAMUAAAACADRTvxcLZhjsRsAAAAZAAAAEQAAAAAAAAAAAAAAgAEAAAAAY29tcHJvdmFudGUtMS50eHRQSwECFAMUAAAACADRTvxcJ+1XxhYAAAAUAAAAEQAAAAAAAAAAAAAAgAFKAAAAY29tcHJvdmFudGUtMi50eHRQSwUGAAAAAAIAAgB+AAAAjwAAAAAA",
|
|
569
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,UEsDBBQAAAAIANFO/Fx5bjPX6AAAAK0BAAATAAAAW0NvbnRlbnRfVHlwZXNdLnhtbH1QyU7DMBD9FWuuKHHggBCK0wPLETiUDxjZk8SqN3nc0v49Tlt6QIXjzFv1+tXeO7GjzDYGBbdtB4KCjsaGScHn+rV5AMEFg0EXAyk4EMNq6NeHRCyqNrCCuZT0KCXrmTxyGxOFiowxeyz1zJNMqDc4kbzrunupYygUSlMWDxj6Zxpx64p42df3qUcmxyCeTsQlSwGm5KzGUnG5C+ZXSnNOaKvyyOHZJr6pBJBXExbk74Cz7r0Ok60h8YG5vKGvLPkVs5Em6q2vyvZ/mys94zhaTRf94pZy1MRcF/euvSAebfjpL49zD99QSwMEFAAAAAgA0U78XJv9N+qtAAAAKQEAAAsAAABfcmVscy8ucmVsc43POw7CMAwG4KtE3mlaBoRQ0y4IqSsqB7ASN61oHkrCo7cnAwNFDIy2f3+W6/ZpZnanECdnBVRFCYysdGqyWsClP232wGJCq3B2lgQsFKFt6jPNmPJKHCcfWTZsFDCm5A+cRzmSwVg4TzZPBhcMplwGzT3KK2ri27Lc8fBpwNpknRIQOlUB6xdP/9huGCZJRydvhmz6ceIrkWUMmpKAhwuKq3e7yCzwpuarF5sXUEsDBBQAAAAIANFO/FyraIuoqgAAAOcAAAARAAAAd29yZC9kb2N1bWVudC54bWxFjksOwjAMBa8SZU9TWCBUNWWBxAngAKExbaTGjpzQz+1JyoLNPFt+Grm9rn4SM3B0hFoeq1oKwJ6sw0HL5+N+uEgRk0FrJkLQcoMor127NJb6jwdMIgswNouWY0qhUSr2I3gTKwqA+fYm9ibllQe1ENvA1EOM2e8ndarrs/LGoSzKF9mtZCjggtTdCBObRMKCgBV8mPJIIjDMDpZWlU4h7ww7fx71/7H7AlBLAQIUAxQAAAAIANFO/Fx5bjPX6AAAAK0BAAATAAAAAAAAAAAAAACAAQAAAABbQ29udGVudF9UeXBlc10ueG1sUEsBAhQDFAAAAAgA0U78XJv9N+qtAAAAKQEAAAsAAAAAAAAAAAAAAIABGQEAAF9yZWxzLy5yZWxzUEsBAhQDFAAAAAgA0U78XKtoi6iqAAAA5wAAABEAAAAAAAAAAAAAAIAB7wEAAHdvcmQvZG9jdW1lbnQueG1sUEsFBgAAAAADAAMAuQAAAMgCAAAAAA==",
|
|
570
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,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"
|
|
571
|
+
};
|
|
572
|
+
var FAMILY_FALLBACK = {
|
|
573
|
+
image: "image/png",
|
|
574
|
+
video: "video/mp4",
|
|
575
|
+
audio: "audio/mpeg",
|
|
576
|
+
text: "text/plain"
|
|
577
|
+
};
|
|
578
|
+
function resolvePreviewFileSample(mimeType, filename) {
|
|
579
|
+
const normalized = (mimeType ?? "").split(";")[0].trim().toLowerCase();
|
|
580
|
+
const exact = PREVIEW_FILE_SAMPLES[normalized];
|
|
581
|
+
if (exact) return exact;
|
|
582
|
+
const family = FAMILY_FALLBACK[normalized.split("/")[0] ?? ""];
|
|
583
|
+
const byFamily = family ? PREVIEW_FILE_SAMPLES[family] : void 0;
|
|
584
|
+
if (byFamily) return byFamily;
|
|
585
|
+
const note = `Preview do SDK: nao existe amostra binaria valida para ${normalized || "tipo desconhecido"}${filename ? ` (${filename})` : ""}. Na tela real este arquivo vem do storage.`;
|
|
586
|
+
return `data:text/plain;charset=utf-8,${encodeURIComponent(note)}`;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// src/preview/previewMediaSource.ts
|
|
590
|
+
var blobUrlCache = /* @__PURE__ */ new Map();
|
|
591
|
+
function toBlob(dataUrl) {
|
|
592
|
+
const [head, payload] = dataUrl.split(",");
|
|
593
|
+
const mimeType = head.replace(/^data:/, "").replace(/;base64$/, "").replace(/;charset=.*$/, "");
|
|
594
|
+
if (!head.endsWith(";base64")) {
|
|
595
|
+
return new Blob([decodeURIComponent(payload)], { type: mimeType || "text/plain" });
|
|
596
|
+
}
|
|
597
|
+
const binary = atob(payload);
|
|
598
|
+
const bytes = new Uint8Array(binary.length);
|
|
599
|
+
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
600
|
+
return new Blob([bytes], { type: mimeType });
|
|
601
|
+
}
|
|
602
|
+
function previewFileUrl(mimeType, filename) {
|
|
603
|
+
const dataUrl = resolvePreviewFileSample(mimeType, filename);
|
|
604
|
+
if (typeof URL === "undefined" || typeof URL.createObjectURL !== "function") return dataUrl;
|
|
605
|
+
const cached = blobUrlCache.get(dataUrl);
|
|
606
|
+
if (cached) return cached;
|
|
607
|
+
const blobUrl = URL.createObjectURL(toBlob(dataUrl));
|
|
608
|
+
blobUrlCache.set(dataUrl, blobUrl);
|
|
609
|
+
return blobUrl;
|
|
610
|
+
}
|
|
611
|
+
function previewFileBase64(mimeType, filename) {
|
|
612
|
+
const dataUrl = resolvePreviewFileSample(mimeType, filename);
|
|
613
|
+
const [head, payload] = dataUrl.split(",");
|
|
614
|
+
const declared = head.replace(/^data:/, "").replace(/;base64$/, "").replace(/;charset=.*$/, "");
|
|
615
|
+
if (head.endsWith(";base64")) return { mimeType: declared, data: payload };
|
|
616
|
+
return { mimeType: declared, data: btoa(decodeURIComponent(payload)) };
|
|
617
|
+
}
|
|
618
|
+
function createPreviewMediaResolver() {
|
|
619
|
+
const byId = /* @__PURE__ */ new Map();
|
|
620
|
+
for (const documents of Object.values(PREVIEW_DOCUMENTS)) {
|
|
621
|
+
for (const document of documents) {
|
|
622
|
+
byId.set(document.id, { mimeType: document.mimeType, filename: document.filename });
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return async (message) => {
|
|
626
|
+
const reference = message.uploadId ?? (message.mediaId ? `preview/inbound/${message.mediaId}` : void 0);
|
|
627
|
+
if (!reference) return null;
|
|
628
|
+
const known = byId.get(reference);
|
|
629
|
+
return previewFileUrl(known?.mimeType ?? message.mimeType, known?.filename ?? message.filename);
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
|
|
426
633
|
// src/preview/createMockConversationsApi.ts
|
|
427
|
-
var PREVIEW_IMAGE_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYGD4DwABBAEAX+XyEgAAAABJRU5ErkJggg==";
|
|
428
634
|
var DEFAULT_LATENCY_MS = 120;
|
|
429
635
|
var PREVIEW_AGENT_ID = "preview-agent";
|
|
430
636
|
var PREVIEW_TEMPLATES = [
|
|
@@ -542,11 +748,51 @@ function createMockConversationsApi(params) {
|
|
|
542
748
|
${names.join("\n")}`], { type: "application/zip" });
|
|
543
749
|
});
|
|
544
750
|
},
|
|
545
|
-
|
|
546
|
-
|
|
751
|
+
/** Junta as bibliotecas de todas as conversas do fixture, com a origem de cada arquivo. */
|
|
752
|
+
getAllDocuments(documentParams) {
|
|
753
|
+
return withLatency(() => {
|
|
754
|
+
let all = Object.entries(PREVIEW_DOCUMENTS).flatMap(
|
|
755
|
+
([conversationId, docs]) => docs.map((document) => ({ ...document, conversationId }))
|
|
756
|
+
);
|
|
757
|
+
const search = documentParams?.search?.trim().toLowerCase();
|
|
758
|
+
if (search) {
|
|
759
|
+
const digits = search.replace(/\D/g, "");
|
|
760
|
+
all = all.filter(
|
|
761
|
+
(document) => document.filename.toLowerCase().includes(search) || digits !== "" && document.conversationId.includes(digits)
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
const source = documentParams?.source;
|
|
765
|
+
if (source === "team") {
|
|
766
|
+
all = all.filter((document) => document.source === "agent" || document.source === "bot");
|
|
767
|
+
} else if (source) {
|
|
768
|
+
all = all.filter((document) => document.source === source);
|
|
769
|
+
}
|
|
770
|
+
all.sort(
|
|
771
|
+
(left, right) => documentParams?.sortDirection === "asc" ? left.linkedAt.localeCompare(right.linkedAt) : right.linkedAt.localeCompare(left.linkedAt)
|
|
772
|
+
);
|
|
773
|
+
const total = all.length;
|
|
774
|
+
const limit = documentParams?.limit ?? total;
|
|
775
|
+
const page = documentParams?.page ?? 1;
|
|
776
|
+
return { documents: all.slice((page - 1) * limit, page * limit), total };
|
|
777
|
+
});
|
|
547
778
|
},
|
|
548
|
-
|
|
549
|
-
|
|
779
|
+
// Devolve os bytes DO TIPO do documento, não uma imagem para tudo: antes, abrir um PDF entregava
|
|
780
|
+
// um PNG rotulado `application/pdf` e o leitor recusava o arquivo. O `uploadId` é a única pista
|
|
781
|
+
// que o contrato dá, então o tipo vem da própria biblioteca.
|
|
782
|
+
getDocumentUrl(uploadId) {
|
|
783
|
+
return withLatency(() => {
|
|
784
|
+
const found = Object.values(PREVIEW_DOCUMENTS).flat().find((document) => document.id === uploadId);
|
|
785
|
+
return previewFileUrl(found?.mimeType, found?.filename);
|
|
786
|
+
});
|
|
787
|
+
},
|
|
788
|
+
// Caminho da mídia ainda não ingerida: o backend busca na Meta e devolve base64. Resolve pelo
|
|
789
|
+
// id para a bolha receber os bytes DO TIPO dela — devolvendo um PNG para todo id, vídeo e áudio
|
|
790
|
+
// apareciam quebrados na thread mesmo havendo amostra válida do formato.
|
|
791
|
+
getMediaProxyUrl(mediaId) {
|
|
792
|
+
return withLatency(() => {
|
|
793
|
+
const found = Object.values(PREVIEW_DOCUMENTS).flat().find((document) => document.id === `preview/inbound/${mediaId}`);
|
|
794
|
+
return previewFileBase64(found?.mimeType, found?.filename);
|
|
795
|
+
});
|
|
550
796
|
},
|
|
551
797
|
takeover(conversationId) {
|
|
552
798
|
return withLatency(
|
|
@@ -599,9 +845,89 @@ function createMockSSEProvider(params) {
|
|
|
599
845
|
}
|
|
600
846
|
|
|
601
847
|
// src/preview/ConversationPreview.tsx
|
|
602
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
603
|
-
|
|
848
|
+
import { useCallback as useCallback2, useEffect, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
849
|
+
|
|
850
|
+
// src/preview/AudioRecorderButton.tsx
|
|
851
|
+
import { useCallback, useRef, useState } from "react";
|
|
852
|
+
import { jsx } from "react/jsx-runtime";
|
|
853
|
+
var DEFAULT_AUDIO_RECORDER_BUTTON_LABELS = {
|
|
854
|
+
start: "Gravar \xE1udio",
|
|
855
|
+
stop: "Parar grava\xE7\xE3o",
|
|
856
|
+
unsupported: "Este navegador n\xE3o grava \xE1udio.",
|
|
857
|
+
denied: "Sem permiss\xE3o para usar o microfone."
|
|
858
|
+
};
|
|
859
|
+
var RECORDING_FORMATS = [
|
|
860
|
+
{ mimeType: "audio/ogg;codecs=opus", uploadMimeType: "audio/ogg", extension: "ogg" },
|
|
861
|
+
{ mimeType: "audio/mp4", uploadMimeType: "audio/mp4", extension: "m4a" },
|
|
862
|
+
{ mimeType: "audio/webm", uploadMimeType: "audio/webm", extension: "webm" }
|
|
863
|
+
];
|
|
864
|
+
function resolveRecordingFormat() {
|
|
865
|
+
if (typeof MediaRecorder === "undefined") return void 0;
|
|
866
|
+
if (typeof MediaRecorder.isTypeSupported !== "function") return RECORDING_FORMATS[0];
|
|
867
|
+
return RECORDING_FORMATS.find((format) => MediaRecorder.isTypeSupported(format.mimeType));
|
|
868
|
+
}
|
|
869
|
+
function AudioRecorderButton({ onRecorded, onFailure, labels, disabled }) {
|
|
870
|
+
const startLabel = labels?.start ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS.start;
|
|
871
|
+
const stopLabel = labels?.stop ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS.stop;
|
|
872
|
+
const [isRecording, setIsRecording] = useState(false);
|
|
873
|
+
const recorderRef = useRef(null);
|
|
874
|
+
const stop = useCallback(() => {
|
|
875
|
+
recorderRef.current?.stop();
|
|
876
|
+
}, []);
|
|
877
|
+
const start = useCallback(async () => {
|
|
878
|
+
const format = resolveRecordingFormat();
|
|
879
|
+
if (!format || !navigator.mediaDevices?.getUserMedia) {
|
|
880
|
+
onFailure?.(labels?.unsupported ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS.unsupported);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
try {
|
|
884
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
885
|
+
const recorder = new MediaRecorder(stream, { mimeType: format.mimeType });
|
|
886
|
+
const chunks = [];
|
|
887
|
+
recorder.addEventListener("dataavailable", (event) => {
|
|
888
|
+
if (event.data.size > 0) chunks.push(event.data);
|
|
889
|
+
});
|
|
890
|
+
recorder.addEventListener("stop", () => {
|
|
891
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
892
|
+
setIsRecording(false);
|
|
893
|
+
recorderRef.current = null;
|
|
894
|
+
const blob = new Blob(chunks, { type: format.uploadMimeType });
|
|
895
|
+
void onRecorded(
|
|
896
|
+
new File([blob], `audio-${Date.now()}.${format.extension}`, { type: format.uploadMimeType })
|
|
897
|
+
);
|
|
898
|
+
});
|
|
899
|
+
recorderRef.current = recorder;
|
|
900
|
+
recorder.start();
|
|
901
|
+
setIsRecording(true);
|
|
902
|
+
} catch {
|
|
903
|
+
onFailure?.(labels?.denied ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS.denied);
|
|
904
|
+
}
|
|
905
|
+
}, [labels?.denied, labels?.unsupported, onFailure, onRecorded]);
|
|
906
|
+
return /* @__PURE__ */ jsx(
|
|
907
|
+
"button",
|
|
908
|
+
{
|
|
909
|
+
type: "button",
|
|
910
|
+
disabled,
|
|
911
|
+
onClick: () => isRecording ? stop() : void start(),
|
|
912
|
+
title: isRecording ? stopLabel : startLabel,
|
|
913
|
+
"aria-label": isRecording ? stopLabel : startLabel,
|
|
914
|
+
"aria-pressed": isRecording,
|
|
915
|
+
className: `flex h-9 w-9 items-center justify-center rounded-full transition-colors ${isRecording ? "bg-red-100 text-red-600 dark:bg-red-900/40" : "text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700"}`,
|
|
916
|
+
children: isRecording ? "\u25A0" : "\u{1F3A4}"
|
|
917
|
+
}
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/preview/ConversationPreview.tsx
|
|
922
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
923
|
+
function mediaTypeOf(mimeType) {
|
|
924
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
925
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
926
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
927
|
+
return "document";
|
|
928
|
+
}
|
|
604
929
|
var GROUPING_WINDOW_MS = 5 * 60 * 1e3;
|
|
930
|
+
var FOLLOW_UP_REFRESH_MS = [400, 1200, 3e3];
|
|
605
931
|
function decorate(messages) {
|
|
606
932
|
return messages.map((message, index) => {
|
|
607
933
|
const previous = index > 0 ? messages[index - 1] : void 0;
|
|
@@ -614,23 +940,52 @@ function decorate(messages) {
|
|
|
614
940
|
};
|
|
615
941
|
});
|
|
616
942
|
}
|
|
943
|
+
function statusOf(error) {
|
|
944
|
+
if (typeof error !== "object" || error === null) return void 0;
|
|
945
|
+
const candidate = error;
|
|
946
|
+
const value = candidate.status ?? candidate.statusCode;
|
|
947
|
+
return typeof value === "number" ? value : void 0;
|
|
948
|
+
}
|
|
949
|
+
function isNotFound(error) {
|
|
950
|
+
return statusOf(error) === 404;
|
|
951
|
+
}
|
|
952
|
+
function describeLoadFailure(error) {
|
|
953
|
+
const status = statusOf(error);
|
|
954
|
+
if (status === 401 || status === 403) {
|
|
955
|
+
return "Sem sess\xE3o de administrador nesta aba: a mensagem \xE9 entregue no webhook, mas o transcript n\xE3o pode ser lido. Entre no painel nesta mesma aba e reabra o simulador.";
|
|
956
|
+
}
|
|
957
|
+
if (error instanceof Error && error.message) return `N\xE3o foi poss\xEDvel ler o transcript: ${error.message}`;
|
|
958
|
+
return "N\xE3o foi poss\xEDvel ler o transcript da conversa.";
|
|
959
|
+
}
|
|
617
960
|
function ConversationPreview({
|
|
618
961
|
client,
|
|
619
962
|
sse,
|
|
620
963
|
conversationId,
|
|
621
964
|
loadMessages,
|
|
622
|
-
placeholder
|
|
965
|
+
placeholder,
|
|
966
|
+
pollIntervalMs,
|
|
967
|
+
uploadMedia
|
|
623
968
|
}) {
|
|
624
|
-
const [messages, setMessages] =
|
|
625
|
-
const [failure, setFailure] =
|
|
626
|
-
const
|
|
627
|
-
const
|
|
969
|
+
const [messages, setMessages] = useState2([]);
|
|
970
|
+
const [failure, setFailure] = useState2(void 0);
|
|
971
|
+
const [loadFailure, setLoadFailure] = useState2(void 0);
|
|
972
|
+
const [pendingLocal, setPendingLocal] = useState2([]);
|
|
973
|
+
const loadMessagesRef = useRef2(loadMessages);
|
|
974
|
+
const bottomRef = useRef2(null);
|
|
628
975
|
loadMessagesRef.current = loadMessages;
|
|
629
|
-
const refresh =
|
|
976
|
+
const refresh = useCallback2(async () => {
|
|
630
977
|
try {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
978
|
+
const loaded = await loadMessagesRef.current(conversationId);
|
|
979
|
+
setMessages(loaded);
|
|
980
|
+
setLoadFailure(void 0);
|
|
981
|
+
if (loaded.length > 0) setPendingLocal([]);
|
|
982
|
+
} catch (error) {
|
|
983
|
+
if (isNotFound(error)) {
|
|
984
|
+
setMessages([]);
|
|
985
|
+
setLoadFailure(void 0);
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
setLoadFailure(describeLoadFailure(error));
|
|
634
989
|
}
|
|
635
990
|
}, [conversationId]);
|
|
636
991
|
useEffect(() => {
|
|
@@ -647,42 +1002,105 @@ function ConversationPreview({
|
|
|
647
1002
|
source.close();
|
|
648
1003
|
};
|
|
649
1004
|
}, [sse, conversationId, refresh]);
|
|
1005
|
+
useEffect(() => {
|
|
1006
|
+
if (!pollIntervalMs) return;
|
|
1007
|
+
const timer = setInterval(() => void refresh(), pollIntervalMs);
|
|
1008
|
+
return () => clearInterval(timer);
|
|
1009
|
+
}, [pollIntervalMs, refresh]);
|
|
650
1010
|
useEffect(() => {
|
|
651
1011
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
652
1012
|
}, [messages]);
|
|
653
|
-
const rendered = useMemo(() => decorate(messages), [messages]);
|
|
1013
|
+
const rendered = useMemo(() => decorate([...messages, ...pendingLocal]), [messages, pendingLocal]);
|
|
1014
|
+
async function refreshWithFollowUps() {
|
|
1015
|
+
await refresh();
|
|
1016
|
+
for (const atraso of FOLLOW_UP_REFRESH_MS) {
|
|
1017
|
+
setTimeout(() => void refresh(), atraso);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
654
1020
|
async function handleSend(text) {
|
|
655
1021
|
setFailure(void 0);
|
|
656
1022
|
try {
|
|
657
1023
|
await client.sendText(text);
|
|
658
|
-
|
|
1024
|
+
setPendingLocal((current) => [
|
|
1025
|
+
...current,
|
|
1026
|
+
{
|
|
1027
|
+
id: `local-${current.length}-${text.length}`,
|
|
1028
|
+
type: "text",
|
|
1029
|
+
content: text,
|
|
1030
|
+
// Do ponto de vista do servidor, mensagem do cliente é inbound — é assim que ela aparece
|
|
1031
|
+
// como "minha" nesta visão.
|
|
1032
|
+
direction: "inbound",
|
|
1033
|
+
sender: "customer",
|
|
1034
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1035
|
+
status: "sent"
|
|
1036
|
+
}
|
|
1037
|
+
]);
|
|
1038
|
+
await refreshWithFollowUps();
|
|
659
1039
|
} catch (error) {
|
|
660
1040
|
setFailure(error instanceof Error ? error.message : "Falha ao entregar a mensagem no webhook.");
|
|
661
1041
|
}
|
|
662
1042
|
}
|
|
1043
|
+
async function handleInteractiveSelect(selection) {
|
|
1044
|
+
setFailure(void 0);
|
|
1045
|
+
const reply = { id: selection.option.id, title: selection.option.title };
|
|
1046
|
+
try {
|
|
1047
|
+
await (selection.kind === "button" ? client.sendButtonReply(reply) : client.sendListReply(reply));
|
|
1048
|
+
await refreshWithFollowUps();
|
|
1049
|
+
} catch (error) {
|
|
1050
|
+
setFailure(error instanceof Error ? error.message : "Falha ao entregar a resposta no webhook.");
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
async function handleAttach(file) {
|
|
1054
|
+
if (!uploadMedia) return;
|
|
1055
|
+
setFailure(void 0);
|
|
1056
|
+
try {
|
|
1057
|
+
const uploaded = await uploadMedia(file);
|
|
1058
|
+
await client.sendMedia({
|
|
1059
|
+
mediaType: mediaTypeOf(uploaded.mimeType ?? file.type),
|
|
1060
|
+
mediaId: uploaded.mediaId,
|
|
1061
|
+
mimeType: uploaded.mimeType ?? file.type,
|
|
1062
|
+
filename: uploaded.filename ?? file.name
|
|
1063
|
+
});
|
|
1064
|
+
await refreshWithFollowUps();
|
|
1065
|
+
} catch (error) {
|
|
1066
|
+
setFailure(error instanceof Error ? error.message : "Falha ao enviar o arquivo.");
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
663
1069
|
return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
664
1070
|
/* @__PURE__ */ jsxs(ConversationWallpaper, { className: "flex-1 min-h-0 overflow-y-auto px-4 py-3", children: [
|
|
665
1071
|
rendered.map(({ message, isFirstInGroup, showDateDivider }) => /* @__PURE__ */ jsxs("div", { children: [
|
|
666
|
-
showDateDivider ? /* @__PURE__ */
|
|
667
|
-
/* @__PURE__ */
|
|
1072
|
+
showDateDivider ? /* @__PURE__ */ jsx2(DateDivider, { iso: message.timestamp }) : null,
|
|
1073
|
+
/* @__PURE__ */ jsx2(
|
|
668
1074
|
MessageBubble,
|
|
669
1075
|
{
|
|
670
1076
|
message,
|
|
671
1077
|
isMine: message.direction === "inbound",
|
|
672
|
-
isFirstInGroup
|
|
1078
|
+
isFirstInGroup,
|
|
1079
|
+
onInteractiveSelect: message.direction === "outbound" ? (selection) => void handleInteractiveSelect(selection) : void 0
|
|
673
1080
|
}
|
|
674
1081
|
)
|
|
675
1082
|
] }, message.id)),
|
|
676
|
-
/* @__PURE__ */
|
|
1083
|
+
/* @__PURE__ */ jsx2("div", { ref: bottomRef })
|
|
677
1084
|
] }),
|
|
678
|
-
failure ? /* @__PURE__ */
|
|
679
|
-
/* @__PURE__ */
|
|
680
|
-
|
|
681
|
-
{
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
1085
|
+
failure ? /* @__PURE__ */ jsx2("p", { role: "alert", className: "px-4 py-2 text-sm text-red-600 dark:text-red-400", children: failure }) : null,
|
|
1086
|
+
loadFailure ? /* @__PURE__ */ jsx2("p", { role: "status", className: "px-4 py-2 text-sm text-amber-700 dark:text-amber-400", children: loadFailure }) : null,
|
|
1087
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-1", children: [
|
|
1088
|
+
/* @__PURE__ */ jsx2("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx2(
|
|
1089
|
+
MessageComposer,
|
|
1090
|
+
{
|
|
1091
|
+
onSend: (text) => void handleSend(text),
|
|
1092
|
+
onAttach: uploadMedia ? (file) => void handleAttach(file) : void 0,
|
|
1093
|
+
placeholder: placeholder ?? "Escreva como o cliente\u2026"
|
|
1094
|
+
}
|
|
1095
|
+
) }),
|
|
1096
|
+
uploadMedia ? /* @__PURE__ */ jsx2(
|
|
1097
|
+
AudioRecorderButton,
|
|
1098
|
+
{
|
|
1099
|
+
onRecorded: (file) => void handleAttach(file),
|
|
1100
|
+
onFailure: (message) => setFailure(message)
|
|
1101
|
+
}
|
|
1102
|
+
) : null
|
|
1103
|
+
] })
|
|
686
1104
|
] });
|
|
687
1105
|
}
|
|
688
1106
|
|
|
@@ -690,6 +1108,7 @@ function ConversationPreview({
|
|
|
690
1108
|
import {
|
|
691
1109
|
buildInboundAudioPayload,
|
|
692
1110
|
buildInboundInteractivePayload,
|
|
1111
|
+
buildInboundMediaPayload,
|
|
693
1112
|
buildInboundTextPayload,
|
|
694
1113
|
serializeWebhookPayload
|
|
695
1114
|
} from "@adatechnology/meta-whatsapp-contracts/testing";
|
|
@@ -709,7 +1128,7 @@ var PreviewWebhookRejectedError = class extends Error {
|
|
|
709
1128
|
function assertPreviewEnvironment(isProduction) {
|
|
710
1129
|
if (isProduction) throw new PreviewInProductionError();
|
|
711
1130
|
}
|
|
712
|
-
async function
|
|
1131
|
+
async function signPreviewPayload(params) {
|
|
713
1132
|
const encoder = new TextEncoder();
|
|
714
1133
|
const key = await globalThis.crypto.subtle.importKey(
|
|
715
1134
|
"raw",
|
|
@@ -721,6 +1140,7 @@ async function signWithWebCrypto(params) {
|
|
|
721
1140
|
const signature = await globalThis.crypto.subtle.sign("HMAC", key, encoder.encode(params.rawBody));
|
|
722
1141
|
return `sha256=${[...new Uint8Array(signature)].map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
723
1142
|
}
|
|
1143
|
+
var signWithWebCrypto = signPreviewPayload;
|
|
724
1144
|
function createPreviewWebhookClient(params) {
|
|
725
1145
|
const sendPayload = async (payload) => {
|
|
726
1146
|
const rawBody = serializeWebhookPayload(payload);
|
|
@@ -738,7 +1158,8 @@ function createPreviewWebhookClient(params) {
|
|
|
738
1158
|
sendText: (text) => sendPayload(buildInboundTextPayload({ ...envelope, text })),
|
|
739
1159
|
sendButtonReply: (reply) => sendPayload(buildInboundInteractivePayload({ ...envelope, buttonReply: reply })),
|
|
740
1160
|
sendListReply: (reply) => sendPayload(buildInboundInteractivePayload({ ...envelope, listReply: reply })),
|
|
741
|
-
sendAudio: (mediaId) => sendPayload(buildInboundAudioPayload({ ...envelope, mediaId }))
|
|
1161
|
+
sendAudio: (mediaId) => sendPayload(buildInboundAudioPayload({ ...envelope, mediaId })),
|
|
1162
|
+
sendMedia: (media) => sendPayload(buildInboundMediaPayload({ ...envelope, ...media }))
|
|
742
1163
|
};
|
|
743
1164
|
}
|
|
744
1165
|
|
|
@@ -777,12 +1198,67 @@ function startPreviewScript(params) {
|
|
|
777
1198
|
}, intervalMs);
|
|
778
1199
|
return () => clearInterval(timer);
|
|
779
1200
|
}
|
|
1201
|
+
|
|
1202
|
+
// src/preview/MediaTypesPreview.tsx
|
|
1203
|
+
import { useMemo as useMemo2 } from "react";
|
|
1204
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1205
|
+
var MEDIA_TYPES_CONVERSATION_ID = "5511944443333";
|
|
1206
|
+
function MediaTypesPreview({
|
|
1207
|
+
conversationId = MEDIA_TYPES_CONVERSATION_ID,
|
|
1208
|
+
className
|
|
1209
|
+
}) {
|
|
1210
|
+
const store = useMemo2(
|
|
1211
|
+
() => createPreviewStore({ conversations: PREVIEW_CONVERSATIONS, messages: PREVIEW_MESSAGES }),
|
|
1212
|
+
[]
|
|
1213
|
+
);
|
|
1214
|
+
const api = useMemo2(() => createMockConversationsApi({ store }), [store]);
|
|
1215
|
+
const sse = useMemo2(() => createMockSSEProvider({ store }), [store]);
|
|
1216
|
+
const messages = PREVIEW_MESSAGES[conversationId] ?? [];
|
|
1217
|
+
const documents = PREVIEW_DOCUMENTS[conversationId] ?? [];
|
|
1218
|
+
const mimeTypes = [...new Set(documents.map((document) => document.mimeType))];
|
|
1219
|
+
return /* @__PURE__ */ jsx3(ConversationsProvider, { api, sse, children: /* @__PURE__ */ jsxs2("div", { className, children: [
|
|
1220
|
+
/* @__PURE__ */ jsxs2("header", { className: "border-b px-4 py-3 dark:border-gray-700", children: [
|
|
1221
|
+
/* @__PURE__ */ jsx3("h1", { className: "text-lg font-semibold", children: "Teste manual de m\xEDdia" }),
|
|
1222
|
+
/* @__PURE__ */ jsxs2("p", { className: "text-sm text-gray-500", children: [
|
|
1223
|
+
documents.length,
|
|
1224
|
+
" arquivos, ",
|
|
1225
|
+
mimeTypes.length,
|
|
1226
|
+
" tipos. Clique no olho para abrir em aba nova e no bot\xE3o da bolha para carregar a m\xEDdia na thread \u2014 \xE9 o que teste automatizado n\xE3o v\xEA."
|
|
1227
|
+
] })
|
|
1228
|
+
] }),
|
|
1229
|
+
/* @__PURE__ */ jsxs2("div", { className: "grid gap-4 p-4 lg:grid-cols-2", children: [
|
|
1230
|
+
/* @__PURE__ */ jsxs2("section", { className: "space-y-3", children: [
|
|
1231
|
+
/* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold uppercase tracking-wide text-gray-500", children: "Biblioteca da empresa" }),
|
|
1232
|
+
/* @__PURE__ */ jsx3(DocumentsLibrary, { perPage: documents.length || 20 })
|
|
1233
|
+
] }),
|
|
1234
|
+
/* @__PURE__ */ jsxs2("section", { className: "space-y-3", children: [
|
|
1235
|
+
/* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold uppercase tracking-wide text-gray-500", children: "Painel da conversa" }),
|
|
1236
|
+
/* @__PURE__ */ jsx3(ConversationDocumentsPanel, { conversationId, open: true, perPage: documents.length || 20 }),
|
|
1237
|
+
/* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold uppercase tracking-wide text-gray-500", children: "Bolhas na thread" }),
|
|
1238
|
+
/* @__PURE__ */ jsx3(ConversationWallpaper, { className: "max-h-[70vh] overflow-y-auto rounded-lg px-3 py-2", children: messages.map((message, index) => /* @__PURE__ */ jsx3(
|
|
1239
|
+
MessageBubble,
|
|
1240
|
+
{
|
|
1241
|
+
message,
|
|
1242
|
+
isMine: message.direction === "outbound",
|
|
1243
|
+
isFirstInGroup: index === 0 || messages[index - 1]?.sender !== message.sender
|
|
1244
|
+
},
|
|
1245
|
+
message.id
|
|
1246
|
+
)) })
|
|
1247
|
+
] })
|
|
1248
|
+
] })
|
|
1249
|
+
] }) });
|
|
1250
|
+
}
|
|
780
1251
|
export {
|
|
1252
|
+
AudioRecorderButton,
|
|
781
1253
|
ConversationPreview,
|
|
1254
|
+
DEFAULT_AUDIO_RECORDER_BUTTON_LABELS,
|
|
782
1255
|
DEFAULT_PREVIEW_SCRIPT,
|
|
783
1256
|
GLOBAL_CHANNEL,
|
|
1257
|
+
MEDIA_TYPES_CONVERSATION_ID,
|
|
1258
|
+
MediaTypesPreview,
|
|
784
1259
|
PREVIEW_CONVERSATIONS,
|
|
785
1260
|
PREVIEW_DOCUMENTS,
|
|
1261
|
+
PREVIEW_FILE_SAMPLES,
|
|
786
1262
|
PREVIEW_MESSAGES,
|
|
787
1263
|
PreviewInProductionError,
|
|
788
1264
|
PreviewWebhookRejectedError,
|
|
@@ -791,7 +1267,13 @@ export {
|
|
|
791
1267
|
createMockConversationsApi,
|
|
792
1268
|
createMockEventSource,
|
|
793
1269
|
createMockSSEProvider,
|
|
1270
|
+
createPreviewMediaResolver,
|
|
794
1271
|
createPreviewStore,
|
|
795
1272
|
createPreviewWebhookClient,
|
|
1273
|
+
mediaTypeOf,
|
|
1274
|
+
previewFileBase64,
|
|
1275
|
+
previewFileUrl,
|
|
1276
|
+
resolvePreviewFileSample,
|
|
1277
|
+
signPreviewPayload,
|
|
796
1278
|
startPreviewScript
|
|
797
1279
|
};
|