@acorex/components 22.1.0-next.14 → 22.1.0-next.16
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/fesm2022/acorex-components-conversation.mjs +744 -484
- package/fesm2022/acorex-components-conversation.mjs.map +1 -1
- package/fesm2022/acorex-components-data-table.mjs +8 -6
- package/fesm2022/acorex-components-data-table.mjs.map +1 -1
- package/fesm2022/acorex-components-lookup.mjs +490 -29
- package/fesm2022/acorex-components-lookup.mjs.map +1 -1
- package/fesm2022/acorex-components-notification.mjs +4 -6
- package/fesm2022/acorex-components-notification.mjs.map +1 -1
- package/lookup/README.md +18 -7
- package/package.json +3 -3
- package/types/acorex-components-conversation.d.ts +166 -245
- package/types/acorex-components-data-table.d.ts +2 -2
- package/types/acorex-components-lookup.d.ts +130 -13
|
@@ -51,8 +51,11 @@ import { HttpClient } from '@angular/common/http';
|
|
|
51
51
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
+
|
|
54
55
|
* Shared API Types
|
|
56
|
+
|
|
55
57
|
* Common types used across all API services
|
|
58
|
+
|
|
56
59
|
*/
|
|
57
60
|
|
|
58
61
|
/**
|
|
@@ -61,18 +64,12 @@ import { DomSanitizer } from '@angular/platform-browser';
|
|
|
61
64
|
*/
|
|
62
65
|
|
|
63
66
|
/**
|
|
64
|
-
|
|
65
67
|
* Default Configuration Values
|
|
66
|
-
|
|
67
68
|
* Centralized defaults to avoid magic numbers throughout the codebase
|
|
68
|
-
|
|
69
69
|
*/
|
|
70
70
|
/**
|
|
71
|
-
|
|
72
71
|
* Default conversation configuration
|
|
73
|
-
|
|
74
72
|
* All values are explicitly defined here for easy maintenance and documentation
|
|
75
|
-
|
|
76
73
|
*/
|
|
77
74
|
const AX_DEFAULT_CONVERSATION_CONFIG = {
|
|
78
75
|
// Pagination
|
|
@@ -83,7 +80,8 @@ const AX_DEFAULT_CONVERSATION_CONFIG = {
|
|
|
83
80
|
infiniteScrollThreshold: 200,
|
|
84
81
|
// Timeout Durations (milliseconds)
|
|
85
82
|
typingIndicatorTimeout: 3000,
|
|
86
|
-
typingIndicatorThrottle:
|
|
83
|
+
typingIndicatorThrottle: 3000,
|
|
84
|
+
typingDisplayDuration: 4000,
|
|
87
85
|
messageHighlightDuration: 2000,
|
|
88
86
|
debounceSearch: 300,
|
|
89
87
|
// Message Storage Limits
|
|
@@ -102,7 +100,7 @@ const AX_DEFAULT_CONVERSATION_CONFIG = {
|
|
|
102
100
|
maxFilesPerMessage: 3,
|
|
103
101
|
// Intersection Observer
|
|
104
102
|
messageReadThreshold: 0.3,
|
|
105
|
-
messageReadDebounce:
|
|
103
|
+
messageReadDebounce: 3000,
|
|
106
104
|
markConversationReadOnSelect: true,
|
|
107
105
|
// Message list
|
|
108
106
|
messageListBackground: '',
|
|
@@ -112,15 +110,10 @@ const AX_DEFAULT_CONVERSATION_CONFIG = {
|
|
|
112
110
|
debugApiLogging: false,
|
|
113
111
|
};
|
|
114
112
|
/**
|
|
115
|
-
|
|
116
113
|
* Helper function to merge user config with defaults
|
|
117
|
-
|
|
118
114
|
* Properly handles array merging to avoid reference issues
|
|
119
|
-
|
|
120
115
|
* @param userConfig - User-provided configuration
|
|
121
|
-
|
|
122
116
|
* @returns Merged configuration with all required fields
|
|
123
|
-
|
|
124
117
|
*/
|
|
125
118
|
function mergeWithDefaults(userConfig) {
|
|
126
119
|
if (!userConfig) {
|
|
@@ -525,220 +518,87 @@ function resolveConversationMessageFileType(type, fileType) {
|
|
|
525
518
|
return fileType ?? AX_CONVERSATION_MESSAGE_TYPE_FILE_TYPE[type];
|
|
526
519
|
}
|
|
527
520
|
|
|
521
|
+
/**
|
|
522
|
+
* Message Utilities Service
|
|
523
|
+
* Helper functions for message formatting and display
|
|
524
|
+
*/
|
|
528
525
|
class AXConversationMessageUtilsService {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
const normalized = value.trim();
|
|
538
|
-
return normalized.length > 0 ? normalized : undefined;
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Get conversation avatar image URL.
|
|
542
|
-
*/
|
|
543
|
-
static getConversationAvatar(conversation) {
|
|
544
|
-
return AXConversationMessageUtilsService.normalizeOptionalMediaValue(conversation.avatar);
|
|
526
|
+
static getInitials(name) {
|
|
527
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
528
|
+
if (parts.length === 0)
|
|
529
|
+
return '?';
|
|
530
|
+
if (parts.length === 1)
|
|
531
|
+
return parts[0].charAt(0).toUpperCase();
|
|
532
|
+
return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
|
|
545
533
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
if (
|
|
551
|
-
return
|
|
552
|
-
}
|
|
553
|
-
const explicit = AXConversationMessageUtilsService.normalizeOptionalMediaValue(conversation.icon);
|
|
554
|
-
if (explicit) {
|
|
555
|
-
return explicit;
|
|
556
|
-
}
|
|
557
|
-
if (conversation.type === 'group') {
|
|
558
|
-
return AX_CONVERSATION_DEFAULT_GROUP_ICON;
|
|
534
|
+
static getMessageText(message) {
|
|
535
|
+
const payload = message.payload;
|
|
536
|
+
if (!payload)
|
|
537
|
+
return '';
|
|
538
|
+
if (payload.type === 'text' && 'text' in payload && typeof payload.text === 'string') {
|
|
539
|
+
return payload.text;
|
|
559
540
|
}
|
|
560
|
-
if (
|
|
561
|
-
return
|
|
541
|
+
if ('caption' in payload && typeof payload.caption === 'string') {
|
|
542
|
+
return payload.caption;
|
|
562
543
|
}
|
|
563
|
-
return
|
|
544
|
+
return '';
|
|
564
545
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
return undefined;
|
|
546
|
+
static getPreviewText(message, maxLength) {
|
|
547
|
+
const type = message.type;
|
|
548
|
+
let text = AXConversationMessageUtilsService.getMessageText(message);
|
|
549
|
+
if (maxLength && text.length > maxLength) {
|
|
550
|
+
text = text.substring(0, maxLength) + '...';
|
|
571
551
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
552
|
+
switch (type) {
|
|
553
|
+
case 'image':
|
|
554
|
+
return { value: text, type: 'image', icon: 'fa-light fa-image' };
|
|
555
|
+
case 'video':
|
|
556
|
+
return { value: text, type: 'video', icon: 'fa-light fa-video' };
|
|
557
|
+
case 'audio':
|
|
558
|
+
case 'voice':
|
|
559
|
+
return { value: text, type: type, icon: 'fa-light fa-microphone' };
|
|
560
|
+
case 'file':
|
|
561
|
+
return { value: text, type: 'file', icon: 'fa-light fa-file' };
|
|
562
|
+
case 'location':
|
|
563
|
+
return { value: text, type: 'location', icon: 'fa-light fa-location-dot' };
|
|
564
|
+
case 'sticker':
|
|
565
|
+
return { value: text, type: 'sticker', icon: 'fa-light fa-note-sticky' };
|
|
566
|
+
default:
|
|
567
|
+
return { value: text, type: 'text', icon: 'fa-light fa-message' };
|
|
575
568
|
}
|
|
576
|
-
return AX_CONVERSATION_DEFAULT_USER_ICON;
|
|
577
569
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
570
|
+
static isOwnMessage(message, currentUserId) {
|
|
571
|
+
return message.senderId === currentUserId;
|
|
572
|
+
}
|
|
581
573
|
static getSenderName(message, conversation) {
|
|
582
574
|
const participant = conversation.participants.find((p) => p.id === message.senderId);
|
|
583
|
-
return participant?.name
|
|
575
|
+
return participant?.name ?? translateSync('@acorex:chat.fallbacks.unknown-user');
|
|
584
576
|
}
|
|
585
|
-
/**
|
|
586
|
-
* Get sender avatar image URL (takes precedence over {@link getSenderAvatarIcon}).
|
|
587
|
-
*/
|
|
588
577
|
static getSenderAvatar(message, conversation) {
|
|
589
|
-
|
|
590
|
-
return AXConversationMessageUtilsService.normalizeOptionalMediaValue(participant?.avatar);
|
|
578
|
+
return conversation.participants.find((p) => p.id === message.senderId)?.avatar;
|
|
591
579
|
}
|
|
592
|
-
/**
|
|
593
|
-
* Font Awesome icon class(es) for the sender when there is no avatar image:
|
|
594
|
-
* participant `icon` first, then conversation-level `icon`.
|
|
595
|
-
*/
|
|
596
580
|
static getSenderAvatarIcon(message, conversation) {
|
|
597
|
-
|
|
598
|
-
if (AXConversationMessageUtilsService.normalizeOptionalMediaValue(participant?.avatar)) {
|
|
599
|
-
return undefined;
|
|
600
|
-
}
|
|
601
|
-
return (AXConversationMessageUtilsService.getParticipantAvatarIcon(participant) ??
|
|
602
|
-
AXConversationMessageUtilsService.getConversationAvatarIcon(conversation));
|
|
581
|
+
return conversation.participants.find((p) => p.id === message.senderId)?.icon;
|
|
603
582
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
static getInitials(name) {
|
|
608
|
-
if (!name)
|
|
609
|
-
return '?';
|
|
610
|
-
return name
|
|
611
|
-
.split(' ')
|
|
612
|
-
.map((n) => n[0])
|
|
613
|
-
.join('')
|
|
614
|
-
.toUpperCase()
|
|
615
|
-
.substring(0, 2);
|
|
583
|
+
static getConversationAvatar(conversation) {
|
|
584
|
+
const avatar = conversation.avatar?.trim();
|
|
585
|
+
return avatar && avatar.length > 0 ? avatar : undefined;
|
|
616
586
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
static isTextPayload(payload) {
|
|
621
|
-
return 'text' in payload && typeof payload.text === 'string';
|
|
587
|
+
static getConversationAvatarIcon(conversation) {
|
|
588
|
+
const icon = conversation.icon?.trim();
|
|
589
|
+
return icon && icon.length > 0 ? icon : undefined;
|
|
622
590
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
*/
|
|
626
|
-
static getMessageText(message) {
|
|
627
|
-
if (message.type === 'text' && AXConversationMessageUtilsService.isTextPayload(message.payload)) {
|
|
628
|
-
return message.payload.text;
|
|
629
|
-
}
|
|
630
|
-
return `[${message.type}]`;
|
|
591
|
+
static getStatusIcon(message) {
|
|
592
|
+
return AXConversationMessageUtilsService.getDeliveryStatusIcon(message.status);
|
|
631
593
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
static getPreviewText(message, maxLength = 50) {
|
|
636
|
-
// Handle different message types
|
|
637
|
-
switch (message.type) {
|
|
638
|
-
case 'text': {
|
|
639
|
-
const textPayload = message.payload;
|
|
640
|
-
const text = textPayload.text || '';
|
|
641
|
-
const truncatedText = text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
|
|
642
|
-
return {
|
|
643
|
-
value: truncatedText,
|
|
644
|
-
type: 'text',
|
|
645
|
-
icon: 'fa-light fa-message',
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
case 'image': {
|
|
649
|
-
const imagePayload = message.payload;
|
|
650
|
-
const images = Array.isArray(imagePayload.images) ? imagePayload.images : [];
|
|
651
|
-
const first = images[0];
|
|
652
|
-
const label = imagePayload.caption?.trim() ||
|
|
653
|
-
(images.length > 1 ? `${images.length} images` : '');
|
|
654
|
-
return {
|
|
655
|
-
value: label || first?.thumbnailUrl || first?.url || '',
|
|
656
|
-
type: 'image',
|
|
657
|
-
icon: 'fa-light fa-image',
|
|
658
|
-
};
|
|
659
|
-
}
|
|
660
|
-
case 'video': {
|
|
661
|
-
const videoPayload = message.payload;
|
|
662
|
-
const videos = Array.isArray(videoPayload.videos) ? videoPayload.videos : [];
|
|
663
|
-
const first = videos[0];
|
|
664
|
-
const label = videoPayload.caption?.trim() ||
|
|
665
|
-
(videos.length > 1 ? `${videos.length} videos` : '');
|
|
666
|
-
return {
|
|
667
|
-
value: label || first?.url || '',
|
|
668
|
-
type: 'video',
|
|
669
|
-
icon: 'fa-light fa-video',
|
|
670
|
-
};
|
|
671
|
-
}
|
|
672
|
-
case 'audio': {
|
|
673
|
-
const audioPayload = message.payload;
|
|
674
|
-
const audios = Array.isArray(audioPayload.audios) ? audioPayload.audios : [];
|
|
675
|
-
const names = audios.map((a) => a.title).filter(Boolean).join(', ');
|
|
676
|
-
const first = audios[0];
|
|
677
|
-
const label = audioPayload.caption?.trim() ||
|
|
678
|
-
(audios.length > 1 ? `${audios.length} audio files` : names);
|
|
679
|
-
return {
|
|
680
|
-
value: label || first?.url || '',
|
|
681
|
-
type: 'audio',
|
|
682
|
-
icon: 'fa-light fa-music',
|
|
683
|
-
};
|
|
684
|
-
}
|
|
685
|
-
case 'voice': {
|
|
686
|
-
const voicePayload = message.payload;
|
|
687
|
-
return {
|
|
688
|
-
value: voicePayload.url || '',
|
|
689
|
-
type: 'voice',
|
|
690
|
-
icon: 'fa-light fa-microphone',
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
case 'file': {
|
|
694
|
-
const filePayload = message.payload;
|
|
695
|
-
const files = Array.isArray(filePayload.files) ? filePayload.files : [];
|
|
696
|
-
const names = files.map((f) => f.name).join(', ');
|
|
697
|
-
const label = filePayload.caption?.trim() ||
|
|
698
|
-
(files.length > 1 ? `${files.length} files` : names);
|
|
699
|
-
return {
|
|
700
|
-
value: label || names,
|
|
701
|
-
type: 'file',
|
|
702
|
-
icon: 'fa-light fa-file',
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
case 'location': {
|
|
706
|
-
const locationPayload = message.payload;
|
|
707
|
-
return {
|
|
708
|
-
value: locationPayload.latitude && locationPayload.longitude
|
|
709
|
-
? `${locationPayload.latitude},${locationPayload.longitude}`
|
|
710
|
-
: '',
|
|
711
|
-
type: 'location',
|
|
712
|
-
icon: 'fa-light fa-location-dot',
|
|
713
|
-
};
|
|
714
|
-
}
|
|
715
|
-
case 'sticker': {
|
|
716
|
-
const stickerPayload = message.payload;
|
|
717
|
-
return {
|
|
718
|
-
value: stickerPayload.url || '',
|
|
719
|
-
type: 'sticker',
|
|
720
|
-
icon: 'fa-light fa-face-smile',
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
default:
|
|
724
|
-
return {
|
|
725
|
-
value: '',
|
|
726
|
-
type: message.type,
|
|
727
|
-
icon: 'fa-light fa-message',
|
|
728
|
-
};
|
|
594
|
+
static getConversationStatus(conversation, presence) {
|
|
595
|
+
if (conversation.type !== 'private') {
|
|
596
|
+
return undefined;
|
|
729
597
|
}
|
|
598
|
+
return presence?.status;
|
|
730
599
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
*/
|
|
734
|
-
static isOwnMessage(message, currentUserId) {
|
|
735
|
-
return message.senderId === currentUserId;
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* Get message status icon class (Font Awesome)
|
|
739
|
-
*/
|
|
740
|
-
static getStatusIcon(message) {
|
|
741
|
-
switch (message.status) {
|
|
600
|
+
static getDeliveryStatusIcon(status) {
|
|
601
|
+
switch (status) {
|
|
742
602
|
case 'sending':
|
|
743
603
|
return 'fa-light fa-clock';
|
|
744
604
|
case 'sent':
|
|
@@ -750,67 +610,34 @@ class AXConversationMessageUtilsService {
|
|
|
750
610
|
case 'failed':
|
|
751
611
|
return 'fa-light fa-circle-exclamation';
|
|
752
612
|
default:
|
|
753
|
-
return '
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
/**
|
|
757
|
-
* Check if message should show avatar
|
|
758
|
-
*/
|
|
759
|
-
static shouldShowAvatar(message, previousMessage, conversation) {
|
|
760
|
-
// Always show avatar for group conversations
|
|
761
|
-
if (conversation.type === 'group' || conversation.type === 'channel') {
|
|
762
|
-
// Don't show if same sender as previous message within 5 minutes
|
|
763
|
-
if (previousMessage && previousMessage.senderId === message.senderId) {
|
|
764
|
-
const timeDiff = message.timestamp.getTime() - previousMessage.timestamp.getTime();
|
|
765
|
-
return timeDiff > 5 * 60 * 1000; // 5 minutes
|
|
766
|
-
}
|
|
767
|
-
return true;
|
|
613
|
+
return '';
|
|
768
614
|
}
|
|
769
|
-
return false;
|
|
770
615
|
}
|
|
771
|
-
|
|
772
|
-
* Group messages by sender for consecutive messages
|
|
773
|
-
*/
|
|
774
|
-
static shouldGroupWithPrevious(message, previousMessage) {
|
|
616
|
+
static shouldGroupMessages(message, previousMessage) {
|
|
775
617
|
if (!previousMessage)
|
|
776
618
|
return false;
|
|
777
|
-
// Same sender
|
|
778
619
|
if (message.senderId !== previousMessage.senderId)
|
|
779
620
|
return false;
|
|
780
|
-
// Within 5 minutes
|
|
781
621
|
const timeDiff = message.timestamp.getTime() - previousMessage.timestamp.getTime();
|
|
782
622
|
return timeDiff < 5 * 60 * 1000;
|
|
783
623
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
*/
|
|
787
|
-
static getConversationStatus(conversation) {
|
|
788
|
-
if (conversation.type === 'private') {
|
|
789
|
-
return conversation.status.presence;
|
|
790
|
-
}
|
|
791
|
-
return undefined;
|
|
624
|
+
static getUserPresenceStatus(presence) {
|
|
625
|
+
return presence?.status;
|
|
792
626
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
*/
|
|
796
|
-
static getTypingText(conversation) {
|
|
797
|
-
const typingUsers = conversation.status.typingUsers;
|
|
798
|
-
if (typingUsers.length === 0)
|
|
627
|
+
static getTypingText(conversation, typingUserIds) {
|
|
628
|
+
if (typingUserIds.length === 0)
|
|
799
629
|
return '';
|
|
800
630
|
if (conversation.type === 'private') {
|
|
801
631
|
return translateSync('@acorex:chat.status.typing');
|
|
802
632
|
}
|
|
803
|
-
const firstUser = conversation.participants.find((p) => p.id ===
|
|
804
|
-
if (
|
|
633
|
+
const firstUser = conversation.participants.find((p) => p.id === typingUserIds[0]);
|
|
634
|
+
if (typingUserIds.length === 1) {
|
|
805
635
|
return translateSync('@acorex:chat.status.user-is-typing', {
|
|
806
636
|
params: { userName: firstUser?.name || translateSync('@acorex:chat.fallbacks.someone') },
|
|
807
637
|
});
|
|
808
638
|
}
|
|
809
|
-
return translateSync('@acorex:chat.status.people-typing', { params: { count:
|
|
639
|
+
return translateSync('@acorex:chat.status.people-typing', { params: { count: typingUserIds.length } });
|
|
810
640
|
}
|
|
811
|
-
/**
|
|
812
|
-
* Format last seen time
|
|
813
|
-
*/
|
|
814
641
|
static formatLastSeen(date) {
|
|
815
642
|
const now = new Date();
|
|
816
643
|
const diff = now.getTime() - date.getTime();
|
|
@@ -825,24 +652,26 @@ class AXConversationMessageUtilsService {
|
|
|
825
652
|
return translateSync('@acorex:chat.time.days-ago', { params: { count: Math.floor(seconds / 86400) } });
|
|
826
653
|
return date.toLocaleDateString();
|
|
827
654
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
655
|
+
static getPrivateChatSubtitle(conversation, presence, currentUserId) {
|
|
656
|
+
const peerPresence = presence;
|
|
657
|
+
if (peerPresence?.status === 'online') {
|
|
658
|
+
return translateSync('@acorex:chat.status.online');
|
|
659
|
+
}
|
|
660
|
+
if (peerPresence?.lastSeen) {
|
|
661
|
+
return translateSync('@acorex:chat.status.last-seen', {
|
|
662
|
+
params: { value: AXConversationMessageUtilsService.formatLastSeen(peerPresence.lastSeen) },
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
return translateSync('@acorex:chat.status.offline');
|
|
666
|
+
}
|
|
667
|
+
static getConversationSubtitle(conversation, options) {
|
|
668
|
+
const typingUserIds = options?.typingUserIds ?? [];
|
|
669
|
+
if (typingUserIds.length > 0) {
|
|
670
|
+
return AXConversationMessageUtilsService.getTypingText(conversation, typingUserIds);
|
|
834
671
|
}
|
|
835
672
|
switch (conversation.type) {
|
|
836
673
|
case 'private':
|
|
837
|
-
|
|
838
|
-
return translateSync('@acorex:chat.status.online');
|
|
839
|
-
}
|
|
840
|
-
if (conversation.status.lastSeen) {
|
|
841
|
-
return translateSync('@acorex:chat.status.last-seen', {
|
|
842
|
-
params: { value: AXConversationMessageUtilsService.formatLastSeen(conversation.status.lastSeen) },
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
return translateSync('@acorex:chat.status.offline');
|
|
674
|
+
return AXConversationMessageUtilsService.getPrivateChatSubtitle(conversation, options?.peerPresence, options?.currentUserId);
|
|
846
675
|
case 'group':
|
|
847
676
|
return translateSync('@acorex:chat.members.count', { params: { count: conversation.participants.length } });
|
|
848
677
|
case 'channel':
|
|
@@ -1473,6 +1302,24 @@ async function toUploaderReference$2(payload) {
|
|
|
1473
1302
|
return mod.toUploaderReference(payload);
|
|
1474
1303
|
}
|
|
1475
1304
|
|
|
1305
|
+
/**
|
|
1306
|
+
* Per-user preferences for a specific conversation (mute, notifications, etc.).
|
|
1307
|
+
* Stored on the user account, keyed by conversation ID — not on the room entity.
|
|
1308
|
+
*/
|
|
1309
|
+
const AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES = {
|
|
1310
|
+
notifications: true,
|
|
1311
|
+
showPreview: true,
|
|
1312
|
+
};
|
|
1313
|
+
|
|
1314
|
+
function mergeRoomPreferences(preferences) {
|
|
1315
|
+
return {
|
|
1316
|
+
...AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES,
|
|
1317
|
+
...preferences,
|
|
1318
|
+
notifications: preferences?.notifications ?? AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES.notifications,
|
|
1319
|
+
showPreview: preferences?.showPreview ?? AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES.showPreview,
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1476
1323
|
/**
|
|
1477
1324
|
* In-memory conversation and message graph (signal-based).
|
|
1478
1325
|
* Plain class — not DI-registered; instantiated by `AXConversationService`.
|
|
@@ -1485,6 +1332,9 @@ class AXConversationState {
|
|
|
1485
1332
|
bumpInboxRevision() {
|
|
1486
1333
|
this._inboxRevision.update((revision) => revision + 1);
|
|
1487
1334
|
}
|
|
1335
|
+
bumpTypingRevision() {
|
|
1336
|
+
this._typingRevision.update((revision) => revision + 1);
|
|
1337
|
+
}
|
|
1488
1338
|
constructor(config) {
|
|
1489
1339
|
this.config = config;
|
|
1490
1340
|
this._conversations = signal(new Map(), /* @ts-ignore */
|
|
@@ -1493,15 +1343,34 @@ class AXConversationState {
|
|
|
1493
1343
|
...(ngDevMode ? [{ debugName: "_messages" }] : /* istanbul ignore next */ []));
|
|
1494
1344
|
this._conversationMessages = signal(new Map(), /* @ts-ignore */
|
|
1495
1345
|
...(ngDevMode ? [{ debugName: "_conversationMessages" }] : /* istanbul ignore next */ []));
|
|
1496
|
-
|
|
1346
|
+
this._userPresence = signal(new Map(), /* @ts-ignore */
|
|
1347
|
+
...(ngDevMode ? [{ debugName: "_userPresence" }] : /* istanbul ignore next */ []));
|
|
1348
|
+
this._typingExpiry = signal(new Map(), /* @ts-ignore */
|
|
1349
|
+
...(ngDevMode ? [{ debugName: "_typingExpiry" }] : /* istanbul ignore next */ []));
|
|
1350
|
+
this._roomPreferences = signal(new Map(), /* @ts-ignore */
|
|
1351
|
+
...(ngDevMode ? [{ debugName: "_roomPreferences" }] : /* istanbul ignore next */ []));
|
|
1352
|
+
this._presenceTimeTick = signal(0, /* @ts-ignore */
|
|
1353
|
+
...(ngDevMode ? [{ debugName: "_presenceTimeTick" }] : /* istanbul ignore next */ []));
|
|
1354
|
+
this._typingRevision = signal(0, /* @ts-ignore */
|
|
1355
|
+
...(ngDevMode ? [{ debugName: "_typingRevision" }] : /* istanbul ignore next */ []));
|
|
1497
1356
|
this._inboxRevision = signal(0, /* @ts-ignore */
|
|
1498
1357
|
...(ngDevMode ? [{ debugName: "_inboxRevision" }] : /* istanbul ignore next */ []));
|
|
1499
1358
|
this.conversations = computed(() => {
|
|
1500
1359
|
this._inboxRevision();
|
|
1501
|
-
|
|
1502
|
-
return Array.from(convMap.values());
|
|
1360
|
+
return Array.from(this._conversations().values());
|
|
1503
1361
|
}, /* @ts-ignore */
|
|
1504
1362
|
...(ngDevMode ? [{ debugName: "conversations" }] : /* istanbul ignore next */ []));
|
|
1363
|
+
this.userPresenceMap = computed(() => this._userPresence(), /* @ts-ignore */
|
|
1364
|
+
...(ngDevMode ? [{ debugName: "userPresenceMap" }] : /* istanbul ignore next */ []));
|
|
1365
|
+
this.presenceTimeTick = this._presenceTimeTick.asReadonly();
|
|
1366
|
+
this.typingRevision = computed(() => {
|
|
1367
|
+
this._typingRevision();
|
|
1368
|
+
return this._typingExpiry();
|
|
1369
|
+
}, /* @ts-ignore */
|
|
1370
|
+
...(ngDevMode ? [{ debugName: "typingRevision" }] : /* istanbul ignore next */ []));
|
|
1371
|
+
}
|
|
1372
|
+
bumpPresenceTimeTick() {
|
|
1373
|
+
this._presenceTimeTick.update((tick) => tick + 1);
|
|
1505
1374
|
}
|
|
1506
1375
|
setConversations(conversations) {
|
|
1507
1376
|
const convMap = new Map();
|
|
@@ -1560,6 +1429,12 @@ class AXConversationState {
|
|
|
1560
1429
|
newMap.delete(conversationId);
|
|
1561
1430
|
return newMap;
|
|
1562
1431
|
});
|
|
1432
|
+
this._typingExpiry.update((map) => {
|
|
1433
|
+
const next = new Map(map);
|
|
1434
|
+
next.delete(conversationId);
|
|
1435
|
+
return next;
|
|
1436
|
+
});
|
|
1437
|
+
this.bumpTypingRevision();
|
|
1563
1438
|
}
|
|
1564
1439
|
updateLastMessage(message) {
|
|
1565
1440
|
this.updateConversation(message.conversationId, {
|
|
@@ -1577,15 +1452,6 @@ class AXConversationState {
|
|
|
1577
1452
|
resetUnreadCount(conversationId) {
|
|
1578
1453
|
this.updateConversation(conversationId, { unreadCount: 0 });
|
|
1579
1454
|
}
|
|
1580
|
-
updateSettings(conversationId, settings) {
|
|
1581
|
-
const conversation = this._conversations().get(conversationId);
|
|
1582
|
-
if (!conversation)
|
|
1583
|
-
return;
|
|
1584
|
-
this.updateConversation(conversationId, {
|
|
1585
|
-
settings: { ...conversation.settings, ...settings },
|
|
1586
|
-
updatedAt: new Date(),
|
|
1587
|
-
});
|
|
1588
|
-
}
|
|
1589
1455
|
updateTitle(conversationId, title) {
|
|
1590
1456
|
this.updateConversation(conversationId, { title, updatedAt: new Date() });
|
|
1591
1457
|
}
|
|
@@ -1598,42 +1464,141 @@ class AXConversationState {
|
|
|
1598
1464
|
updatedAt: new Date(),
|
|
1599
1465
|
});
|
|
1600
1466
|
}
|
|
1601
|
-
|
|
1602
|
-
const
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1467
|
+
updateUserPresence(update) {
|
|
1468
|
+
const lastSeen = update.lastSeen instanceof Date
|
|
1469
|
+
? update.lastSeen
|
|
1470
|
+
: update.lastSeen
|
|
1471
|
+
? new Date(update.lastSeen)
|
|
1472
|
+
: undefined;
|
|
1473
|
+
this._userPresence.update((map) => {
|
|
1474
|
+
const next = new Map(map);
|
|
1475
|
+
next.set(update.userId, {
|
|
1476
|
+
userId: update.userId,
|
|
1477
|
+
status: update.status,
|
|
1478
|
+
lastSeen,
|
|
1479
|
+
statusText: update.statusText,
|
|
1480
|
+
updatedAt: new Date(),
|
|
1481
|
+
});
|
|
1482
|
+
return next;
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1485
|
+
bulkSetUserPresence(updates) {
|
|
1486
|
+
if (updates.length === 0)
|
|
1487
|
+
return;
|
|
1488
|
+
this._userPresence.update((map) => {
|
|
1489
|
+
const next = new Map(map);
|
|
1490
|
+
for (const update of updates) {
|
|
1491
|
+
const lastSeen = update.lastSeen instanceof Date
|
|
1492
|
+
? update.lastSeen
|
|
1493
|
+
: update.lastSeen
|
|
1494
|
+
? new Date(update.lastSeen)
|
|
1495
|
+
: undefined;
|
|
1496
|
+
next.set(update.userId, {
|
|
1497
|
+
userId: update.userId,
|
|
1498
|
+
status: update.status,
|
|
1499
|
+
lastSeen,
|
|
1500
|
+
statusText: update.statusText,
|
|
1501
|
+
updatedAt: new Date(),
|
|
1502
|
+
});
|
|
1609
1503
|
}
|
|
1610
|
-
|
|
1611
|
-
else {
|
|
1612
|
-
typingUsers = typingUsers.filter((id) => id !== userId);
|
|
1613
|
-
}
|
|
1614
|
-
this.updateConversation(conversationId, {
|
|
1615
|
-
status: {
|
|
1616
|
-
...conversation.status,
|
|
1617
|
-
isTyping: typingUsers.length > 0,
|
|
1618
|
-
typingUsers,
|
|
1619
|
-
},
|
|
1504
|
+
return next;
|
|
1620
1505
|
});
|
|
1621
1506
|
}
|
|
1622
|
-
|
|
1623
|
-
this.
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1507
|
+
getUserPresence(userId) {
|
|
1508
|
+
return this._userPresence().get(userId);
|
|
1509
|
+
}
|
|
1510
|
+
setTypingActive(conversationId, userId, displayDurationMs) {
|
|
1511
|
+
const expiresAt = Date.now() + displayDurationMs;
|
|
1512
|
+
this._typingExpiry.update((map) => {
|
|
1513
|
+
const next = new Map(map);
|
|
1514
|
+
const room = new Map(next.get(conversationId) ?? []);
|
|
1515
|
+
room.set(userId, expiresAt);
|
|
1516
|
+
next.set(conversationId, room);
|
|
1517
|
+
return next;
|
|
1518
|
+
});
|
|
1519
|
+
this.bumpTypingRevision();
|
|
1520
|
+
}
|
|
1521
|
+
clearTypingUser(conversationId, userId) {
|
|
1522
|
+
this._typingExpiry.update((map) => {
|
|
1523
|
+
const room = map.get(conversationId);
|
|
1524
|
+
if (!room?.has(userId)) {
|
|
1525
|
+
return map;
|
|
1526
|
+
}
|
|
1527
|
+
const next = new Map(map);
|
|
1528
|
+
const nextRoom = new Map(room);
|
|
1529
|
+
nextRoom.delete(userId);
|
|
1530
|
+
if (nextRoom.size === 0) {
|
|
1531
|
+
next.delete(conversationId);
|
|
1532
|
+
}
|
|
1533
|
+
else {
|
|
1534
|
+
next.set(conversationId, nextRoom);
|
|
1535
|
+
}
|
|
1536
|
+
return next;
|
|
1537
|
+
});
|
|
1538
|
+
this.bumpTypingRevision();
|
|
1539
|
+
}
|
|
1540
|
+
getActiveTypingUserIds(conversationId) {
|
|
1541
|
+
const now = Date.now();
|
|
1542
|
+
const room = this._typingExpiry().get(conversationId);
|
|
1543
|
+
if (!room)
|
|
1544
|
+
return [];
|
|
1545
|
+
const active = [];
|
|
1546
|
+
for (const [userId, expiresAt] of room) {
|
|
1547
|
+
if (expiresAt > now) {
|
|
1548
|
+
active.push(userId);
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
return active;
|
|
1552
|
+
}
|
|
1553
|
+
isAnyoneTyping(conversationId) {
|
|
1554
|
+
return this.getActiveTypingUserIds(conversationId).length > 0;
|
|
1555
|
+
}
|
|
1556
|
+
pruneExpiredTyping() {
|
|
1557
|
+
const now = Date.now();
|
|
1558
|
+
let changed = false;
|
|
1559
|
+
this._typingExpiry.update((map) => {
|
|
1560
|
+
const next = new Map();
|
|
1561
|
+
for (const [conversationId, room] of map) {
|
|
1562
|
+
const activeRoom = new Map();
|
|
1563
|
+
for (const [userId, expiresAt] of room) {
|
|
1564
|
+
if (expiresAt > now) {
|
|
1565
|
+
activeRoom.set(userId, expiresAt);
|
|
1566
|
+
}
|
|
1567
|
+
else {
|
|
1568
|
+
changed = true;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
if (activeRoom.size > 0) {
|
|
1572
|
+
next.set(conversationId, activeRoom);
|
|
1573
|
+
}
|
|
1574
|
+
else if (room.size > 0) {
|
|
1575
|
+
changed = true;
|
|
1634
1576
|
}
|
|
1635
1577
|
}
|
|
1636
|
-
return
|
|
1578
|
+
return changed ? next : map;
|
|
1579
|
+
});
|
|
1580
|
+
if (changed) {
|
|
1581
|
+
this.bumpTypingRevision();
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
setRoomPreferencesBulk(preferences) {
|
|
1585
|
+
this._roomPreferences.update(() => {
|
|
1586
|
+
const next = new Map();
|
|
1587
|
+
for (const [conversationId, prefs] of Object.entries(preferences)) {
|
|
1588
|
+
next.set(conversationId, mergeRoomPreferences(prefs));
|
|
1589
|
+
}
|
|
1590
|
+
return next;
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
getRoomPreferences(conversationId) {
|
|
1594
|
+
return this._roomPreferences().get(conversationId) ?? { ...AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES };
|
|
1595
|
+
}
|
|
1596
|
+
updateRoomPreferences(conversationId, updates) {
|
|
1597
|
+
this._roomPreferences.update((map) => {
|
|
1598
|
+
const next = new Map(map);
|
|
1599
|
+
const current = next.get(conversationId) ?? { ...AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES };
|
|
1600
|
+
next.set(conversationId, mergeRoomPreferences({ ...current, ...updates }));
|
|
1601
|
+
return next;
|
|
1637
1602
|
});
|
|
1638
1603
|
}
|
|
1639
1604
|
addMessage(message) {
|
|
@@ -1660,9 +1625,6 @@ class AXConversationState {
|
|
|
1660
1625
|
return newMap;
|
|
1661
1626
|
});
|
|
1662
1627
|
}
|
|
1663
|
-
/**
|
|
1664
|
-
* Replace all messages for a conversation (initial page load).
|
|
1665
|
-
*/
|
|
1666
1628
|
setConversationMessages(conversationId, messages) {
|
|
1667
1629
|
const sorted = [...messages]
|
|
1668
1630
|
.map(withNormalizedPayload)
|
|
@@ -3213,6 +3175,8 @@ class AXConversationService {
|
|
|
3213
3175
|
...(ngDevMode ? [{ debugName: "_loading" }] : /* istanbul ignore next */ []));
|
|
3214
3176
|
this._loadingActiveMessages = signal(false, /* @ts-ignore */
|
|
3215
3177
|
...(ngDevMode ? [{ debugName: "_loadingActiveMessages" }] : /* istanbul ignore next */ []));
|
|
3178
|
+
this._isForwardingMessage = signal(false, /* @ts-ignore */
|
|
3179
|
+
...(ngDevMode ? [{ debugName: "_isForwardingMessage" }] : /* istanbul ignore next */ []));
|
|
3216
3180
|
this._error = signal(null, /* @ts-ignore */
|
|
3217
3181
|
...(ngDevMode ? [{ debugName: "_error" }] : /* istanbul ignore next */ []));
|
|
3218
3182
|
this._conversationsPagination = signal({ page: 0, hasMore: true }, /* @ts-ignore */
|
|
@@ -3255,6 +3219,8 @@ class AXConversationService {
|
|
|
3255
3219
|
this.loading = this._loading.asReadonly();
|
|
3256
3220
|
/** Loading state for the active conversation's message history */
|
|
3257
3221
|
this.loadingActiveMessages = this._loadingActiveMessages.asReadonly();
|
|
3222
|
+
/** Whether a message forward operation is in progress. */
|
|
3223
|
+
this.isForwardingMessage = this._isForwardingMessage.asReadonly();
|
|
3258
3224
|
/** Sidebar conversation list pagination */
|
|
3259
3225
|
this.conversationsPagination = this._conversationsPagination.asReadonly();
|
|
3260
3226
|
/** Active conversation message pagination */
|
|
@@ -3283,6 +3249,15 @@ class AXConversationService {
|
|
|
3283
3249
|
this._currentUser = signal(null, /* @ts-ignore */
|
|
3284
3250
|
...(ngDevMode ? [{ debugName: "_currentUser" }] : /* istanbul ignore next */ []));
|
|
3285
3251
|
this.currentUser = this._currentUser.asReadonly();
|
|
3252
|
+
this.userPresenceMap = computed(() => this.state.userPresenceMap(), /* @ts-ignore */
|
|
3253
|
+
...(ngDevMode ? [{ debugName: "userPresenceMap" }] : /* istanbul ignore next */ []));
|
|
3254
|
+
this.presenceTimeTick = computed(() => {
|
|
3255
|
+
this.state.presenceTimeTick();
|
|
3256
|
+
return this.state.userPresenceMap();
|
|
3257
|
+
}, /* @ts-ignore */
|
|
3258
|
+
...(ngDevMode ? [{ debugName: "presenceTimeTick" }] : /* istanbul ignore next */ []));
|
|
3259
|
+
this.typingRevision = computed(() => this.state.typingRevision(), /* @ts-ignore */
|
|
3260
|
+
...(ngDevMode ? [{ debugName: "typingRevision" }] : /* istanbul ignore next */ []));
|
|
3286
3261
|
/** One-time async initialization (connect, user, conversations, realtime). */
|
|
3287
3262
|
this.initPromise = null;
|
|
3288
3263
|
/** Generation counter — stale page-0 loads are ignored after conversation switches. */
|
|
@@ -3291,9 +3266,12 @@ class AXConversationService {
|
|
|
3291
3266
|
this.conversationListLoadGeneration = 0;
|
|
3292
3267
|
/** Batched read-receipt queue keyed by conversation ID. */
|
|
3293
3268
|
this.readQueue = new Map();
|
|
3269
|
+
this.isTypingActiveForConversation = false;
|
|
3294
3270
|
/** Session cache for available reaction emojis. */
|
|
3295
3271
|
this.availableReactionsCache = null;
|
|
3296
3272
|
this.availableReactionsPromise = null;
|
|
3273
|
+
this.presenceTickHandle = setInterval(() => this.state.bumpPresenceTimeTick(), 60_000);
|
|
3274
|
+
this.typingPruneHandle = setInterval(() => this.state.pruneExpiredTyping(), 1_000);
|
|
3297
3275
|
this.destroyRef.onDestroy(() => {
|
|
3298
3276
|
this._conversationSwitch$.next();
|
|
3299
3277
|
this._conversationSwitch$.complete();
|
|
@@ -3302,7 +3280,17 @@ class AXConversationService {
|
|
|
3302
3280
|
if (this.readFlushHandle) {
|
|
3303
3281
|
clearTimeout(this.readFlushHandle);
|
|
3304
3282
|
}
|
|
3283
|
+
if (this.presenceTickHandle) {
|
|
3284
|
+
clearInterval(this.presenceTickHandle);
|
|
3285
|
+
}
|
|
3286
|
+
if (this.typingPruneHandle) {
|
|
3287
|
+
clearInterval(this.typingPruneHandle);
|
|
3288
|
+
}
|
|
3289
|
+
if (this.typingStopHandle) {
|
|
3290
|
+
clearTimeout(this.typingStopHandle);
|
|
3291
|
+
}
|
|
3305
3292
|
void this.flushReadQueue();
|
|
3293
|
+
void this.userApi.updatePresence('offline').catch(() => undefined);
|
|
3306
3294
|
});
|
|
3307
3295
|
}
|
|
3308
3296
|
/** Log and invoke an async API method from AXConversationService. */
|
|
@@ -3337,10 +3325,16 @@ class AXConversationService {
|
|
|
3337
3325
|
// Load current user
|
|
3338
3326
|
const currentUser = await this.callApi('initializeService', 'userApi', 'getCurrentUser', () => this.userApi.getCurrentUser());
|
|
3339
3327
|
this._currentUser.set(currentUser);
|
|
3328
|
+
if (currentUser.conversationPreferences) {
|
|
3329
|
+
this.state.setRoomPreferencesBulk(currentUser.conversationPreferences);
|
|
3330
|
+
}
|
|
3340
3331
|
// Subscribe to real-time events
|
|
3341
3332
|
this.subscribeToEvents();
|
|
3333
|
+
void this.userApi.updatePresence('online').catch(() => undefined);
|
|
3342
3334
|
// Load initial data
|
|
3343
3335
|
await this.loadConversations();
|
|
3336
|
+
await this.hydrateUserPresence();
|
|
3337
|
+
await this.loadRoomPreferences();
|
|
3344
3338
|
}
|
|
3345
3339
|
catch (error) {
|
|
3346
3340
|
const handledError = this.errorHandler.handle(error, 'initializeService');
|
|
@@ -3428,6 +3422,113 @@ class AXConversationService {
|
|
|
3428
3422
|
this.handleNewMessage(message);
|
|
3429
3423
|
this._messageReceived$.next(message);
|
|
3430
3424
|
});
|
|
3425
|
+
this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToMessageReactions');
|
|
3426
|
+
this.realtimeApi
|
|
3427
|
+
.subscribeToMessageReactions()
|
|
3428
|
+
.pipe(takeUntil(this.destroy$), catchError((error) => {
|
|
3429
|
+
this.errorHandler.handle(error, 'subscribeToMessageReactions');
|
|
3430
|
+
return EMPTY;
|
|
3431
|
+
}))
|
|
3432
|
+
.subscribe((message) => {
|
|
3433
|
+
this.handleMessageUpdate(message);
|
|
3434
|
+
this._messageUpdated$.next(message);
|
|
3435
|
+
});
|
|
3436
|
+
this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToConversationCreated');
|
|
3437
|
+
this.realtimeApi
|
|
3438
|
+
.subscribeToConversationCreated()
|
|
3439
|
+
.pipe(takeUntil(this.destroy$), catchError((error) => {
|
|
3440
|
+
this.errorHandler.handle(error, 'subscribeToConversationCreated');
|
|
3441
|
+
return EMPTY;
|
|
3442
|
+
}))
|
|
3443
|
+
.subscribe((conversation) => {
|
|
3444
|
+
this.handleConversationCreated(conversation);
|
|
3445
|
+
});
|
|
3446
|
+
this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToConversationDeleted');
|
|
3447
|
+
this.realtimeApi
|
|
3448
|
+
.subscribeToConversationDeleted()
|
|
3449
|
+
.pipe(takeUntil(this.destroy$), catchError((error) => {
|
|
3450
|
+
this.errorHandler.handle(error, 'subscribeToConversationDeleted');
|
|
3451
|
+
return EMPTY;
|
|
3452
|
+
}))
|
|
3453
|
+
.subscribe((conversationId) => {
|
|
3454
|
+
this.handleConversationDeleted(conversationId);
|
|
3455
|
+
});
|
|
3456
|
+
this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToReadReceipts');
|
|
3457
|
+
this.realtimeApi
|
|
3458
|
+
.subscribeToReadReceipts()
|
|
3459
|
+
.pipe(takeUntil(this.destroy$), catchError((error) => {
|
|
3460
|
+
this.errorHandler.handle(error, 'subscribeToReadReceipts');
|
|
3461
|
+
return EMPTY;
|
|
3462
|
+
}))
|
|
3463
|
+
.subscribe((receipt) => {
|
|
3464
|
+
this.handleReadReceipt(receipt);
|
|
3465
|
+
});
|
|
3466
|
+
this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToMessageStatusChanges');
|
|
3467
|
+
this.realtimeApi
|
|
3468
|
+
.subscribeToMessageStatusChanges()
|
|
3469
|
+
.pipe(takeUntil(this.destroy$), catchError((error) => {
|
|
3470
|
+
this.errorHandler.handle(error, 'subscribeToMessageStatusChanges');
|
|
3471
|
+
return EMPTY;
|
|
3472
|
+
}))
|
|
3473
|
+
.subscribe((change) => {
|
|
3474
|
+
this.handleMessageStatusChange(change);
|
|
3475
|
+
});
|
|
3476
|
+
this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToConversationSettingsChanges');
|
|
3477
|
+
this.realtimeApi
|
|
3478
|
+
.subscribeToConversationSettingsChanges()
|
|
3479
|
+
.pipe(takeUntil(this.destroy$), catchError((error) => {
|
|
3480
|
+
this.errorHandler.handle(error, 'subscribeToConversationSettingsChanges');
|
|
3481
|
+
return EMPTY;
|
|
3482
|
+
}))
|
|
3483
|
+
.subscribe((change) => {
|
|
3484
|
+
this.handleRoomPreferencesChange(change);
|
|
3485
|
+
});
|
|
3486
|
+
}
|
|
3487
|
+
getUserPresence(userId) {
|
|
3488
|
+
return this.state.getUserPresence(userId);
|
|
3489
|
+
}
|
|
3490
|
+
getRoomPreferences(conversationId) {
|
|
3491
|
+
return this.state.getRoomPreferences(conversationId);
|
|
3492
|
+
}
|
|
3493
|
+
isAnyoneTyping(conversationId) {
|
|
3494
|
+
return this.state.isAnyoneTyping(conversationId);
|
|
3495
|
+
}
|
|
3496
|
+
getActiveTypingUserIds(conversationId) {
|
|
3497
|
+
return this.state.getActiveTypingUserIds(conversationId);
|
|
3498
|
+
}
|
|
3499
|
+
getPeerPresence(conversation) {
|
|
3500
|
+
const peerId = resolveConversationPeerUserId(conversation, this._currentUser()?.id);
|
|
3501
|
+
return peerId ? this.getUserPresence(peerId) : undefined;
|
|
3502
|
+
}
|
|
3503
|
+
async hydrateUserPresence() {
|
|
3504
|
+
const currentUserId = this._currentUser()?.id;
|
|
3505
|
+
const userIds = new Set();
|
|
3506
|
+
for (const conversation of this.state.conversations()) {
|
|
3507
|
+
for (const participant of conversation.participants) {
|
|
3508
|
+
if (participant.id !== currentUserId) {
|
|
3509
|
+
userIds.add(participant.id);
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
if (userIds.size === 0) {
|
|
3514
|
+
return;
|
|
3515
|
+
}
|
|
3516
|
+
try {
|
|
3517
|
+
const updates = await this.callApi('hydrateUserPresence', 'userApi', 'getUsersPresence', () => this.userApi.getUsersPresence([...userIds]), [...userIds]);
|
|
3518
|
+
this.state.bulkSetUserPresence(updates);
|
|
3519
|
+
}
|
|
3520
|
+
catch (error) {
|
|
3521
|
+
this.errorHandler.handle(error, 'hydrateUserPresence');
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
async loadRoomPreferences() {
|
|
3525
|
+
try {
|
|
3526
|
+
const preferences = await this.callApi('loadRoomPreferences', 'userApi', 'getConversationPreferences', () => this.userApi.getConversationPreferences());
|
|
3527
|
+
this.state.setRoomPreferencesBulk(preferences);
|
|
3528
|
+
}
|
|
3529
|
+
catch (error) {
|
|
3530
|
+
this.errorHandler.handle(error, 'loadRoomPreferences');
|
|
3531
|
+
}
|
|
3431
3532
|
}
|
|
3432
3533
|
/**
|
|
3433
3534
|
* Load conversations from server
|
|
@@ -3455,6 +3556,7 @@ class AXConversationService {
|
|
|
3455
3556
|
hasMore: result.hasMore,
|
|
3456
3557
|
nextCursor: result.nextCursor,
|
|
3457
3558
|
});
|
|
3559
|
+
await this.hydrateUserPresence();
|
|
3458
3560
|
}
|
|
3459
3561
|
catch (error) {
|
|
3460
3562
|
const handledError = this.errorHandler.handle(error, 'loadConversations');
|
|
@@ -3497,16 +3599,22 @@ class AXConversationService {
|
|
|
3497
3599
|
*/
|
|
3498
3600
|
async selectConversation(conversationId) {
|
|
3499
3601
|
await this.ensureInitialized();
|
|
3602
|
+
const isAlreadyActive = this._activeConversationId() === conversationId;
|
|
3603
|
+
const hasCachedMessages = this.state.getConversationMessages(conversationId).length > 0;
|
|
3500
3604
|
try {
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3605
|
+
if (!isAlreadyActive) {
|
|
3606
|
+
this._conversationSwitch$.next();
|
|
3607
|
+
this.messageLoadGeneration++;
|
|
3608
|
+
this._activeConversationId.set(conversationId);
|
|
3609
|
+
}
|
|
3610
|
+
if (!isAlreadyActive || !hasCachedMessages) {
|
|
3611
|
+
this._loadingActiveMessages.set(true);
|
|
3612
|
+
try {
|
|
3613
|
+
await this.loadMessages(conversationId, 0);
|
|
3614
|
+
}
|
|
3615
|
+
finally {
|
|
3616
|
+
this._loadingActiveMessages.set(false);
|
|
3617
|
+
}
|
|
3510
3618
|
}
|
|
3511
3619
|
if (this.config.markConversationReadOnSelect) {
|
|
3512
3620
|
const conversation = this.state.getConversation(conversationId);
|
|
@@ -3545,7 +3653,12 @@ class AXConversationService {
|
|
|
3545
3653
|
return empty;
|
|
3546
3654
|
}
|
|
3547
3655
|
if (page === 0) {
|
|
3548
|
-
this.state
|
|
3656
|
+
const pendingLocal = this.state
|
|
3657
|
+
.getConversationMessages(conversationId)
|
|
3658
|
+
.filter((m) => m.isLocal || m.status === 'sending');
|
|
3659
|
+
const serverIds = new Set(result.items.map((m) => m.id));
|
|
3660
|
+
const localsToKeep = pendingLocal.filter((m) => !serverIds.has(m.id));
|
|
3661
|
+
this.state.setConversationMessages(conversationId, [...result.items, ...localsToKeep]);
|
|
3549
3662
|
}
|
|
3550
3663
|
else if (result.items.length > 0) {
|
|
3551
3664
|
this.state.addMessages(result.items);
|
|
@@ -3657,9 +3770,7 @@ class AXConversationService {
|
|
|
3657
3770
|
};
|
|
3658
3771
|
this.state.updateMessage(tempMessageId, { payload: sendCommand.payload });
|
|
3659
3772
|
const sentMessage = await this.callApi('sendMessage', 'messageApi', 'sendMessage', () => this.messageApi.sendMessage(sendCommand), sendCommand);
|
|
3660
|
-
this.
|
|
3661
|
-
this.state.addMessage(sentMessage);
|
|
3662
|
-
this.updateConversationLastMessage(sentMessage);
|
|
3773
|
+
this.finalizeSentMessage(tempMessageId, sentMessage);
|
|
3663
3774
|
if (localPreviewUrl?.startsWith('blob:')) {
|
|
3664
3775
|
await revokeObjectUrl$1(this.platformId, localPreviewUrl);
|
|
3665
3776
|
}
|
|
@@ -3694,9 +3805,7 @@ class AXConversationService {
|
|
|
3694
3805
|
};
|
|
3695
3806
|
this.state.addMessage(tempMessage);
|
|
3696
3807
|
const sentMessage = await this.callApi('sendMessage', 'messageApi', 'sendMessage', () => this.messageApi.sendMessage(sendCommand), sendCommand);
|
|
3697
|
-
this.
|
|
3698
|
-
this.state.addMessage(sentMessage);
|
|
3699
|
-
this.updateConversationLastMessage(sentMessage);
|
|
3808
|
+
this.finalizeSentMessage(tempMessageId, sentMessage);
|
|
3700
3809
|
}
|
|
3701
3810
|
catch (error) {
|
|
3702
3811
|
this.state.updateMessage(tempMessageId, { status: 'failed' });
|
|
@@ -3731,11 +3840,8 @@ class AXConversationService {
|
|
|
3731
3840
|
};
|
|
3732
3841
|
// Send to server
|
|
3733
3842
|
const sentMessage = await this.callApi('retryFailedMessage', 'messageApi', 'sendMessage', () => this.messageApi.sendMessage(command), command);
|
|
3734
|
-
// Replace with real message
|
|
3735
|
-
this.
|
|
3736
|
-
this.state.addMessage(sentMessage);
|
|
3737
|
-
// Update conversation's last message
|
|
3738
|
-
this.updateConversationLastMessage(sentMessage);
|
|
3843
|
+
// Replace with real message (keep same DOM row when server echoes tempId)
|
|
3844
|
+
this.finalizeSentMessage(messageId, sentMessage);
|
|
3739
3845
|
}
|
|
3740
3846
|
catch (error) {
|
|
3741
3847
|
// Mark as failed again
|
|
@@ -3758,7 +3864,8 @@ class AXConversationService {
|
|
|
3758
3864
|
editedAt: new Date(),
|
|
3759
3865
|
});
|
|
3760
3866
|
// Sync with server
|
|
3761
|
-
await this.callApi('editMessage', 'messageApi', 'editMessage', () => this.messageApi.editMessage(messageId, payload), messageId, payload);
|
|
3867
|
+
const updatedMessage = await this.callApi('editMessage', 'messageApi', 'editMessage', () => this.messageApi.editMessage(messageId, payload), messageId, payload);
|
|
3868
|
+
this.state.updateMessage(messageId, updatedMessage);
|
|
3762
3869
|
}
|
|
3763
3870
|
catch (error) {
|
|
3764
3871
|
// Rollback on failure
|
|
@@ -3807,11 +3914,22 @@ class AXConversationService {
|
|
|
3807
3914
|
* Adds reaction optimistically, server update comes via subscription
|
|
3808
3915
|
*/
|
|
3809
3916
|
async reactToMessage(messageId, emoji) {
|
|
3917
|
+
const message = this.state.getMessage(messageId);
|
|
3918
|
+
const currentUserId = this._currentUser()?.id;
|
|
3919
|
+
if (!message || !currentUserId) {
|
|
3920
|
+
return;
|
|
3921
|
+
}
|
|
3922
|
+
const originalReactions = [...message.reactions];
|
|
3923
|
+
const hasReaction = message.reactions.some((r) => r.emoji === emoji && r.userId === currentUserId);
|
|
3924
|
+
const optimisticReactions = hasReaction
|
|
3925
|
+
? message.reactions.filter((r) => !(r.emoji === emoji && r.userId === currentUserId))
|
|
3926
|
+
: [...message.reactions, { emoji, userId: currentUserId, timestamp: new Date() }];
|
|
3927
|
+
this.state.updateMessage(messageId, { reactions: optimisticReactions });
|
|
3810
3928
|
try {
|
|
3811
3929
|
await this.callApi('reactToMessage', 'messageApi', 'addReaction', () => this.messageApi.addReaction(messageId, emoji), messageId, emoji);
|
|
3812
|
-
// Update will come through subscribeToMessageUpdates
|
|
3813
3930
|
}
|
|
3814
3931
|
catch (error) {
|
|
3932
|
+
this.state.updateMessage(messageId, { reactions: originalReactions });
|
|
3815
3933
|
this.errorHandler.handle(error, 'reactToMessage', { messageId, emoji });
|
|
3816
3934
|
throw error;
|
|
3817
3935
|
}
|
|
@@ -3850,8 +3968,12 @@ class AXConversationService {
|
|
|
3850
3968
|
if (!message || message.status === 'read') {
|
|
3851
3969
|
return;
|
|
3852
3970
|
}
|
|
3971
|
+
const existingQueue = this.readQueue.get(message.conversationId);
|
|
3972
|
+
if (existingQueue?.has(messageId)) {
|
|
3973
|
+
return;
|
|
3974
|
+
}
|
|
3853
3975
|
this.state.updateMessage(messageId, { status: 'read' });
|
|
3854
|
-
let queue =
|
|
3976
|
+
let queue = existingQueue;
|
|
3855
3977
|
if (!queue) {
|
|
3856
3978
|
queue = new Set();
|
|
3857
3979
|
this.readQueue.set(message.conversationId, queue);
|
|
@@ -3969,10 +4091,17 @@ class AXConversationService {
|
|
|
3969
4091
|
await this.callApi('sendTypingIndicator', 'messageApi', 'sendTypingIndicator', () => this.messageApi.sendTypingIndicator(conversationId), conversationId);
|
|
3970
4092
|
}
|
|
3971
4093
|
catch (error) {
|
|
3972
|
-
// Log but don't throw - typing indicators are not critical
|
|
3973
4094
|
this.errorHandler.handle(error, 'sendTypingIndicator', { conversationId });
|
|
3974
4095
|
}
|
|
3975
4096
|
}
|
|
4097
|
+
async stopTypingIndicator(conversationId) {
|
|
4098
|
+
try {
|
|
4099
|
+
await this.callApi('stopTypingIndicator', 'messageApi', 'stopTypingIndicator', () => this.messageApi.stopTypingIndicator(conversationId), conversationId);
|
|
4100
|
+
}
|
|
4101
|
+
catch (error) {
|
|
4102
|
+
this.errorHandler.handle(error, 'stopTypingIndicator', { conversationId });
|
|
4103
|
+
}
|
|
4104
|
+
}
|
|
3976
4105
|
/**
|
|
3977
4106
|
* Search conversations
|
|
3978
4107
|
* Returns empty array on failure
|
|
@@ -3990,15 +4119,22 @@ class AXConversationService {
|
|
|
3990
4119
|
* Handle new message received
|
|
3991
4120
|
*/
|
|
3992
4121
|
handleNewMessage(message) {
|
|
4122
|
+
if (message.status === 'read') {
|
|
4123
|
+
return;
|
|
4124
|
+
}
|
|
3993
4125
|
if (this.state.getMessage(message.id)) {
|
|
3994
4126
|
return;
|
|
3995
4127
|
}
|
|
4128
|
+
this.state.clearTypingUser(message.conversationId, message.senderId);
|
|
3996
4129
|
this.state.addMessage(message);
|
|
3997
4130
|
this.state.updateLastMessage(message);
|
|
3998
4131
|
const currentId = this._currentUser()?.id ?? 'current-user';
|
|
3999
4132
|
const isFromOtherUser = message.senderId !== currentId;
|
|
4000
4133
|
const isActiveConversation = message.conversationId === this._activeConversationId();
|
|
4001
|
-
if (isFromOtherUser &&
|
|
4134
|
+
if (isFromOtherUser && isActiveConversation) {
|
|
4135
|
+
this.queueMessageAsRead(message.id);
|
|
4136
|
+
}
|
|
4137
|
+
else if (isFromOtherUser && !isActiveConversation) {
|
|
4002
4138
|
this.state.incrementUnreadCount(message.conversationId);
|
|
4003
4139
|
}
|
|
4004
4140
|
this.syncMessageCountFromRealtime(message, isActiveConversation);
|
|
@@ -4046,22 +4182,21 @@ class AXConversationService {
|
|
|
4046
4182
|
* Handle typing indicator
|
|
4047
4183
|
*/
|
|
4048
4184
|
handleTypingIndicator(indicator) {
|
|
4049
|
-
// Ignore typing indicators from the current user
|
|
4050
4185
|
const currentUser = this._currentUser();
|
|
4051
4186
|
if (currentUser && indicator.userId === currentUser.id) {
|
|
4052
4187
|
return;
|
|
4053
4188
|
}
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4189
|
+
if (indicator.isTyping === false) {
|
|
4190
|
+
this.state.clearTypingUser(indicator.conversationId, indicator.userId);
|
|
4191
|
+
return;
|
|
4192
|
+
}
|
|
4193
|
+
this.state.setTypingActive(indicator.conversationId, indicator.userId, this.config.typingDisplayDuration ?? 4000);
|
|
4059
4194
|
}
|
|
4060
4195
|
/**
|
|
4061
4196
|
* Handle presence update
|
|
4062
4197
|
*/
|
|
4063
4198
|
handlePresenceUpdate(update) {
|
|
4064
|
-
this.state.
|
|
4199
|
+
this.state.updateUserPresence(update);
|
|
4065
4200
|
}
|
|
4066
4201
|
/**
|
|
4067
4202
|
* Handle conversation update
|
|
@@ -4070,6 +4205,43 @@ class AXConversationService {
|
|
|
4070
4205
|
handleConversationUpdate(conversation) {
|
|
4071
4206
|
this.syncConversationToInbox(conversation);
|
|
4072
4207
|
}
|
|
4208
|
+
handleConversationCreated(conversation) {
|
|
4209
|
+
this.syncConversationToInbox(conversation, true);
|
|
4210
|
+
}
|
|
4211
|
+
handleConversationDeleted(conversationId) {
|
|
4212
|
+
this.state.deleteConversation(conversationId);
|
|
4213
|
+
this.readQueue.delete(conversationId);
|
|
4214
|
+
if (this._activeConversationId() === conversationId) {
|
|
4215
|
+
this._activeConversationId.set(undefined);
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
handleReadReceipt(receipt) {
|
|
4219
|
+
const currentUserId = this._currentUser()?.id;
|
|
4220
|
+
const message = this.state.getMessage(receipt.messageId);
|
|
4221
|
+
if (!message || !currentUserId) {
|
|
4222
|
+
return;
|
|
4223
|
+
}
|
|
4224
|
+
if (receipt.userId === currentUserId) {
|
|
4225
|
+
return;
|
|
4226
|
+
}
|
|
4227
|
+
if (message.senderId === currentUserId && message.status !== 'read') {
|
|
4228
|
+
this.state.updateMessage(receipt.messageId, { status: 'read' });
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
handleMessageStatusChange(change) {
|
|
4232
|
+
const message = this.state.getMessage(change.messageId);
|
|
4233
|
+
if (!message || message.status === change.status) {
|
|
4234
|
+
return;
|
|
4235
|
+
}
|
|
4236
|
+
this.state.updateMessage(change.messageId, { status: change.status });
|
|
4237
|
+
}
|
|
4238
|
+
handleRoomPreferencesChange(change) {
|
|
4239
|
+
const currentUserId = this._currentUser()?.id;
|
|
4240
|
+
if (!currentUserId) {
|
|
4241
|
+
return;
|
|
4242
|
+
}
|
|
4243
|
+
this.state.updateRoomPreferences(change.conversationId, change.settings);
|
|
4244
|
+
}
|
|
4073
4245
|
/**
|
|
4074
4246
|
* Insert or refresh a conversation in the in-memory inbox.
|
|
4075
4247
|
* @param promote When true, bumps activity so the chat sorts to the top (create / reopen).
|
|
@@ -4085,6 +4257,16 @@ class AXConversationService {
|
|
|
4085
4257
|
updatedAt: conversation.updatedAt ?? now,
|
|
4086
4258
|
});
|
|
4087
4259
|
}
|
|
4260
|
+
finalizeSentMessage(tempMessageId, sentMessage) {
|
|
4261
|
+
if (sentMessage.id === tempMessageId) {
|
|
4262
|
+
this.state.updateMessage(tempMessageId, { ...sentMessage, isLocal: false });
|
|
4263
|
+
}
|
|
4264
|
+
else {
|
|
4265
|
+
this.state.deleteMessage(tempMessageId);
|
|
4266
|
+
this.state.addMessage(sentMessage);
|
|
4267
|
+
}
|
|
4268
|
+
this.updateConversationLastMessage(sentMessage);
|
|
4269
|
+
}
|
|
4088
4270
|
/**
|
|
4089
4271
|
* Update conversation's last message
|
|
4090
4272
|
*/
|
|
@@ -4138,8 +4320,8 @@ class AXConversationService {
|
|
|
4138
4320
|
*/
|
|
4139
4321
|
async updateConversationSettings(conversationId, settings) {
|
|
4140
4322
|
try {
|
|
4141
|
-
await this.callApi('updateConversationSettings', '
|
|
4142
|
-
this.state.
|
|
4323
|
+
const updated = await this.callApi('updateConversationSettings', 'userApi', 'updateConversationPreferences', () => this.userApi.updateConversationPreferences(conversationId, settings), conversationId, settings);
|
|
4324
|
+
this.state.updateRoomPreferences(conversationId, updated);
|
|
4143
4325
|
}
|
|
4144
4326
|
catch (error) {
|
|
4145
4327
|
this.errorHandler.handle(error, 'updateConversationSettings', { conversationId });
|
|
@@ -4420,9 +4602,8 @@ class AXConversationService {
|
|
|
4420
4602
|
*/
|
|
4421
4603
|
async muteConversation(conversationId, duration) {
|
|
4422
4604
|
try {
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
this.state.updateSettings(conversationId, { mutedUntil, notifications: false });
|
|
4605
|
+
const mutedUntil = duration ? new Date(Date.now() + duration) : new Date('2099-12-31');
|
|
4606
|
+
await this.updateConversationSettings(conversationId, { mutedUntil, notifications: false });
|
|
4426
4607
|
}
|
|
4427
4608
|
catch (error) {
|
|
4428
4609
|
this.errorHandler.handle(error, 'muteConversation', { conversationId, duration });
|
|
@@ -4435,8 +4616,7 @@ class AXConversationService {
|
|
|
4435
4616
|
*/
|
|
4436
4617
|
async unmuteConversation(conversationId) {
|
|
4437
4618
|
try {
|
|
4438
|
-
await this.
|
|
4439
|
-
this.state.updateSettings(conversationId, { mutedUntil: undefined, notifications: true });
|
|
4619
|
+
await this.updateConversationSettings(conversationId, { mutedUntil: undefined, notifications: true });
|
|
4440
4620
|
}
|
|
4441
4621
|
catch (error) {
|
|
4442
4622
|
this.errorHandler.handle(error, 'unmuteConversation', { conversationId });
|
|
@@ -4498,7 +4678,6 @@ class AXConversationService {
|
|
|
4498
4678
|
async saveDraft(conversationId, draft) {
|
|
4499
4679
|
try {
|
|
4500
4680
|
await this.callApi('saveDraft', 'conversationApi', 'saveDraft', () => this.conversationApi.saveDraft(conversationId, draft), conversationId, draft);
|
|
4501
|
-
this.state.updateConversation(conversationId, { draft });
|
|
4502
4681
|
}
|
|
4503
4682
|
catch (error) {
|
|
4504
4683
|
this.errorHandler.handle(error, 'saveDraft', { conversationId });
|
|
@@ -4512,7 +4691,6 @@ class AXConversationService {
|
|
|
4512
4691
|
async clearDraft(conversationId) {
|
|
4513
4692
|
try {
|
|
4514
4693
|
await this.callApi('clearDraft', 'conversationApi', 'clearDraft', () => this.conversationApi.clearDraft(conversationId), conversationId);
|
|
4515
|
-
this.state.updateConversation(conversationId, { draft: undefined });
|
|
4516
4694
|
}
|
|
4517
4695
|
catch (error) {
|
|
4518
4696
|
this.errorHandler.handle(error, 'clearDraft', { conversationId });
|
|
@@ -4559,18 +4737,35 @@ class AXConversationService {
|
|
|
4559
4737
|
* @param caption - Optional caption
|
|
4560
4738
|
*/
|
|
4561
4739
|
async forwardMessage(messageId, conversationIds, caption) {
|
|
4740
|
+
await this.runWithForwardingLock(async () => {
|
|
4741
|
+
try {
|
|
4742
|
+
const forwardCommand = {
|
|
4743
|
+
messageId,
|
|
4744
|
+
conversationIds,
|
|
4745
|
+
caption,
|
|
4746
|
+
};
|
|
4747
|
+
await this.callApi('forwardMessage', 'messageApi', 'forwardMessage', () => this.messageApi.forwardMessage(forwardCommand), forwardCommand);
|
|
4748
|
+
this.bumpMessageCount(messageId, 'forwardCount', conversationIds.length);
|
|
4749
|
+
}
|
|
4750
|
+
catch (error) {
|
|
4751
|
+
this.errorHandler.handle(error, 'forwardMessage', { messageId, conversationIds });
|
|
4752
|
+
throw error;
|
|
4753
|
+
}
|
|
4754
|
+
});
|
|
4755
|
+
}
|
|
4756
|
+
/**
|
|
4757
|
+
* Runs a forward operation while locking all forward actions until it completes.
|
|
4758
|
+
*/
|
|
4759
|
+
async runWithForwardingLock(task) {
|
|
4760
|
+
if (this._isForwardingMessage()) {
|
|
4761
|
+
throw new Error('A message forward is already in progress.');
|
|
4762
|
+
}
|
|
4763
|
+
this._isForwardingMessage.set(true);
|
|
4562
4764
|
try {
|
|
4563
|
-
|
|
4564
|
-
messageId,
|
|
4565
|
-
conversationIds,
|
|
4566
|
-
caption,
|
|
4567
|
-
};
|
|
4568
|
-
await this.callApi('forwardMessage', 'messageApi', 'forwardMessage', () => this.messageApi.forwardMessage(forwardCommand), forwardCommand);
|
|
4569
|
-
this.bumpMessageCount(messageId, 'forwardCount', conversationIds.length);
|
|
4765
|
+
return await task();
|
|
4570
4766
|
}
|
|
4571
|
-
|
|
4572
|
-
this.
|
|
4573
|
-
throw error;
|
|
4767
|
+
finally {
|
|
4768
|
+
this._isForwardingMessage.set(false);
|
|
4574
4769
|
}
|
|
4575
4770
|
}
|
|
4576
4771
|
/**
|
|
@@ -5892,22 +6087,32 @@ class AXConversationRegistryComponentOutletComponent {
|
|
|
5892
6087
|
...(ngDevMode ? [{ debugName: "resolvedComponent" }] : /* istanbul ignore next */ []));
|
|
5893
6088
|
this.loading = signal(false, /* @ts-ignore */
|
|
5894
6089
|
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
6090
|
+
/** Avoid re-loading when the parent re-binds the same lazy loader reference. */
|
|
6091
|
+
this.activeLoader = null;
|
|
5895
6092
|
effect(() => {
|
|
5896
6093
|
const direct = this.component();
|
|
5897
6094
|
const loader = this.componentLoader();
|
|
5898
6095
|
if (direct) {
|
|
6096
|
+
this.activeLoader = null;
|
|
5899
6097
|
this.resolvedComponent.set(direct);
|
|
5900
6098
|
this.loading.set(false);
|
|
5901
6099
|
return;
|
|
5902
6100
|
}
|
|
5903
6101
|
if (!loader) {
|
|
6102
|
+
this.activeLoader = null;
|
|
5904
6103
|
this.resolvedComponent.set(null);
|
|
5905
6104
|
this.loading.set(false);
|
|
5906
6105
|
return;
|
|
5907
6106
|
}
|
|
6107
|
+
if (this.resolvedComponent() && this.activeLoader === loader) {
|
|
6108
|
+
return;
|
|
6109
|
+
}
|
|
6110
|
+
this.activeLoader = loader;
|
|
5908
6111
|
this.loading.set(true);
|
|
5909
|
-
this.resolvedComponent.set(null);
|
|
5910
6112
|
void loader().then((loaded) => {
|
|
6113
|
+
if (this.activeLoader !== loader) {
|
|
6114
|
+
return;
|
|
6115
|
+
}
|
|
5911
6116
|
this.resolvedComponent.set(loaded);
|
|
5912
6117
|
this.loading.set(false);
|
|
5913
6118
|
});
|
|
@@ -6002,9 +6207,6 @@ class AXConversationComposerService {
|
|
|
6002
6207
|
/** Attachments */
|
|
6003
6208
|
this.attachments = signal([], /* @ts-ignore */
|
|
6004
6209
|
...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
|
|
6005
|
-
/** Show typing indicator */
|
|
6006
|
-
this.showTypingIndicator = signal(false, /* @ts-ignore */
|
|
6007
|
-
...(ngDevMode ? [{ debugName: "showTypingIndicator" }] : /* istanbul ignore next */ []));
|
|
6008
6210
|
/** Incremented to request focus on the composer text area (handled by AXConversationComposerComponent). */
|
|
6009
6211
|
this._focusRequest = signal(0, /* @ts-ignore */
|
|
6010
6212
|
...(ngDevMode ? [{ debugName: "_focusRequest" }] : /* istanbul ignore next */ []));
|
|
@@ -6318,8 +6520,6 @@ class AXConversationComposerComponent {
|
|
|
6318
6520
|
/** Replying to message */
|
|
6319
6521
|
this.replyingToMessage = signal(null, /* @ts-ignore */
|
|
6320
6522
|
...(ngDevMode ? [{ debugName: "replyingToMessage" }] : /* istanbul ignore next */ []));
|
|
6321
|
-
/** Show typing indicator - use service */
|
|
6322
|
-
this.showTypingIndicator = this.composerService.showTypingIndicator;
|
|
6323
6523
|
/** Message sent event */
|
|
6324
6524
|
this.messageSent = output();
|
|
6325
6525
|
/** Emitted when the user cancels an in-progress generation from the composer. */
|
|
@@ -6430,7 +6630,7 @@ class AXConversationComposerComponent {
|
|
|
6430
6630
|
/** Default end action (voice/send morph) */
|
|
6431
6631
|
this.defaultAction = this.composerService.defaultAction;
|
|
6432
6632
|
this.typingSubject
|
|
6433
|
-
.pipe(throttleTime(this.config.typingIndicatorThrottle ??
|
|
6633
|
+
.pipe(throttleTime(this.config.typingIndicatorThrottle ?? 3000), takeUntilDestroyed())
|
|
6434
6634
|
.subscribe((conversationId) => {
|
|
6435
6635
|
this.conversationService.sendTypingIndicator(conversationId);
|
|
6436
6636
|
});
|
|
@@ -6467,17 +6667,37 @@ class AXConversationComposerComponent {
|
|
|
6467
6667
|
const conversation = this.activeConversation();
|
|
6468
6668
|
if (!conversation)
|
|
6469
6669
|
return;
|
|
6470
|
-
|
|
6471
|
-
this.
|
|
6670
|
+
const conversationId = conversation.id;
|
|
6671
|
+
const draft = this.draftText().trim();
|
|
6672
|
+
if (!draft) {
|
|
6673
|
+
this.stopTypingIndicator(conversationId);
|
|
6674
|
+
return;
|
|
6675
|
+
}
|
|
6676
|
+
this.typingSubject.next(conversationId);
|
|
6677
|
+
if (this.typingStopHandle) {
|
|
6678
|
+
clearTimeout(this.typingStopHandle);
|
|
6679
|
+
}
|
|
6680
|
+
this.typingStopHandle = window.setTimeout(() => {
|
|
6681
|
+
this.stopTypingIndicator(conversationId);
|
|
6682
|
+
}, this.config.typingIndicatorTimeout ?? 3000);
|
|
6683
|
+
}
|
|
6684
|
+
stopTypingIndicator(conversationId) {
|
|
6685
|
+
if (this.typingStopHandle) {
|
|
6686
|
+
clearTimeout(this.typingStopHandle);
|
|
6687
|
+
this.typingStopHandle = undefined;
|
|
6688
|
+
}
|
|
6689
|
+
void this.conversationService.stopTypingIndicator(conversationId);
|
|
6472
6690
|
}
|
|
6473
6691
|
/** Cleanup on destroy */
|
|
6474
6692
|
ngOnDestroy() {
|
|
6475
|
-
this.typingSubject.complete();
|
|
6476
|
-
// Save draft before destroying
|
|
6477
6693
|
const conversation = this.activeConversation();
|
|
6478
|
-
if (conversation?.id
|
|
6479
|
-
this.
|
|
6694
|
+
if (conversation?.id) {
|
|
6695
|
+
this.stopTypingIndicator(conversation.id);
|
|
6696
|
+
if (!this.composerService.editMessage()) {
|
|
6697
|
+
this.composerService.saveDraft(conversation.id, this.draftText());
|
|
6698
|
+
}
|
|
6480
6699
|
}
|
|
6700
|
+
this.typingSubject.complete();
|
|
6481
6701
|
// Clear timeout
|
|
6482
6702
|
if (this.draftSaveTimeout) {
|
|
6483
6703
|
clearTimeout(this.draftSaveTimeout);
|
|
@@ -6514,6 +6734,7 @@ class AXConversationComposerComponent {
|
|
|
6514
6734
|
};
|
|
6515
6735
|
this.editingMessage.set(null);
|
|
6516
6736
|
this.replyingToMessage.set(null);
|
|
6737
|
+
this.stopTypingIndicator(conversation.id);
|
|
6517
6738
|
void this.composerService
|
|
6518
6739
|
.sendMessage(command)
|
|
6519
6740
|
.then(() => {
|
|
@@ -6851,7 +7072,7 @@ class AXConversationComposerComponent {
|
|
|
6851
7072
|
}
|
|
6852
7073
|
}
|
|
6853
7074
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationComposerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6854
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationComposerComponent, isStandalone: true, selector: "ax-conversation-composer", outputs: { messageSent: "messageSent", generationCancelled: "generationCancelled", emojiClick: "emojiClick", attachClick: "attachClick", voiceClick: "voiceClick" }, viewQueries: [{ propertyName: "textAreaRef", first: true, predicate: ["inputElement"], descendants: true, read: AXTextAreaComponent, isSignal: true }, { propertyName: "emojiPopoverRef", first: true, predicate: ["emojiPopover"], descendants: true, isSignal: true }, { propertyName: "attachPopoverRef", first: true, predicate: ["attachPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (activeConversation()) {\n <div class=\"composer\">\n <!-- Edit/Reply Banner -->\n @if (editingMessage() || replyingToMessage()) {\n <div\n class=\"ax-conversation-composer-banner\"\n [class.ax-conversation-composer-banner--edit]=\"!!editingMessage()\"\n [class.ax-conversation-composer-banner--reply]=\"!!replyingToMessage()\"\n >\n <div class=\"ax-conversation-composer-banner__accent\" aria-hidden=\"true\"></div>\n @if (editingMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-pen-to-square\"></i\n ></span>\n <div class=\"ax-conversation-composer-banner__body\">\n <span class=\"ax-conversation-composer-banner__label\">{{\n '@acorex:chat.composer.editing-message' | translate | async\n }}</span>\n @if (getEditingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n } @else if (replyingToMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-reply\"></i\n ></span>\n <div\n class=\"ax-conversation-composer-banner__body ax-conversation-composer-banner__body--clickable\"\n (click)=\"onReplyPreviewClick()\"\n >\n <span class=\"ax-conversation-composer-banner__label\">\n {{ '@acorex:chat.composer.replying-to' | translate | async }} {{ getReplyingSenderName() }}\n </span>\n @if (getReplyingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n }\n <button\n type=\"button\"\n class=\"ax-conversation-composer-banner__close\"\n (click)=\"cancelEditReply()\"\n [attr.aria-label]=\"'@acorex:chat.actions.cancel' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <!-- Input Area -->\n <div class=\"composer-input-container\">\n <!-- Start actions -->\n <div class=\"composer-actions-left\">\n @if (startMenuActions().length > 0) {\n <ax-button\n class=\"rounded-full text-xl\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"('@acorex:chat.tooltips.attach-file' | translate | async) ?? ''\"\n (onClick)=\"onAttachMenuClick($event)\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-paperclip\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n @for (action of startInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <!-- Text Input -->\n <div class=\"composer-input-wrapper\">\n <ax-text-area\n #inputElement\n [(ngModel)]=\"draftText\"\n (onKeyDown)=\"onKeyDown($event)\"\n (onValueChanged)=\"onInput()\"\n [placeholder]=\"placeholder()\"\n (onKeyDown)=\"onEnter($event)\"\n [rows]=\"inputRows()\"\n ></ax-text-area>\n </div>\n\n <!-- End actions -->\n <div class=\"composer-actions-right\">\n @for (action of endInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n <ax-button\n class=\"rounded-full text-xl\"\n [class.ax-conversation-composer-primary--stopping]=\"primaryButtonMode() === 'stopping'\"\n color=\"primary\"\n look=\"solid\"\n [iconOnly]=\"true\"\n [text]=\"getPrimaryButtonLabel()\"\n [disabled]=\"isPrimaryButtonDisabled()\"\n (onClick)=\"onPrimaryButtonClick()\"\n >\n <ax-prefix>\n <i [class]=\"getPrimaryButtonIcon()\"></i>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n\n <!-- Attachments Preview -->\n @if (attachments().length > 0) {\n <div class=\"composer-attachments\">\n @for (attachment of attachments(); track $index) {\n <div class=\"attachment-item\">\n <span class=\"attachment-icon\"><i class=\"fa-light fa-paperclip\"></i></span>\n <span class=\"attachment-name\">{{ attachment.name }}</span>\n <button\n type=\"button\"\n class=\"attachment-remove\"\n (click)=\"removeAttachment($index)\"\n [attr.aria-label]=\"'@acorex:chat.actions.remove-attachment' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Typing Indicator -->\n @if (showTypingIndicator()) {\n <div class=\"typing-indicator-container\">\n <span class=\"typing-indicator\">{{ '@acorex:chat.status.someone-typing' | translate | async }}</span>\n </div>\n }\n </div>\n}\n\n<!-- Popover for attachment menu -->\n@if (attachPopoverTarget()) {\n <ax-popover\n #attachPopover\n [target]=\"attachPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n (onClosed)=\"onAttachPopoverClosed()\"\n >\n <ax-button-item-list>\n @for (action of startMenuActions(); track action.id) {\n <ax-button-item\n [text]=\"getActionLabel(action)\"\n (click)=\"onAttachMenuAction(action.id)\"\n [disabled]=\"!isActionEnabled(action)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-popover>\n}\n\n<!-- Popover for emoji/sticker picker -->\n@if (emojiPopoverTarget()) {\n <ax-popover\n #emojiPopover\n [target]=\"emojiPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n panelClass=\"composer-emoji-popover-panel\"\n (onClosed)=\"onEmojiPopoverClosed()\"\n >\n <div class=\"composer-emoji-popover\">\n <ax-conversation-registry-component-outlet\n [componentLoader]=\"composerPopupLoader\"\n [inputs]=\"getEmojiPopupInputs()\"\n />\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-composer{display:block;width:100%;@keyframes ax-conversation-composer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}ax-conversation-composer .ax-conversation-composer-banner{display:flex;min-height:2.75rem;align-items:stretch;gap:calc(var(--spacing, .25rem) * 0);border-block-style:var(--tw-border-style);border-block-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-composer .ax-conversation-composer-banner__accent{width:3px;flex-shrink:0;border-start-end-radius:var(--radius-sm, .25rem);border-end-end-radius:var(--radius-sm, .25rem);background-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__accent{background-color:rgba(var(--ax-sys-color-secondary-500))}ax-conversation-composer .ax-conversation-composer-banner__content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-composer .ax-conversation-composer-banner__icon{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600));background:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__icon{color:rgba(var(--ax-sys-color-secondary-600));background:rgba(var(--ax-sys-color-secondary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner__body{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}ax-conversation-composer .ax-conversation-composer-banner__body--clickable{cursor:pointer;border-radius:var(--ax-sys-border-radius);transition:opacity .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__body--clickable:hover{opacity:.85}}ax-conversation-composer .ax-conversation-composer-banner__label{font-size:.6875rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-600));text-transform:uppercase}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__label{color:rgba(var(--ax-sys-color-secondary-600))}ax-conversation-composer .ax-conversation-composer-banner__preview{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);overflow:hidden;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:.88}ax-conversation-composer .ax-conversation-composer-banner__preview i{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .ax-conversation-composer-banner__close{margin-inline-end:calc(var(--spacing, .25rem) * 1.5);display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;align-self:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.55);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__close:hover{color:rgba(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.06)}}ax-conversation-composer .ax-conversation-composer-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .emoji-icon{flex-shrink:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}ax-conversation-composer .composer-input-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}ax-conversation-composer .composer-actions-left,ax-conversation-composer .composer-actions-right{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-composer .composer-input-wrapper{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-composer .composer-input-wrapper .ax-editor-container{padding:calc(var(--spacing, .25rem) * 0)}ax-conversation-composer .composer-input{max-height:120px;min-height:calc(var(--spacing, .25rem) * 10);width:100%;resize:none;border-radius:1.25rem;border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);--tw-outline-style: none;outline-style:none;transition:border-color .2s}ax-conversation-composer .composer-input:focus{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .composer-attachments{display:flex;flex-wrap:wrap;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}ax-conversation-composer .attachment-item{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}ax-conversation-composer .attachment-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}ax-conversation-composer .attachment-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-composer .attachment-remove{display:flex;height:calc(var(--spacing, .25rem) * 5);width:calc(var(--spacing, .25rem) * 5);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:background .2s}@media(hover:hover){ax-conversation-composer .attachment-remove:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}}ax-conversation-composer .typing-indicator-container{padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .composer-component-fullwidth{min-height:72px;width:100%;background-color:rgba(var(--ax-sys-color-lightest-surface))}ax-conversation-composer .composer-emoji-popover{width:100%}ax-conversation-composer .ax-conversation-composer-primary--stopping .fa-spinner{animation:ax-conversation-composer-spin .75s linear infinite}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial;--tw-tracking: initial;--tw-leading: initial;--tw-outline-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXTextAreaComponent, selector: "ax-text-area", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "placeholder", "maxLength", "look", "rows", "allowResize", "showCounter", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXCommonModule }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
7075
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationComposerComponent, isStandalone: true, selector: "ax-conversation-composer", outputs: { messageSent: "messageSent", generationCancelled: "generationCancelled", emojiClick: "emojiClick", attachClick: "attachClick", voiceClick: "voiceClick" }, viewQueries: [{ propertyName: "textAreaRef", first: true, predicate: ["inputElement"], descendants: true, read: AXTextAreaComponent, isSignal: true }, { propertyName: "emojiPopoverRef", first: true, predicate: ["emojiPopover"], descendants: true, isSignal: true }, { propertyName: "attachPopoverRef", first: true, predicate: ["attachPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (activeConversation()) {\n <div class=\"composer\">\n <!-- Edit/Reply Banner -->\n @if (editingMessage() || replyingToMessage()) {\n <div\n class=\"ax-conversation-composer-banner\"\n [class.ax-conversation-composer-banner--edit]=\"!!editingMessage()\"\n [class.ax-conversation-composer-banner--reply]=\"!!replyingToMessage()\"\n >\n <div class=\"ax-conversation-composer-banner__accent\" aria-hidden=\"true\"></div>\n @if (editingMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-pen-to-square\"></i\n ></span>\n <div class=\"ax-conversation-composer-banner__body\">\n <span class=\"ax-conversation-composer-banner__label\">{{\n '@acorex:chat.composer.editing-message' | translate | async\n }}</span>\n @if (getEditingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n } @else if (replyingToMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-reply\"></i\n ></span>\n <div\n class=\"ax-conversation-composer-banner__body ax-conversation-composer-banner__body--clickable\"\n (click)=\"onReplyPreviewClick()\"\n >\n <span class=\"ax-conversation-composer-banner__label\">\n {{ '@acorex:chat.composer.replying-to' | translate | async }} {{ getReplyingSenderName() }}\n </span>\n @if (getReplyingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n }\n <button\n type=\"button\"\n class=\"ax-conversation-composer-banner__close\"\n (click)=\"cancelEditReply()\"\n [attr.aria-label]=\"'@acorex:chat.actions.cancel' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <!-- Input Area -->\n <div class=\"composer-input-container\">\n <!-- Start actions -->\n <div class=\"composer-actions-left\">\n @if (startMenuActions().length > 0) {\n <ax-button\n class=\"rounded-full text-xl\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"('@acorex:chat.tooltips.attach-file' | translate | async) ?? ''\"\n (onClick)=\"onAttachMenuClick($event)\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-paperclip\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n @for (action of startInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <!-- Text Input -->\n <div class=\"composer-input-wrapper\">\n <ax-text-area\n #inputElement\n [(ngModel)]=\"draftText\"\n (onKeyDown)=\"onKeyDown($event)\"\n (onValueChanged)=\"onInput()\"\n [placeholder]=\"placeholder()\"\n (onKeyDown)=\"onEnter($event)\"\n [rows]=\"inputRows()\"\n ></ax-text-area>\n </div>\n\n <!-- End actions -->\n <div class=\"composer-actions-right\">\n @for (action of endInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n <ax-button\n class=\"rounded-full text-xl\"\n [class.ax-conversation-composer-primary--stopping]=\"primaryButtonMode() === 'stopping'\"\n color=\"primary\"\n look=\"solid\"\n [iconOnly]=\"true\"\n [text]=\"getPrimaryButtonLabel()\"\n [disabled]=\"isPrimaryButtonDisabled()\"\n (onClick)=\"onPrimaryButtonClick()\"\n >\n <ax-prefix>\n <i [class]=\"getPrimaryButtonIcon()\"></i>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n\n <!-- Attachments Preview -->\n @if (attachments().length > 0) {\n <div class=\"composer-attachments\">\n @for (attachment of attachments(); track $index) {\n <div class=\"attachment-item\">\n <span class=\"attachment-icon\"><i class=\"fa-light fa-paperclip\"></i></span>\n <span class=\"attachment-name\">{{ attachment.name }}</span>\n <button\n type=\"button\"\n class=\"attachment-remove\"\n (click)=\"removeAttachment($index)\"\n [attr.aria-label]=\"'@acorex:chat.actions.remove-attachment' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n }\n </div>\n}\n\n<!-- Popover for attachment menu -->\n@if (attachPopoverTarget()) {\n <ax-popover\n #attachPopover\n [target]=\"attachPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n (onClosed)=\"onAttachPopoverClosed()\"\n >\n <ax-button-item-list>\n @for (action of startMenuActions(); track action.id) {\n <ax-button-item\n [text]=\"getActionLabel(action)\"\n (click)=\"onAttachMenuAction(action.id)\"\n [disabled]=\"!isActionEnabled(action)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-popover>\n}\n\n<!-- Popover for emoji/sticker picker -->\n@if (emojiPopoverTarget()) {\n <ax-popover\n #emojiPopover\n [target]=\"emojiPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n panelClass=\"composer-emoji-popover-panel\"\n (onClosed)=\"onEmojiPopoverClosed()\"\n >\n <div class=\"composer-emoji-popover\">\n <ax-conversation-registry-component-outlet\n [componentLoader]=\"composerPopupLoader\"\n [inputs]=\"getEmojiPopupInputs()\"\n />\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-composer{display:block;width:100%;@keyframes ax-conversation-composer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}ax-conversation-composer .ax-conversation-composer-banner{display:flex;min-height:2.75rem;align-items:stretch;gap:calc(var(--spacing, .25rem) * 0);border-block-style:var(--tw-border-style);border-block-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-composer .ax-conversation-composer-banner__accent{width:3px;flex-shrink:0;border-start-end-radius:var(--radius-sm, .25rem);border-end-end-radius:var(--radius-sm, .25rem);background-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__accent{background-color:rgba(var(--ax-sys-color-secondary-500))}ax-conversation-composer .ax-conversation-composer-banner__content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-composer .ax-conversation-composer-banner__icon{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600));background:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__icon{color:rgba(var(--ax-sys-color-secondary-600));background:rgba(var(--ax-sys-color-secondary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner__body{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}ax-conversation-composer .ax-conversation-composer-banner__body--clickable{cursor:pointer;border-radius:var(--ax-sys-border-radius);transition:opacity .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__body--clickable:hover{opacity:.85}}ax-conversation-composer .ax-conversation-composer-banner__label{font-size:.6875rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-600));text-transform:uppercase}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__label{color:rgba(var(--ax-sys-color-secondary-600))}ax-conversation-composer .ax-conversation-composer-banner__preview{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);overflow:hidden;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:.88}ax-conversation-composer .ax-conversation-composer-banner__preview i{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .ax-conversation-composer-banner__close{margin-inline-end:calc(var(--spacing, .25rem) * 1.5);display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;align-self:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.55);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__close:hover{color:rgba(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.06)}}ax-conversation-composer .ax-conversation-composer-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .emoji-icon{flex-shrink:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}ax-conversation-composer .composer-input-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}ax-conversation-composer .composer-actions-left,ax-conversation-composer .composer-actions-right{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-composer .composer-input-wrapper{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-composer .composer-input-wrapper .ax-editor-container{padding:calc(var(--spacing, .25rem) * 0)}ax-conversation-composer .composer-input{max-height:120px;min-height:calc(var(--spacing, .25rem) * 10);width:100%;resize:none;border-radius:1.25rem;border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);--tw-outline-style: none;outline-style:none;transition:border-color .2s}ax-conversation-composer .composer-input:focus{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .composer-attachments{display:flex;flex-wrap:wrap;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}ax-conversation-composer .attachment-item{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}ax-conversation-composer .attachment-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}ax-conversation-composer .attachment-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-composer .attachment-remove{display:flex;height:calc(var(--spacing, .25rem) * 5);width:calc(var(--spacing, .25rem) * 5);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:background .2s}@media(hover:hover){ax-conversation-composer .attachment-remove:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}}ax-conversation-composer .composer-component-fullwidth{min-height:72px;width:100%;background-color:rgba(var(--ax-sys-color-lightest-surface))}ax-conversation-composer .composer-emoji-popover{width:100%}ax-conversation-composer .ax-conversation-composer-primary--stopping .fa-spinner{animation:ax-conversation-composer-spin .75s linear infinite}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial;--tw-tracking: initial;--tw-leading: initial;--tw-outline-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXTextAreaComponent, selector: "ax-text-area", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "placeholder", "maxLength", "look", "rows", "allowResize", "showCounter", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXCommonModule }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
6855
7076
|
}
|
|
6856
7077
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationComposerComponent, decorators: [{
|
|
6857
7078
|
type: Component,
|
|
@@ -6867,7 +7088,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
6867
7088
|
AXTranslationModule,
|
|
6868
7089
|
AXButtonItemComponent,
|
|
6869
7090
|
AXButtonItemListComponent,
|
|
6870
|
-
], template: "@if (activeConversation()) {\n <div class=\"composer\">\n <!-- Edit/Reply Banner -->\n @if (editingMessage() || replyingToMessage()) {\n <div\n class=\"ax-conversation-composer-banner\"\n [class.ax-conversation-composer-banner--edit]=\"!!editingMessage()\"\n [class.ax-conversation-composer-banner--reply]=\"!!replyingToMessage()\"\n >\n <div class=\"ax-conversation-composer-banner__accent\" aria-hidden=\"true\"></div>\n @if (editingMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-pen-to-square\"></i\n ></span>\n <div class=\"ax-conversation-composer-banner__body\">\n <span class=\"ax-conversation-composer-banner__label\">{{\n '@acorex:chat.composer.editing-message' | translate | async\n }}</span>\n @if (getEditingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n } @else if (replyingToMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-reply\"></i\n ></span>\n <div\n class=\"ax-conversation-composer-banner__body ax-conversation-composer-banner__body--clickable\"\n (click)=\"onReplyPreviewClick()\"\n >\n <span class=\"ax-conversation-composer-banner__label\">\n {{ '@acorex:chat.composer.replying-to' | translate | async }} {{ getReplyingSenderName() }}\n </span>\n @if (getReplyingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n }\n <button\n type=\"button\"\n class=\"ax-conversation-composer-banner__close\"\n (click)=\"cancelEditReply()\"\n [attr.aria-label]=\"'@acorex:chat.actions.cancel' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <!-- Input Area -->\n <div class=\"composer-input-container\">\n <!-- Start actions -->\n <div class=\"composer-actions-left\">\n @if (startMenuActions().length > 0) {\n <ax-button\n class=\"rounded-full text-xl\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"('@acorex:chat.tooltips.attach-file' | translate | async) ?? ''\"\n (onClick)=\"onAttachMenuClick($event)\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-paperclip\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n @for (action of startInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <!-- Text Input -->\n <div class=\"composer-input-wrapper\">\n <ax-text-area\n #inputElement\n [(ngModel)]=\"draftText\"\n (onKeyDown)=\"onKeyDown($event)\"\n (onValueChanged)=\"onInput()\"\n [placeholder]=\"placeholder()\"\n (onKeyDown)=\"onEnter($event)\"\n [rows]=\"inputRows()\"\n ></ax-text-area>\n </div>\n\n <!-- End actions -->\n <div class=\"composer-actions-right\">\n @for (action of endInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n <ax-button\n class=\"rounded-full text-xl\"\n [class.ax-conversation-composer-primary--stopping]=\"primaryButtonMode() === 'stopping'\"\n color=\"primary\"\n look=\"solid\"\n [iconOnly]=\"true\"\n [text]=\"getPrimaryButtonLabel()\"\n [disabled]=\"isPrimaryButtonDisabled()\"\n (onClick)=\"onPrimaryButtonClick()\"\n >\n <ax-prefix>\n <i [class]=\"getPrimaryButtonIcon()\"></i>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n\n <!-- Attachments Preview -->\n @if (attachments().length > 0) {\n <div class=\"composer-attachments\">\n @for (attachment of attachments(); track $index) {\n <div class=\"attachment-item\">\n <span class=\"attachment-icon\"><i class=\"fa-light fa-paperclip\"></i></span>\n <span class=\"attachment-name\">{{ attachment.name }}</span>\n <button\n type=\"button\"\n class=\"attachment-remove\"\n (click)=\"removeAttachment($index)\"\n [attr.aria-label]=\"'@acorex:chat.actions.remove-attachment' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Typing Indicator -->\n @if (showTypingIndicator()) {\n <div class=\"typing-indicator-container\">\n <span class=\"typing-indicator\">{{ '@acorex:chat.status.someone-typing' | translate | async }}</span>\n </div>\n }\n </div>\n}\n\n<!-- Popover for attachment menu -->\n@if (attachPopoverTarget()) {\n <ax-popover\n #attachPopover\n [target]=\"attachPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n (onClosed)=\"onAttachPopoverClosed()\"\n >\n <ax-button-item-list>\n @for (action of startMenuActions(); track action.id) {\n <ax-button-item\n [text]=\"getActionLabel(action)\"\n (click)=\"onAttachMenuAction(action.id)\"\n [disabled]=\"!isActionEnabled(action)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-popover>\n}\n\n<!-- Popover for emoji/sticker picker -->\n@if (emojiPopoverTarget()) {\n <ax-popover\n #emojiPopover\n [target]=\"emojiPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n panelClass=\"composer-emoji-popover-panel\"\n (onClosed)=\"onEmojiPopoverClosed()\"\n >\n <div class=\"composer-emoji-popover\">\n <ax-conversation-registry-component-outlet\n [componentLoader]=\"composerPopupLoader\"\n [inputs]=\"getEmojiPopupInputs()\"\n />\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-composer{display:block;width:100%;@keyframes ax-conversation-composer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}ax-conversation-composer .ax-conversation-composer-banner{display:flex;min-height:2.75rem;align-items:stretch;gap:calc(var(--spacing, .25rem) * 0);border-block-style:var(--tw-border-style);border-block-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-composer .ax-conversation-composer-banner__accent{width:3px;flex-shrink:0;border-start-end-radius:var(--radius-sm, .25rem);border-end-end-radius:var(--radius-sm, .25rem);background-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__accent{background-color:rgba(var(--ax-sys-color-secondary-500))}ax-conversation-composer .ax-conversation-composer-banner__content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-composer .ax-conversation-composer-banner__icon{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600));background:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__icon{color:rgba(var(--ax-sys-color-secondary-600));background:rgba(var(--ax-sys-color-secondary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner__body{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}ax-conversation-composer .ax-conversation-composer-banner__body--clickable{cursor:pointer;border-radius:var(--ax-sys-border-radius);transition:opacity .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__body--clickable:hover{opacity:.85}}ax-conversation-composer .ax-conversation-composer-banner__label{font-size:.6875rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-600));text-transform:uppercase}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__label{color:rgba(var(--ax-sys-color-secondary-600))}ax-conversation-composer .ax-conversation-composer-banner__preview{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);overflow:hidden;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:.88}ax-conversation-composer .ax-conversation-composer-banner__preview i{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .ax-conversation-composer-banner__close{margin-inline-end:calc(var(--spacing, .25rem) * 1.5);display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;align-self:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.55);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__close:hover{color:rgba(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.06)}}ax-conversation-composer .ax-conversation-composer-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .emoji-icon{flex-shrink:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}ax-conversation-composer .composer-input-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}ax-conversation-composer .composer-actions-left,ax-conversation-composer .composer-actions-right{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-composer .composer-input-wrapper{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-composer .composer-input-wrapper .ax-editor-container{padding:calc(var(--spacing, .25rem) * 0)}ax-conversation-composer .composer-input{max-height:120px;min-height:calc(var(--spacing, .25rem) * 10);width:100%;resize:none;border-radius:1.25rem;border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);--tw-outline-style: none;outline-style:none;transition:border-color .2s}ax-conversation-composer .composer-input:focus{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .composer-attachments{display:flex;flex-wrap:wrap;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}ax-conversation-composer .attachment-item{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}ax-conversation-composer .attachment-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}ax-conversation-composer .attachment-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-composer .attachment-remove{display:flex;height:calc(var(--spacing, .25rem) * 5);width:calc(var(--spacing, .25rem) * 5);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:background .2s}@media(hover:hover){ax-conversation-composer .attachment-remove:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}}ax-conversation-composer .typing-indicator-container{padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .composer-component-fullwidth{min-height:72px;width:100%;background-color:rgba(var(--ax-sys-color-lightest-surface))}ax-conversation-composer .composer-emoji-popover{width:100%}ax-conversation-composer .ax-conversation-composer-primary--stopping .fa-spinner{animation:ax-conversation-composer-spin .75s linear infinite}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial;--tw-tracking: initial;--tw-leading: initial;--tw-outline-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
7091
|
+
], template: "@if (activeConversation()) {\n <div class=\"composer\">\n <!-- Edit/Reply Banner -->\n @if (editingMessage() || replyingToMessage()) {\n <div\n class=\"ax-conversation-composer-banner\"\n [class.ax-conversation-composer-banner--edit]=\"!!editingMessage()\"\n [class.ax-conversation-composer-banner--reply]=\"!!replyingToMessage()\"\n >\n <div class=\"ax-conversation-composer-banner__accent\" aria-hidden=\"true\"></div>\n @if (editingMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-pen-to-square\"></i\n ></span>\n <div class=\"ax-conversation-composer-banner__body\">\n <span class=\"ax-conversation-composer-banner__label\">{{\n '@acorex:chat.composer.editing-message' | translate | async\n }}</span>\n @if (getEditingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n } @else if (replyingToMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-reply\"></i\n ></span>\n <div\n class=\"ax-conversation-composer-banner__body ax-conversation-composer-banner__body--clickable\"\n (click)=\"onReplyPreviewClick()\"\n >\n <span class=\"ax-conversation-composer-banner__label\">\n {{ '@acorex:chat.composer.replying-to' | translate | async }} {{ getReplyingSenderName() }}\n </span>\n @if (getReplyingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n }\n <button\n type=\"button\"\n class=\"ax-conversation-composer-banner__close\"\n (click)=\"cancelEditReply()\"\n [attr.aria-label]=\"'@acorex:chat.actions.cancel' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <!-- Input Area -->\n <div class=\"composer-input-container\">\n <!-- Start actions -->\n <div class=\"composer-actions-left\">\n @if (startMenuActions().length > 0) {\n <ax-button\n class=\"rounded-full text-xl\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"('@acorex:chat.tooltips.attach-file' | translate | async) ?? ''\"\n (onClick)=\"onAttachMenuClick($event)\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-paperclip\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n @for (action of startInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <!-- Text Input -->\n <div class=\"composer-input-wrapper\">\n <ax-text-area\n #inputElement\n [(ngModel)]=\"draftText\"\n (onKeyDown)=\"onKeyDown($event)\"\n (onValueChanged)=\"onInput()\"\n [placeholder]=\"placeholder()\"\n (onKeyDown)=\"onEnter($event)\"\n [rows]=\"inputRows()\"\n ></ax-text-area>\n </div>\n\n <!-- End actions -->\n <div class=\"composer-actions-right\">\n @for (action of endInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n <ax-button\n class=\"rounded-full text-xl\"\n [class.ax-conversation-composer-primary--stopping]=\"primaryButtonMode() === 'stopping'\"\n color=\"primary\"\n look=\"solid\"\n [iconOnly]=\"true\"\n [text]=\"getPrimaryButtonLabel()\"\n [disabled]=\"isPrimaryButtonDisabled()\"\n (onClick)=\"onPrimaryButtonClick()\"\n >\n <ax-prefix>\n <i [class]=\"getPrimaryButtonIcon()\"></i>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n\n <!-- Attachments Preview -->\n @if (attachments().length > 0) {\n <div class=\"composer-attachments\">\n @for (attachment of attachments(); track $index) {\n <div class=\"attachment-item\">\n <span class=\"attachment-icon\"><i class=\"fa-light fa-paperclip\"></i></span>\n <span class=\"attachment-name\">{{ attachment.name }}</span>\n <button\n type=\"button\"\n class=\"attachment-remove\"\n (click)=\"removeAttachment($index)\"\n [attr.aria-label]=\"'@acorex:chat.actions.remove-attachment' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n }\n </div>\n}\n\n<!-- Popover for attachment menu -->\n@if (attachPopoverTarget()) {\n <ax-popover\n #attachPopover\n [target]=\"attachPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n (onClosed)=\"onAttachPopoverClosed()\"\n >\n <ax-button-item-list>\n @for (action of startMenuActions(); track action.id) {\n <ax-button-item\n [text]=\"getActionLabel(action)\"\n (click)=\"onAttachMenuAction(action.id)\"\n [disabled]=\"!isActionEnabled(action)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-popover>\n}\n\n<!-- Popover for emoji/sticker picker -->\n@if (emojiPopoverTarget()) {\n <ax-popover\n #emojiPopover\n [target]=\"emojiPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n panelClass=\"composer-emoji-popover-panel\"\n (onClosed)=\"onEmojiPopoverClosed()\"\n >\n <div class=\"composer-emoji-popover\">\n <ax-conversation-registry-component-outlet\n [componentLoader]=\"composerPopupLoader\"\n [inputs]=\"getEmojiPopupInputs()\"\n />\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-composer{display:block;width:100%;@keyframes ax-conversation-composer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}ax-conversation-composer .ax-conversation-composer-banner{display:flex;min-height:2.75rem;align-items:stretch;gap:calc(var(--spacing, .25rem) * 0);border-block-style:var(--tw-border-style);border-block-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-composer .ax-conversation-composer-banner__accent{width:3px;flex-shrink:0;border-start-end-radius:var(--radius-sm, .25rem);border-end-end-radius:var(--radius-sm, .25rem);background-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__accent{background-color:rgba(var(--ax-sys-color-secondary-500))}ax-conversation-composer .ax-conversation-composer-banner__content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-composer .ax-conversation-composer-banner__icon{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600));background:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__icon{color:rgba(var(--ax-sys-color-secondary-600));background:rgba(var(--ax-sys-color-secondary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner__body{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}ax-conversation-composer .ax-conversation-composer-banner__body--clickable{cursor:pointer;border-radius:var(--ax-sys-border-radius);transition:opacity .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__body--clickable:hover{opacity:.85}}ax-conversation-composer .ax-conversation-composer-banner__label{font-size:.6875rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-600));text-transform:uppercase}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__label{color:rgba(var(--ax-sys-color-secondary-600))}ax-conversation-composer .ax-conversation-composer-banner__preview{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);overflow:hidden;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:.88}ax-conversation-composer .ax-conversation-composer-banner__preview i{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .ax-conversation-composer-banner__close{margin-inline-end:calc(var(--spacing, .25rem) * 1.5);display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;align-self:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.55);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__close:hover{color:rgba(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.06)}}ax-conversation-composer .ax-conversation-composer-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .emoji-icon{flex-shrink:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}ax-conversation-composer .composer-input-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}ax-conversation-composer .composer-actions-left,ax-conversation-composer .composer-actions-right{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-composer .composer-input-wrapper{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-composer .composer-input-wrapper .ax-editor-container{padding:calc(var(--spacing, .25rem) * 0)}ax-conversation-composer .composer-input{max-height:120px;min-height:calc(var(--spacing, .25rem) * 10);width:100%;resize:none;border-radius:1.25rem;border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);--tw-outline-style: none;outline-style:none;transition:border-color .2s}ax-conversation-composer .composer-input:focus{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .composer-attachments{display:flex;flex-wrap:wrap;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}ax-conversation-composer .attachment-item{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}ax-conversation-composer .attachment-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}ax-conversation-composer .attachment-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-composer .attachment-remove{display:flex;height:calc(var(--spacing, .25rem) * 5);width:calc(var(--spacing, .25rem) * 5);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:background .2s}@media(hover:hover){ax-conversation-composer .attachment-remove:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}}ax-conversation-composer .composer-component-fullwidth{min-height:72px;width:100%;background-color:rgba(var(--ax-sys-color-lightest-surface))}ax-conversation-composer .composer-emoji-popover{width:100%}ax-conversation-composer .ax-conversation-composer-primary--stopping .fa-spinner{animation:ax-conversation-composer-spin .75s linear infinite}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial;--tw-tracking: initial;--tw-leading: initial;--tw-outline-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
6871
7092
|
}], ctorParameters: () => [], propDecorators: { textAreaRef: [{ type: i0.ViewChild, args: ['inputElement', { ...{ read: AXTextAreaComponent }, isSignal: true }] }], messageSent: [{ type: i0.Output, args: ["messageSent"] }], generationCancelled: [{ type: i0.Output, args: ["generationCancelled"] }], emojiClick: [{ type: i0.Output, args: ["emojiClick"] }], attachClick: [{ type: i0.Output, args: ["attachClick"] }], voiceClick: [{ type: i0.Output, args: ["voiceClick"] }], emojiPopoverRef: [{ type: i0.ViewChild, args: ['emojiPopover', { isSignal: true }] }], attachPopoverRef: [{ type: i0.ViewChild, args: ['attachPopover', { isSignal: true }] }] } });
|
|
6872
7093
|
|
|
6873
7094
|
/**
|
|
@@ -7130,9 +7351,19 @@ class AXConversationAvatarComponent {
|
|
|
7130
7351
|
displayIcon: explicitIcon ?? resolved.icon,
|
|
7131
7352
|
};
|
|
7132
7353
|
}
|
|
7354
|
+
const conversation = this.conversation();
|
|
7355
|
+
const explicitName = this.name();
|
|
7356
|
+
const explicitAvatar = this.avatar();
|
|
7357
|
+
const explicitIcon = this.icon();
|
|
7358
|
+
const resolved = conversation
|
|
7359
|
+
? resolveConversationAvatarDisplay(conversation, this.currentUserId())
|
|
7360
|
+
: { name: explicitName ?? '?', avatar: explicitAvatar, icon: explicitIcon };
|
|
7133
7361
|
return {
|
|
7134
|
-
conversationId:
|
|
7362
|
+
conversationId: conversation?.id ?? '',
|
|
7135
7363
|
size: this.size(),
|
|
7364
|
+
displayName: explicitName ?? resolved.name,
|
|
7365
|
+
displayAvatar: explicitAvatar ?? resolved.avatar,
|
|
7366
|
+
displayIcon: explicitIcon ?? resolved.icon,
|
|
7136
7367
|
};
|
|
7137
7368
|
}, /* @ts-ignore */
|
|
7138
7369
|
...(ngDevMode ? [{ debugName: "customInputs" }] : /* istanbul ignore next */ []));
|
|
@@ -7175,14 +7406,14 @@ class AXConversationAvatarComponent {
|
|
|
7175
7406
|
this.fallbackInitials = computed(() => AXConversationMessageUtilsService.getInitials(this.fallbackDisplay().name), /* @ts-ignore */
|
|
7176
7407
|
...(ngDevMode ? [{ debugName: "fallbackInitials" }] : /* istanbul ignore next */ []));
|
|
7177
7408
|
this.resolvedStatus = computed(() => {
|
|
7178
|
-
const
|
|
7179
|
-
if (!
|
|
7409
|
+
const userId = this.resolvedUserId();
|
|
7410
|
+
if (!userId || !this.showStatus()) {
|
|
7180
7411
|
return undefined;
|
|
7181
7412
|
}
|
|
7182
|
-
|
|
7413
|
+
const presence = this.conversationService?.getUserPresence(userId);
|
|
7414
|
+
return AXConversationMessageUtilsService.getUserPresenceStatus(presence);
|
|
7183
7415
|
}, /* @ts-ignore */
|
|
7184
7416
|
...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
|
|
7185
|
-
/** Hide presence badge when a registered custom avatar component is rendered. */
|
|
7186
7417
|
this.statusBadgePresence = computed(() => {
|
|
7187
7418
|
if (this.customComponent()) {
|
|
7188
7419
|
return undefined;
|
|
@@ -7192,13 +7423,13 @@ class AXConversationAvatarComponent {
|
|
|
7192
7423
|
...(ngDevMode ? [{ debugName: "statusBadgePresence" }] : /* istanbul ignore next */ []));
|
|
7193
7424
|
}
|
|
7194
7425
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationAvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7195
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationAvatarComponent, isStandalone: true, selector: "ax-conversation-avatar", inputs: { kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, userId: { classPropertyName: "userId", publicName: "userId", isSignal: true, isRequired: false, transformFunction: null }, conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showStatus: { classPropertyName: "showStatus", publicName: "showStatus", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--ax-conversation-avatar-size.px": "size()" } }, ngImport: i0, template: "<div class=\"ax-conversation-avatar\">\n @if (customComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; inputs: filteredCustomInputs()\" />\n } @else {\n <ax-avatar [size]=\"size()\">\n @if (fallbackDisplay().avatar; as avatarSrc) {\n <ax-image [src]=\"avatarSrc\" [alt]=\"fallbackDisplay().name\"></ax-image>\n } @else if (fallbackDisplay().icon; as iconClass) {\n <ax-icon><i [class]=\"iconClass\" aria-hidden=\"true\"></i></ax-icon>\n } @else {\n <ax-label>{{ fallbackInitials() }}</ax-label>\n }\n </ax-avatar>\n }\n\n @if (statusBadgePresence(); as presence) {\n <span\n class=\"ax-conversation-avatar-status\"\n [class.status-online]=\"presence === 'online'\"\n [class.status-offline]=\"presence === 'offline'\"\n [class.status-away]=\"presence === 'away'\"\n ></span>\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-avatar{display:inline-flex}ax-conversation-avatar .ax-conversation-avatar{position:relative;display:inline-flex}ax-conversation-avatar .ax-conversation-avatar-status{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * .5);bottom:calc(var(--spacing, .25rem) * .5);height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px)}ax-conversation-avatar .ax-conversation-avatar-status.status-online{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-success-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-away{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-warning-500))}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
7426
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationAvatarComponent, isStandalone: true, selector: "ax-conversation-avatar", inputs: { kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, userId: { classPropertyName: "userId", publicName: "userId", isSignal: true, isRequired: false, transformFunction: null }, conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showStatus: { classPropertyName: "showStatus", publicName: "showStatus", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--ax-conversation-avatar-size.px": "size()" } }, ngImport: i0, template: "<div class=\"ax-conversation-avatar\">\n @if (customComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; inputs: filteredCustomInputs()\" />\n } @else {\n <ax-avatar [size]=\"size()\">\n @if (fallbackDisplay().avatar; as avatarSrc) {\n <ax-image [src]=\"avatarSrc\" [alt]=\"fallbackDisplay().name\"></ax-image>\n } @else if (fallbackDisplay().icon; as iconClass) {\n <ax-icon><i [class]=\"iconClass\" aria-hidden=\"true\"></i></ax-icon>\n } @else {\n <ax-label>{{ fallbackInitials() }}</ax-label>\n }\n </ax-avatar>\n }\n\n @if (statusBadgePresence(); as presence) {\n <span\n class=\"ax-conversation-avatar-status\"\n [class.status-online]=\"presence === 'online'\"\n [class.status-offline]=\"presence === 'offline'\"\n [class.status-away]=\"presence === 'away'\"\n [class.status-busy]=\"presence === 'busy'\"\n ></span>\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-avatar{display:inline-flex}ax-conversation-avatar .ax-conversation-avatar{position:relative;display:inline-flex}ax-conversation-avatar .ax-conversation-avatar-status{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * .5);bottom:calc(var(--spacing, .25rem) * .5);height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px)}ax-conversation-avatar .ax-conversation-avatar-status.status-online{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-success-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-away{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-warning-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-offline{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:var(--color-neutral-400, oklch(70.8% 0 0))}ax-conversation-avatar .ax-conversation-avatar-status.status-busy{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-danger-500))}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
7196
7427
|
}
|
|
7197
7428
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationAvatarComponent, decorators: [{
|
|
7198
7429
|
type: Component,
|
|
7199
7430
|
args: [{ selector: 'ax-conversation-avatar', encapsulation: ViewEncapsulation.None, imports: [NgComponentOutlet, AXAvatarComponent, AXDecoratorModule, AXImageComponent, AXLabelComponent], host: {
|
|
7200
7431
|
'[style.--ax-conversation-avatar-size.px]': 'size()',
|
|
7201
|
-
}, template: "<div class=\"ax-conversation-avatar\">\n @if (customComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; inputs: filteredCustomInputs()\" />\n } @else {\n <ax-avatar [size]=\"size()\">\n @if (fallbackDisplay().avatar; as avatarSrc) {\n <ax-image [src]=\"avatarSrc\" [alt]=\"fallbackDisplay().name\"></ax-image>\n } @else if (fallbackDisplay().icon; as iconClass) {\n <ax-icon><i [class]=\"iconClass\" aria-hidden=\"true\"></i></ax-icon>\n } @else {\n <ax-label>{{ fallbackInitials() }}</ax-label>\n }\n </ax-avatar>\n }\n\n @if (statusBadgePresence(); as presence) {\n <span\n class=\"ax-conversation-avatar-status\"\n [class.status-online]=\"presence === 'online'\"\n [class.status-offline]=\"presence === 'offline'\"\n [class.status-away]=\"presence === 'away'\"\n ></span>\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-avatar{display:inline-flex}ax-conversation-avatar .ax-conversation-avatar{position:relative;display:inline-flex}ax-conversation-avatar .ax-conversation-avatar-status{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * .5);bottom:calc(var(--spacing, .25rem) * .5);height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px)}ax-conversation-avatar .ax-conversation-avatar-status.status-online{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-success-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-away{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-warning-500))}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
7432
|
+
}, template: "<div class=\"ax-conversation-avatar\">\n @if (customComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; inputs: filteredCustomInputs()\" />\n } @else {\n <ax-avatar [size]=\"size()\">\n @if (fallbackDisplay().avatar; as avatarSrc) {\n <ax-image [src]=\"avatarSrc\" [alt]=\"fallbackDisplay().name\"></ax-image>\n } @else if (fallbackDisplay().icon; as iconClass) {\n <ax-icon><i [class]=\"iconClass\" aria-hidden=\"true\"></i></ax-icon>\n } @else {\n <ax-label>{{ fallbackInitials() }}</ax-label>\n }\n </ax-avatar>\n }\n\n @if (statusBadgePresence(); as presence) {\n <span\n class=\"ax-conversation-avatar-status\"\n [class.status-online]=\"presence === 'online'\"\n [class.status-offline]=\"presence === 'offline'\"\n [class.status-away]=\"presence === 'away'\"\n [class.status-busy]=\"presence === 'busy'\"\n ></span>\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-avatar{display:inline-flex}ax-conversation-avatar .ax-conversation-avatar{position:relative;display:inline-flex}ax-conversation-avatar .ax-conversation-avatar-status{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * .5);bottom:calc(var(--spacing, .25rem) * .5);height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px)}ax-conversation-avatar .ax-conversation-avatar-status.status-online{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-success-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-away{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-warning-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-offline{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:var(--color-neutral-400, oklch(70.8% 0 0))}ax-conversation-avatar .ax-conversation-avatar-status.status-busy{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-danger-500))}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
7202
7433
|
}], propDecorators: { kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: false }] }], userId: [{ type: i0.Input, args: [{ isSignal: true, alias: "userId", required: false }] }], conversation: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversation", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "showStatus", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], avatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatar", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
|
|
7203
7434
|
|
|
7204
7435
|
/**
|
|
@@ -7469,33 +7700,21 @@ class AXConversationInfoBarComponent {
|
|
|
7469
7700
|
this.platform = inject(AXPlatform);
|
|
7470
7701
|
this.destroyRef = inject(DestroyRef);
|
|
7471
7702
|
this.customUserAvatarComponent = inject(AX_CONVERSATION_USER_AVATAR_COMPONENT, { optional: true });
|
|
7472
|
-
/** Bumps when viewport changes so dynamic action locations re-resolve. */
|
|
7473
7703
|
this.layoutTick = signal(0, /* @ts-ignore */
|
|
7474
7704
|
...(ngDevMode ? [{ debugName: "layoutTick" }] : /* istanbul ignore next */ []));
|
|
7475
|
-
/** Whether a custom user avatar component is registered via conversation config. */
|
|
7476
7705
|
this.hasCustomUserAvatar = computed(() => !!this.customUserAvatarComponent, /* @ts-ignore */
|
|
7477
7706
|
...(ngDevMode ? [{ debugName: "hasCustomUserAvatar" }] : /* istanbul ignore next */ []));
|
|
7478
|
-
/** Active conversation */
|
|
7479
7707
|
this.activeConversation = this.infoBar.activeConversation;
|
|
7480
|
-
/** Active component from service */
|
|
7481
7708
|
this.activeComponent = this.infoBar.activeComponent;
|
|
7482
|
-
/** Active banner from service */
|
|
7483
7709
|
this.activeBanner = this.infoBar.activeBanner;
|
|
7484
|
-
/** Members popover target element — retained for API compatibility */
|
|
7485
7710
|
this.membersPopoverTarget = signal(null, /* @ts-ignore */
|
|
7486
7711
|
...(ngDevMode ? [{ debugName: "membersPopoverTarget" }] : /* istanbul ignore next */ []));
|
|
7487
|
-
/** Loading state for async actions */
|
|
7488
7712
|
this.actionLoading = signal(false, /* @ts-ignore */
|
|
7489
7713
|
...(ngDevMode ? [{ debugName: "actionLoading" }] : /* istanbul ignore next */ []));
|
|
7490
|
-
/** Info area clicked event — host apps can open a custom conversation details UI */
|
|
7491
7714
|
this.infoClick = output();
|
|
7492
|
-
/** Search clicked event */
|
|
7493
7715
|
this.searchClick = output();
|
|
7494
|
-
/** Search query changed event */
|
|
7495
7716
|
this.searchQuery = output();
|
|
7496
|
-
/** Menu item clicked event */
|
|
7497
7717
|
this.menuItemAction = output();
|
|
7498
|
-
/** Inline action buttons from registry */
|
|
7499
7718
|
this.inlineActions = computed(() => {
|
|
7500
7719
|
this.layoutTick();
|
|
7501
7720
|
const conversation = this.activeConversation();
|
|
@@ -7504,24 +7723,25 @@ class AXConversationInfoBarComponent {
|
|
|
7504
7723
|
return this.registry.infoBarActions.getInlineActions(conversation);
|
|
7505
7724
|
}, /* @ts-ignore */
|
|
7506
7725
|
...(ngDevMode ? [{ debugName: "inlineActions" }] : /* istanbul ignore next */ []));
|
|
7507
|
-
/** Dropdown menu items from registry */
|
|
7508
7726
|
this.menuItems = computed(() => {
|
|
7509
7727
|
this.layoutTick();
|
|
7510
7728
|
const conversation = this.activeConversation();
|
|
7511
7729
|
if (!conversation)
|
|
7512
7730
|
return [];
|
|
7513
|
-
// Get menu actions from registry
|
|
7514
7731
|
const actions = this.registry.infoBarActions.getMenuActions(conversation);
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7732
|
+
return actions.map((action) => {
|
|
7733
|
+
const originalIndex = actions.findIndex((a) => a.id === action.id);
|
|
7734
|
+
const nextAction = actions[originalIndex + 1];
|
|
7735
|
+
const hasBreakAfter = nextAction?.divider === true;
|
|
7736
|
+
return {
|
|
7737
|
+
id: action.id,
|
|
7738
|
+
label: this.registry.infoBarActions.getActionLabel(action, conversation),
|
|
7739
|
+
icon: this.registry.infoBarActions.getActionIcon(action, conversation),
|
|
7740
|
+
divider: action.divider,
|
|
7741
|
+
destructive: action.destructive,
|
|
7742
|
+
disabled: !this.registry.infoBarActions.isActionEnabled(action, { conversation }),
|
|
7743
|
+
};
|
|
7744
|
+
});
|
|
7525
7745
|
}, /* @ts-ignore */
|
|
7526
7746
|
...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
|
|
7527
7747
|
const resizeSub = this.platform.resize.subscribe(() => {
|
|
@@ -7529,23 +7749,24 @@ class AXConversationInfoBarComponent {
|
|
|
7529
7749
|
});
|
|
7530
7750
|
this.destroyRef.onDestroy(() => resizeSub.unsubscribe());
|
|
7531
7751
|
}
|
|
7532
|
-
// Access registry through conversation service
|
|
7533
7752
|
get registry() {
|
|
7534
7753
|
return this.conversationService.registry;
|
|
7535
7754
|
}
|
|
7536
|
-
/** Get conversation status - delegate to utils */
|
|
7537
7755
|
getStatus(conversation) {
|
|
7538
|
-
return AXConversationMessageUtilsService.getConversationStatus(conversation);
|
|
7756
|
+
return AXConversationMessageUtilsService.getConversationStatus(conversation, this.conversationService.getPeerPresence(conversation));
|
|
7539
7757
|
}
|
|
7540
|
-
/** Get subtitle text - delegate to utils */
|
|
7541
7758
|
getSubtitle(conversation) {
|
|
7542
|
-
|
|
7759
|
+
this.conversationService.presenceTimeTick();
|
|
7760
|
+
this.conversationService.typingRevision();
|
|
7761
|
+
return AXConversationMessageUtilsService.getConversationSubtitle(conversation, {
|
|
7762
|
+
typingUserIds: this.conversationService.getActiveTypingUserIds(conversation.id),
|
|
7763
|
+
peerPresence: this.conversationService.getPeerPresence(conversation),
|
|
7764
|
+
currentUserId: this.conversationService.currentUser()?.id,
|
|
7765
|
+
});
|
|
7543
7766
|
}
|
|
7544
|
-
/** Info area clicked — emits for host apps to open a custom conversation details UI */
|
|
7545
7767
|
onInfoLeftClick() {
|
|
7546
7768
|
this.infoClick.emit();
|
|
7547
7769
|
}
|
|
7548
|
-
/** Handle inline action click */
|
|
7549
7770
|
async onInlineActionClick(actionId) {
|
|
7550
7771
|
const conversation = this.activeConversation();
|
|
7551
7772
|
if (!conversation)
|
|
@@ -7581,7 +7802,6 @@ class AXConversationInfoBarComponent {
|
|
|
7581
7802
|
this.actionLoading.set(false);
|
|
7582
7803
|
}
|
|
7583
7804
|
}
|
|
7584
|
-
/** Get inputs for dynamic component */
|
|
7585
7805
|
getComponentInputs() {
|
|
7586
7806
|
const activeComp = this.activeComponent();
|
|
7587
7807
|
if (!activeComp)
|
|
@@ -7604,7 +7824,6 @@ class AXConversationInfoBarComponent {
|
|
|
7604
7824
|
return false;
|
|
7605
7825
|
return activeComp.action.fullWidthComponent !== false;
|
|
7606
7826
|
}
|
|
7607
|
-
/** Handle close component */
|
|
7608
7827
|
onCloseComponent() {
|
|
7609
7828
|
this.infoBar.hideComponent();
|
|
7610
7829
|
}
|
|
@@ -7620,7 +7839,6 @@ class AXConversationInfoBarComponent {
|
|
|
7620
7839
|
onCloseBanner() {
|
|
7621
7840
|
this.infoBar.hideMessageBanner();
|
|
7622
7841
|
}
|
|
7623
|
-
/** Handle menu item click */
|
|
7624
7842
|
async onMenuItemClick(item) {
|
|
7625
7843
|
const conversation = this.activeConversation();
|
|
7626
7844
|
if (!conversation)
|
|
@@ -7632,7 +7850,7 @@ class AXConversationInfoBarComponent {
|
|
|
7632
7850
|
this.menuItemAction.emit(item.id);
|
|
7633
7851
|
}
|
|
7634
7852
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationInfoBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7635
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationInfoBarComponent, isStandalone: true, selector: "ax-conversation-info-bar", outputs: { infoClick: "infoClick", searchClick: "searchClick", searchQuery: "searchQuery", menuItemAction: "menuItemAction" }, ngImport: i0, template: "@if (activeConversation(); as conversation) {\n <div class=\"info-bar\">\n <!-- Left: Avatar and Info -->\n <div class=\"info-prefix\" (click)=\"$event.stopPropagation()\">\n <ng-content select=\"ax-prefix\"></ng-content>\n </div>\n <div\n class=\"info-left\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onInfoLeftClick()\"\n (keydown.enter)=\"onInfoLeftClick()\"\n (keydown.space)=\"$event.preventDefault(); onInfoLeftClick()\"\n >\n <div class=\"avatar-wrapper\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"conversation\"\n [size]=\"48\"\n [showStatus]=\"conversation.type === 'private'\"\n />\n </div>\n\n <div class=\"info-details\">\n <p class=\"info-title\">{{ conversation.title }}</p>\n @if (conversation.type !== 'private') {\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n } @else {\n <div class=\"info-subtitle-with-status\">\n @if (getStatus(conversation) === 'online' && !hasCustomUserAvatar()) {\n <span class=\"online-badge\">\u25CF</span>\n }\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Right: Actions or Full-Width Component -->\n @if (!activeComponent() || !isActiveComponentFullWidth()) {\n <div class=\"info-actions\" (click)=\"$event.stopPropagation()\">\n <!-- Inline action buttons from registry -->\n @for (action of inlineActions(); track action.id) {\n @if ((action.component || action.componentLoader) && action.fullWidthComponent === false) {\n <ax-conversation-registry-component-outlet\n [component]=\"action.component\"\n [componentLoader]=\"action.componentLoader\"\n [inputs]=\"getInlineComponentInputs()\"\n />\n } @else {\n <ax-button class=\"action-button\" (onClick)=\"onInlineActionClick(action.id)\" look=\"ghost\">\n <ax-icon [icon]=\"registry.infoBarActions.getActionIcon(action, activeConversation()!)\"></ax-icon>\n </ax-button>\n }\n }\n\n <ax-button look=\"blank\">\n <ax-icon><i class=\"fa-light fa-ellipsis-vertical\"></i></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of menuItems(); track item.id) {\n @if (item.divider) {\n <ax-divider></ax-divider>\n } @else {\n <ax-button-item\n [text]=\"item.label\"\n [disabled]=\"item.disabled\"\n [color]=\"item.destructive ? 'danger' : 'default'\"\n (onClick)=\"onMenuItemClick(item)\"\n >\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n }\n @if (item.shortcut) {\n <ax-suffix>\n <ax-label class=\"shortcut\">{{ item.shortcut }}</ax-label>\n </ax-suffix>\n }\n </ax-button-item>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n @if (activeComponent() && isActiveComponentFullWidth()) {\n <!-- Full-width component mode (e.g., search) - takes entire info-bar -->\n <div\n class=\"info-component-fullwidth\"\n animate.enter=\"slide-in\"\n animate.leave=\"slide-out\"\n (click)=\"$event.stopPropagation()\"\n >\n <ax-conversation-registry-component-outlet\n [component]=\"activeComponent()!.component\"\n [componentLoader]=\"activeComponent()!.componentLoader\"\n [inputs]=\"getComponentInputs()\"\n />\n <ax-button class=\"action-button close-button\" (onClick)=\"onCloseComponent()\" [look]=\"'ghost'\">\n <ax-icon><i class=\"fa-light fa-xmark\"></i></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n\n @if (activeBanner()) {\n <div class=\"ax-conversation-info-banner\" (click)=\"$event.stopPropagation()\">\n <div class=\"ax-conversation-info-banner__content\">\n <ax-conversation-registry-component-outlet\n [component]=\"activeBanner()!.component\"\n [componentLoader]=\"activeBanner()!.componentLoader\"\n [inputs]=\"getBannerInputs()\"\n />\n </div>\n <button\n type=\"button\"\n class=\"ax-conversation-info-banner__close\"\n (click)=\"onCloseBanner()\"\n [attr.aria-label]=\"'Close'\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n}\n", styles: ["@layer properties;@layer components{ax-conversation-info-bar{display:block;max-width:100%;@keyframes axInfoBarPulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes axInfoBarSlideIn{0%{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%))}to{opacity:1;transform:translate(0)}}}ax-conversation-info-bar .info-bar{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 16);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);overflow:hidden;padding:calc(var(--spacing, .25rem) * 2);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-info-bar .ax-conversation-info-banner{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:calc(var(--spacing, .25rem) * 2);padding-inline-start:calc(var(--spacing, .25rem) * 3);padding-inline-end:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .ax-conversation-info-banner__content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .ax-conversation-info-banner__close{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.65);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-info-bar .ax-conversation-info-banner__close:hover{color:rgba(var(--ax-sys-color-on-primary-lightest-surface));background:rgba(var(--ax-sys-color-primary-500),.12)}}ax-conversation-info-bar .ax-conversation-info-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-info-bar .info-bar-empty{justify-content:center;opacity:60%}ax-conversation-info-bar .info-prefix{flex-shrink:0}ax-conversation-info-bar .info-left{margin-inline:calc(var(--spacing, .25rem) * -1.5);margin-block:calc(var(--spacing, .25rem) * -1);display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * 1);transition:background-color .15s ease}ax-conversation-info-bar .info-left:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-500))}ax-conversation-info-bar .avatar-wrapper{flex-shrink:0}ax-conversation-info-bar .info-details{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .info-title{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}ax-conversation-info-bar .info-subtitle-with-status{margin-top:calc(var(--spacing, .25rem) * .5);margin-bottom:calc(var(--spacing, .25rem) * 0);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5)}ax-conversation-info-bar .online-badge{font-size:.625rem;--tw-leading: 1;line-height:1;color:rgba(var(--ax-sys-color-success-500));animation:axInfoBarPulse 2s cubic-bezier(.4,0,.6,1) infinite}ax-conversation-info-bar .info-subtitle{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.85rem;--tw-tracking: .02rem;letter-spacing:.02rem;text-overflow:ellipsis;white-space:nowrap;opacity:70%}ax-conversation-info-bar .info-actions{display:flex;flex-shrink:0;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .info-component-fullwidth{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);inset-block:calc(var(--spacing, .25rem) * 0);z-index:10;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 4)}ax-conversation-info-bar .slide-in{animation:axInfoBarSlideIn var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-info-bar .slide-out{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%));transition:opacity .25s cubic-bezier(.4,0,1,1),transform .25s cubic-bezier(.4,0,1,1)}ax-conversation-info-bar .info-component-fullwidth>*:first-child{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .action-button{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));transition:background .2s}ax-conversation-info-bar .action-button:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-info-bar .search-container{display:flex;width:100%;min-width:calc(var(--spacing, .25rem) * 48);align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .search-input{min-width:calc(var(--spacing, .25rem) * 0);flex:1}[dir=rtl] ax-conversation-info-bar{--ax-info-bar-slide-distance: -100%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-border-style: solid;--tw-outline-style: solid;--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "component", type: AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
7853
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationInfoBarComponent, isStandalone: true, selector: "ax-conversation-info-bar", outputs: { infoClick: "infoClick", searchClick: "searchClick", searchQuery: "searchQuery", menuItemAction: "menuItemAction" }, ngImport: i0, template: "@if (activeConversation(); as conversation) {\n <div class=\"info-bar\">\n <!-- Left: Avatar and Info -->\n <div class=\"info-prefix\" (click)=\"$event.stopPropagation()\">\n <ng-content select=\"ax-prefix\"></ng-content>\n </div>\n <div\n class=\"info-left\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onInfoLeftClick()\"\n (keydown.enter)=\"onInfoLeftClick()\"\n (keydown.space)=\"$event.preventDefault(); onInfoLeftClick()\"\n >\n <div class=\"avatar-wrapper\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"conversation\"\n [size]=\"48\"\n [showStatus]=\"conversation.type === 'private' && !hasCustomUserAvatar()\"\n />\n </div>\n\n <div class=\"info-details\">\n <p class=\"info-title\">{{ conversation.title }}</p>\n @if (conversation.type !== 'private') {\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n } @else {\n <div class=\"info-subtitle-with-status\">\n @if (getStatus(conversation) === 'online' && !hasCustomUserAvatar()) {\n <span class=\"online-badge\">\u25CF</span>\n }\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Right: Actions or Full-Width Component -->\n @if (!activeComponent() || !isActiveComponentFullWidth()) {\n <div class=\"info-actions\" (click)=\"$event.stopPropagation()\">\n <!-- Inline action buttons from registry -->\n @for (action of inlineActions(); track action.id) {\n @if ((action.component || action.componentLoader) && action.fullWidthComponent === false) {\n <ax-conversation-registry-component-outlet\n [component]=\"action.component\"\n [componentLoader]=\"action.componentLoader\"\n [inputs]=\"getInlineComponentInputs()\"\n />\n } @else {\n <ax-button class=\"action-button\" (onClick)=\"onInlineActionClick(action.id)\" look=\"ghost\">\n <ax-icon [icon]=\"registry.infoBarActions.getActionIcon(action, activeConversation()!)\"></ax-icon>\n </ax-button>\n }\n }\n\n <ax-button look=\"blank\">\n <ax-icon><i class=\"fa-light fa-ellipsis-vertical\"></i></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of menuItems(); track item.id) {\n @if (item.divider) {\n <ax-divider></ax-divider>\n } @else {\n <ax-button-item\n [text]=\"item.label\"\n [disabled]=\"item.disabled\"\n [color]=\"item.destructive ? 'danger' : 'default'\"\n (onClick)=\"onMenuItemClick(item)\"\n >\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n }\n @if (item.shortcut) {\n <ax-suffix>\n <ax-label class=\"shortcut\">{{ item.shortcut }}</ax-label>\n </ax-suffix>\n }\n </ax-button-item>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n @if (activeComponent() && isActiveComponentFullWidth()) {\n <!-- Full-width component mode (e.g., search) - takes entire info-bar -->\n <div\n class=\"info-component-fullwidth\"\n animate.enter=\"slide-in\"\n animate.leave=\"slide-out\"\n (click)=\"$event.stopPropagation()\"\n >\n <ax-conversation-registry-component-outlet\n [component]=\"activeComponent()!.component\"\n [componentLoader]=\"activeComponent()!.componentLoader\"\n [inputs]=\"getComponentInputs()\"\n />\n <ax-button class=\"action-button close-button\" (onClick)=\"onCloseComponent()\" [look]=\"'ghost'\">\n <ax-icon><i class=\"fa-light fa-xmark\"></i></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n\n @if (activeBanner()) {\n <div class=\"ax-conversation-info-banner\" (click)=\"$event.stopPropagation()\">\n <div class=\"ax-conversation-info-banner__content\">\n <ax-conversation-registry-component-outlet\n [component]=\"activeBanner()!.component\"\n [componentLoader]=\"activeBanner()!.componentLoader\"\n [inputs]=\"getBannerInputs()\"\n />\n </div>\n <button\n type=\"button\"\n class=\"ax-conversation-info-banner__close\"\n (click)=\"onCloseBanner()\"\n [attr.aria-label]=\"'Close'\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n}\n", styles: ["@layer properties;@layer components{ax-conversation-info-bar{display:block;max-width:100%;@keyframes axInfoBarPulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes axInfoBarSlideIn{0%{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%))}to{opacity:1;transform:translate(0)}}}ax-conversation-info-bar .info-bar{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 16);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);overflow:hidden;padding:calc(var(--spacing, .25rem) * 2);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-info-bar .ax-conversation-info-banner{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:calc(var(--spacing, .25rem) * 2);padding-inline-start:calc(var(--spacing, .25rem) * 3);padding-inline-end:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .ax-conversation-info-banner__content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .ax-conversation-info-banner__close{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.65);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-info-bar .ax-conversation-info-banner__close:hover{color:rgba(var(--ax-sys-color-on-primary-lightest-surface));background:rgba(var(--ax-sys-color-primary-500),.12)}}ax-conversation-info-bar .ax-conversation-info-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-info-bar .info-bar-empty{justify-content:center;opacity:60%}ax-conversation-info-bar .info-prefix{flex-shrink:0}ax-conversation-info-bar .info-left{margin-inline:calc(var(--spacing, .25rem) * -1.5);margin-block:calc(var(--spacing, .25rem) * -1);display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * 1);transition:background-color .15s ease}ax-conversation-info-bar .info-left:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-500))}ax-conversation-info-bar .avatar-wrapper{flex-shrink:0}ax-conversation-info-bar .info-details{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .info-title{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}ax-conversation-info-bar .info-subtitle-with-status{margin-top:calc(var(--spacing, .25rem) * .5);margin-bottom:calc(var(--spacing, .25rem) * 0);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5)}ax-conversation-info-bar .online-badge{font-size:.625rem;--tw-leading: 1;line-height:1;color:rgba(var(--ax-sys-color-success-500));animation:axInfoBarPulse 2s cubic-bezier(.4,0,.6,1) infinite}ax-conversation-info-bar .info-subtitle{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.85rem;--tw-tracking: .02rem;letter-spacing:.02rem;text-overflow:ellipsis;white-space:nowrap;opacity:70%}ax-conversation-info-bar .info-actions{display:flex;flex-shrink:0;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .info-component-fullwidth{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);inset-block:calc(var(--spacing, .25rem) * 0);z-index:10;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 4)}ax-conversation-info-bar .slide-in{animation:axInfoBarSlideIn var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-info-bar .slide-out{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%));transition:opacity .25s cubic-bezier(.4,0,1,1),transform .25s cubic-bezier(.4,0,1,1)}ax-conversation-info-bar .info-component-fullwidth>*:first-child{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .action-button{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));transition:background .2s}ax-conversation-info-bar .action-button:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-info-bar .search-container{display:flex;width:100%;min-width:calc(var(--spacing, .25rem) * 48);align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .search-input{min-width:calc(var(--spacing, .25rem) * 0);flex:1}[dir=rtl] ax-conversation-info-bar{--ax-info-bar-slide-distance: -100%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-border-style: solid;--tw-outline-style: solid;--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "component", type: AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
7636
7854
|
}
|
|
7637
7855
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationInfoBarComponent, decorators: [{
|
|
7638
7856
|
type: Component,
|
|
@@ -7646,7 +7864,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
7646
7864
|
AXLabelComponent,
|
|
7647
7865
|
AXConversationAvatarComponent,
|
|
7648
7866
|
AXConversationRegistryComponentOutletComponent,
|
|
7649
|
-
], template: "@if (activeConversation(); as conversation) {\n <div class=\"info-bar\">\n <!-- Left: Avatar and Info -->\n <div class=\"info-prefix\" (click)=\"$event.stopPropagation()\">\n <ng-content select=\"ax-prefix\"></ng-content>\n </div>\n <div\n class=\"info-left\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onInfoLeftClick()\"\n (keydown.enter)=\"onInfoLeftClick()\"\n (keydown.space)=\"$event.preventDefault(); onInfoLeftClick()\"\n >\n <div class=\"avatar-wrapper\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"conversation\"\n [size]=\"48\"\n [showStatus]=\"conversation.type === 'private'\"\n />\n </div>\n\n <div class=\"info-details\">\n <p class=\"info-title\">{{ conversation.title }}</p>\n @if (conversation.type !== 'private') {\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n } @else {\n <div class=\"info-subtitle-with-status\">\n @if (getStatus(conversation) === 'online' && !hasCustomUserAvatar()) {\n <span class=\"online-badge\">\u25CF</span>\n }\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Right: Actions or Full-Width Component -->\n @if (!activeComponent() || !isActiveComponentFullWidth()) {\n <div class=\"info-actions\" (click)=\"$event.stopPropagation()\">\n <!-- Inline action buttons from registry -->\n @for (action of inlineActions(); track action.id) {\n @if ((action.component || action.componentLoader) && action.fullWidthComponent === false) {\n <ax-conversation-registry-component-outlet\n [component]=\"action.component\"\n [componentLoader]=\"action.componentLoader\"\n [inputs]=\"getInlineComponentInputs()\"\n />\n } @else {\n <ax-button class=\"action-button\" (onClick)=\"onInlineActionClick(action.id)\" look=\"ghost\">\n <ax-icon [icon]=\"registry.infoBarActions.getActionIcon(action, activeConversation()!)\"></ax-icon>\n </ax-button>\n }\n }\n\n <ax-button look=\"blank\">\n <ax-icon><i class=\"fa-light fa-ellipsis-vertical\"></i></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of menuItems(); track item.id) {\n @if (item.divider) {\n <ax-divider></ax-divider>\n } @else {\n <ax-button-item\n [text]=\"item.label\"\n [disabled]=\"item.disabled\"\n [color]=\"item.destructive ? 'danger' : 'default'\"\n (onClick)=\"onMenuItemClick(item)\"\n >\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n }\n @if (item.shortcut) {\n <ax-suffix>\n <ax-label class=\"shortcut\">{{ item.shortcut }}</ax-label>\n </ax-suffix>\n }\n </ax-button-item>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n @if (activeComponent() && isActiveComponentFullWidth()) {\n <!-- Full-width component mode (e.g., search) - takes entire info-bar -->\n <div\n class=\"info-component-fullwidth\"\n animate.enter=\"slide-in\"\n animate.leave=\"slide-out\"\n (click)=\"$event.stopPropagation()\"\n >\n <ax-conversation-registry-component-outlet\n [component]=\"activeComponent()!.component\"\n [componentLoader]=\"activeComponent()!.componentLoader\"\n [inputs]=\"getComponentInputs()\"\n />\n <ax-button class=\"action-button close-button\" (onClick)=\"onCloseComponent()\" [look]=\"'ghost'\">\n <ax-icon><i class=\"fa-light fa-xmark\"></i></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n\n @if (activeBanner()) {\n <div class=\"ax-conversation-info-banner\" (click)=\"$event.stopPropagation()\">\n <div class=\"ax-conversation-info-banner__content\">\n <ax-conversation-registry-component-outlet\n [component]=\"activeBanner()!.component\"\n [componentLoader]=\"activeBanner()!.componentLoader\"\n [inputs]=\"getBannerInputs()\"\n />\n </div>\n <button\n type=\"button\"\n class=\"ax-conversation-info-banner__close\"\n (click)=\"onCloseBanner()\"\n [attr.aria-label]=\"'Close'\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n}\n", styles: ["@layer properties;@layer components{ax-conversation-info-bar{display:block;max-width:100%;@keyframes axInfoBarPulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes axInfoBarSlideIn{0%{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%))}to{opacity:1;transform:translate(0)}}}ax-conversation-info-bar .info-bar{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 16);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);overflow:hidden;padding:calc(var(--spacing, .25rem) * 2);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-info-bar .ax-conversation-info-banner{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:calc(var(--spacing, .25rem) * 2);padding-inline-start:calc(var(--spacing, .25rem) * 3);padding-inline-end:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .ax-conversation-info-banner__content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .ax-conversation-info-banner__close{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.65);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-info-bar .ax-conversation-info-banner__close:hover{color:rgba(var(--ax-sys-color-on-primary-lightest-surface));background:rgba(var(--ax-sys-color-primary-500),.12)}}ax-conversation-info-bar .ax-conversation-info-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-info-bar .info-bar-empty{justify-content:center;opacity:60%}ax-conversation-info-bar .info-prefix{flex-shrink:0}ax-conversation-info-bar .info-left{margin-inline:calc(var(--spacing, .25rem) * -1.5);margin-block:calc(var(--spacing, .25rem) * -1);display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * 1);transition:background-color .15s ease}ax-conversation-info-bar .info-left:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-500))}ax-conversation-info-bar .avatar-wrapper{flex-shrink:0}ax-conversation-info-bar .info-details{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .info-title{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}ax-conversation-info-bar .info-subtitle-with-status{margin-top:calc(var(--spacing, .25rem) * .5);margin-bottom:calc(var(--spacing, .25rem) * 0);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5)}ax-conversation-info-bar .online-badge{font-size:.625rem;--tw-leading: 1;line-height:1;color:rgba(var(--ax-sys-color-success-500));animation:axInfoBarPulse 2s cubic-bezier(.4,0,.6,1) infinite}ax-conversation-info-bar .info-subtitle{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.85rem;--tw-tracking: .02rem;letter-spacing:.02rem;text-overflow:ellipsis;white-space:nowrap;opacity:70%}ax-conversation-info-bar .info-actions{display:flex;flex-shrink:0;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .info-component-fullwidth{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);inset-block:calc(var(--spacing, .25rem) * 0);z-index:10;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 4)}ax-conversation-info-bar .slide-in{animation:axInfoBarSlideIn var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-info-bar .slide-out{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%));transition:opacity .25s cubic-bezier(.4,0,1,1),transform .25s cubic-bezier(.4,0,1,1)}ax-conversation-info-bar .info-component-fullwidth>*:first-child{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .action-button{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));transition:background .2s}ax-conversation-info-bar .action-button:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-info-bar .search-container{display:flex;width:100%;min-width:calc(var(--spacing, .25rem) * 48);align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .search-input{min-width:calc(var(--spacing, .25rem) * 0);flex:1}[dir=rtl] ax-conversation-info-bar{--ax-info-bar-slide-distance: -100%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-border-style: solid;--tw-outline-style: solid;--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
7867
|
+
], template: "@if (activeConversation(); as conversation) {\n <div class=\"info-bar\">\n <!-- Left: Avatar and Info -->\n <div class=\"info-prefix\" (click)=\"$event.stopPropagation()\">\n <ng-content select=\"ax-prefix\"></ng-content>\n </div>\n <div\n class=\"info-left\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onInfoLeftClick()\"\n (keydown.enter)=\"onInfoLeftClick()\"\n (keydown.space)=\"$event.preventDefault(); onInfoLeftClick()\"\n >\n <div class=\"avatar-wrapper\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"conversation\"\n [size]=\"48\"\n [showStatus]=\"conversation.type === 'private' && !hasCustomUserAvatar()\"\n />\n </div>\n\n <div class=\"info-details\">\n <p class=\"info-title\">{{ conversation.title }}</p>\n @if (conversation.type !== 'private') {\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n } @else {\n <div class=\"info-subtitle-with-status\">\n @if (getStatus(conversation) === 'online' && !hasCustomUserAvatar()) {\n <span class=\"online-badge\">\u25CF</span>\n }\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Right: Actions or Full-Width Component -->\n @if (!activeComponent() || !isActiveComponentFullWidth()) {\n <div class=\"info-actions\" (click)=\"$event.stopPropagation()\">\n <!-- Inline action buttons from registry -->\n @for (action of inlineActions(); track action.id) {\n @if ((action.component || action.componentLoader) && action.fullWidthComponent === false) {\n <ax-conversation-registry-component-outlet\n [component]=\"action.component\"\n [componentLoader]=\"action.componentLoader\"\n [inputs]=\"getInlineComponentInputs()\"\n />\n } @else {\n <ax-button class=\"action-button\" (onClick)=\"onInlineActionClick(action.id)\" look=\"ghost\">\n <ax-icon [icon]=\"registry.infoBarActions.getActionIcon(action, activeConversation()!)\"></ax-icon>\n </ax-button>\n }\n }\n\n <ax-button look=\"blank\">\n <ax-icon><i class=\"fa-light fa-ellipsis-vertical\"></i></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of menuItems(); track item.id) {\n @if (item.divider) {\n <ax-divider></ax-divider>\n } @else {\n <ax-button-item\n [text]=\"item.label\"\n [disabled]=\"item.disabled\"\n [color]=\"item.destructive ? 'danger' : 'default'\"\n (onClick)=\"onMenuItemClick(item)\"\n >\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n }\n @if (item.shortcut) {\n <ax-suffix>\n <ax-label class=\"shortcut\">{{ item.shortcut }}</ax-label>\n </ax-suffix>\n }\n </ax-button-item>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n @if (activeComponent() && isActiveComponentFullWidth()) {\n <!-- Full-width component mode (e.g., search) - takes entire info-bar -->\n <div\n class=\"info-component-fullwidth\"\n animate.enter=\"slide-in\"\n animate.leave=\"slide-out\"\n (click)=\"$event.stopPropagation()\"\n >\n <ax-conversation-registry-component-outlet\n [component]=\"activeComponent()!.component\"\n [componentLoader]=\"activeComponent()!.componentLoader\"\n [inputs]=\"getComponentInputs()\"\n />\n <ax-button class=\"action-button close-button\" (onClick)=\"onCloseComponent()\" [look]=\"'ghost'\">\n <ax-icon><i class=\"fa-light fa-xmark\"></i></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n\n @if (activeBanner()) {\n <div class=\"ax-conversation-info-banner\" (click)=\"$event.stopPropagation()\">\n <div class=\"ax-conversation-info-banner__content\">\n <ax-conversation-registry-component-outlet\n [component]=\"activeBanner()!.component\"\n [componentLoader]=\"activeBanner()!.componentLoader\"\n [inputs]=\"getBannerInputs()\"\n />\n </div>\n <button\n type=\"button\"\n class=\"ax-conversation-info-banner__close\"\n (click)=\"onCloseBanner()\"\n [attr.aria-label]=\"'Close'\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n}\n", styles: ["@layer properties;@layer components{ax-conversation-info-bar{display:block;max-width:100%;@keyframes axInfoBarPulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes axInfoBarSlideIn{0%{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%))}to{opacity:1;transform:translate(0)}}}ax-conversation-info-bar .info-bar{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 16);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);overflow:hidden;padding:calc(var(--spacing, .25rem) * 2);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-info-bar .ax-conversation-info-banner{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:calc(var(--spacing, .25rem) * 2);padding-inline-start:calc(var(--spacing, .25rem) * 3);padding-inline-end:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .ax-conversation-info-banner__content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .ax-conversation-info-banner__close{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.65);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-info-bar .ax-conversation-info-banner__close:hover{color:rgba(var(--ax-sys-color-on-primary-lightest-surface));background:rgba(var(--ax-sys-color-primary-500),.12)}}ax-conversation-info-bar .ax-conversation-info-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-info-bar .info-bar-empty{justify-content:center;opacity:60%}ax-conversation-info-bar .info-prefix{flex-shrink:0}ax-conversation-info-bar .info-left{margin-inline:calc(var(--spacing, .25rem) * -1.5);margin-block:calc(var(--spacing, .25rem) * -1);display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * 1);transition:background-color .15s ease}ax-conversation-info-bar .info-left:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-500))}ax-conversation-info-bar .avatar-wrapper{flex-shrink:0}ax-conversation-info-bar .info-details{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .info-title{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}ax-conversation-info-bar .info-subtitle-with-status{margin-top:calc(var(--spacing, .25rem) * .5);margin-bottom:calc(var(--spacing, .25rem) * 0);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5)}ax-conversation-info-bar .online-badge{font-size:.625rem;--tw-leading: 1;line-height:1;color:rgba(var(--ax-sys-color-success-500));animation:axInfoBarPulse 2s cubic-bezier(.4,0,.6,1) infinite}ax-conversation-info-bar .info-subtitle{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.85rem;--tw-tracking: .02rem;letter-spacing:.02rem;text-overflow:ellipsis;white-space:nowrap;opacity:70%}ax-conversation-info-bar .info-actions{display:flex;flex-shrink:0;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .info-component-fullwidth{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);inset-block:calc(var(--spacing, .25rem) * 0);z-index:10;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 4)}ax-conversation-info-bar .slide-in{animation:axInfoBarSlideIn var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-info-bar .slide-out{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%));transition:opacity .25s cubic-bezier(.4,0,1,1),transform .25s cubic-bezier(.4,0,1,1)}ax-conversation-info-bar .info-component-fullwidth>*:first-child{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .action-button{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));transition:background .2s}ax-conversation-info-bar .action-button:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-info-bar .search-container{display:flex;width:100%;min-width:calc(var(--spacing, .25rem) * 48);align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .search-input{min-width:calc(var(--spacing, .25rem) * 0);flex:1}[dir=rtl] ax-conversation-info-bar{--ax-info-bar-slide-distance: -100%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-border-style: solid;--tw-outline-style: solid;--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
7650
7868
|
}], ctorParameters: () => [], propDecorators: { infoClick: [{ type: i0.Output, args: ["infoClick"] }], searchClick: [{ type: i0.Output, args: ["searchClick"] }], searchQuery: [{ type: i0.Output, args: ["searchQuery"] }], menuItemAction: [{ type: i0.Output, args: ["menuItemAction"] }] } });
|
|
7651
7869
|
|
|
7652
7870
|
class AXConversationForwardMessageDialogComponent {
|
|
@@ -7681,7 +7899,9 @@ class AXConversationForwardMessageDialogComponent {
|
|
|
7681
7899
|
},
|
|
7682
7900
|
byKey: (key) => Promise.resolve(this.allConversations().find((c) => c.id === key) ?? null),
|
|
7683
7901
|
});
|
|
7684
|
-
this.
|
|
7902
|
+
this.isForwarding = computed(() => this.conversationService?.isForwardingMessage() ?? false, /* @ts-ignore */
|
|
7903
|
+
...(ngDevMode ? [{ debugName: "isForwarding" }] : /* istanbul ignore next */ []));
|
|
7904
|
+
this.canForward = computed(() => this.selectedConversationIds().length > 0 && !this.isForwarding(), /* @ts-ignore */
|
|
7685
7905
|
...(ngDevMode ? [{ debugName: "canForward" }] : /* istanbul ignore next */ []));
|
|
7686
7906
|
this._syncPopupTitleEffect = effect(() => {
|
|
7687
7907
|
const popupRef = this.__popup__();
|
|
@@ -7728,38 +7948,40 @@ class AXConversationForwardMessageDialogComponent {
|
|
|
7728
7948
|
if (!this.conversationService || !this.message)
|
|
7729
7949
|
return;
|
|
7730
7950
|
const selectedIds = this.selectedConversationIds();
|
|
7731
|
-
if (selectedIds.length === 0)
|
|
7951
|
+
if (selectedIds.length === 0 || this.isForwarding())
|
|
7732
7952
|
return;
|
|
7733
7953
|
try {
|
|
7734
|
-
|
|
7735
|
-
.
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
const
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7954
|
+
await this.conversationService.runWithForwardingLock(async () => {
|
|
7955
|
+
const originalConversation = this.conversationService
|
|
7956
|
+
.conversations()
|
|
7957
|
+
.find((c) => c.id === this.message.conversationId);
|
|
7958
|
+
const sender = originalConversation?.participants.find((p) => p.id === this.message.senderId);
|
|
7959
|
+
const forwardPromises = selectedIds.map(async (conversationId) => {
|
|
7960
|
+
const forwardCommand = {
|
|
7961
|
+
conversationId,
|
|
7962
|
+
type: this.message.type,
|
|
7963
|
+
payload: this.message.payload,
|
|
7964
|
+
forwarded: true,
|
|
7965
|
+
forwardedFrom: {
|
|
7966
|
+
messageId: this.message.id,
|
|
7967
|
+
senderId: this.message.senderId,
|
|
7968
|
+
senderName: sender?.name || this.translation.translateSync('@acorex:chat.fallbacks.unknown-user'),
|
|
7969
|
+
conversationId: this.message.conversationId,
|
|
7970
|
+
conversationTitle: originalConversation?.title,
|
|
7971
|
+
},
|
|
7972
|
+
originalSenderId: this.message.senderId,
|
|
7973
|
+
metadata: this.message.metadata,
|
|
7974
|
+
};
|
|
7975
|
+
return this.conversationService.sendMessage(forwardCommand);
|
|
7976
|
+
});
|
|
7977
|
+
await Promise.all(forwardPromises);
|
|
7978
|
+
const count = selectedIds.length;
|
|
7979
|
+
this.toastService.success(this.translation.translateSync('@acorex:chat.notifications.message-forwarded', { params: { count } }));
|
|
7980
|
+
const event = new AXComponentCloseEvent();
|
|
7981
|
+
event.component = this;
|
|
7982
|
+
event.data = { success: true, count };
|
|
7983
|
+
this.onClosed.emit(event);
|
|
7755
7984
|
});
|
|
7756
|
-
await Promise.all(forwardPromises);
|
|
7757
|
-
const count = selectedIds.length;
|
|
7758
|
-
this.toastService.success(this.translation.translateSync('@acorex:chat.notifications.message-forwarded', { params: { count } }));
|
|
7759
|
-
const event = new AXComponentCloseEvent();
|
|
7760
|
-
event.component = this;
|
|
7761
|
-
event.data = { success: true, count };
|
|
7762
|
-
this.onClosed.emit(event);
|
|
7763
7985
|
}
|
|
7764
7986
|
catch (error) {
|
|
7765
7987
|
console.error('Failed to forward message:', error);
|
|
@@ -7773,7 +7995,7 @@ class AXConversationForwardMessageDialogComponent {
|
|
|
7773
7995
|
}
|
|
7774
7996
|
}
|
|
7775
7997
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationForwardMessageDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7776
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationForwardMessageDialogComponent, isStandalone: true, selector: "ax-conversation-forward-message-dialog", inputs: { __popup__: { classPropertyName: "__popup__", publicName: "__popup__", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: AXClosableComponent, useExisting: AXConversationForwardMessageDialogComponent }], viewQueries: [{ propertyName: "forwardListEmptyTpl", first: true, predicate: ["forwardListEmpty"], descendants: true, isSignal: true }, { propertyName: "forwardList", first: true, predicate: ["forwardList"], descendants: true, isSignal: true }], ngImport: i0, template: "
|
|
7998
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationForwardMessageDialogComponent, isStandalone: true, selector: "ax-conversation-forward-message-dialog", inputs: { __popup__: { classPropertyName: "__popup__", publicName: "__popup__", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: AXClosableComponent, useExisting: AXConversationForwardMessageDialogComponent }], viewQueries: [{ propertyName: "forwardListEmptyTpl", first: true, predicate: ["forwardListEmpty"], descendants: true, isSignal: true }, { propertyName: "forwardList", first: true, predicate: ["forwardList"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"forward-message-dialog\">\n <ng-template #forwardListEmpty>\n <div class=\"forward-list-empty\">\n @if (forwardSearchQuery()) {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-search' | translate | async }}\n } @else {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-available' | translate | async }}\n }\n </div>\n </ng-template>\n\n <div class=\"dialog-content\">\n <div class=\"forward-list-wrap\">\n <ax-list\n #forwardList\n class=\"forward-list\"\n [dataSource]=\"forwardListDataSource\"\n [multiple]=\"true\"\n [valueField]=\"'id'\"\n [textField]=\"'title'\"\n [checkbox]=\"false\"\n [itemHeight]=\"52\"\n [ngModel]=\"selectedConversationIds()\"\n (ngModelChange)=\"selectedConversationIds.set($event ?? [])\"\n [emptyTemplate]=\"forwardListEmptyTpl()\"\n [itemTemplate]=\"forwardItemTpl\"\n >\n <ax-header class=\"forward-list-header\">\n <div class=\"forward-list-header-inner\">\n <ax-search-box\n [value]=\"forwardSearchQuery()\"\n (valueChange)=\"onForwardSearchChange($event)\"\n [placeholder]=\"'@acorex:chat.placeholders.search-conversations' | translate | async\"\n ></ax-search-box>\n </div>\n </ax-header>\n </ax-list>\n </div>\n </div>\n\n <ng-template #forwardItemTpl let-item>\n @if (conversationFromItem(item); as conversation) {\n <div class=\"forward-item-content\">\n <input class=\"ax-checkbox\" type=\"checkbox\" [checked]=\"isSelected(conversation.id)\" tabindex=\"0\" />\n <ax-conversation-avatar kind=\"auto\" [conversation]=\"conversation\" [size]=\"36\" />\n <span class=\"forward-title-text ax-truncated\">{{ conversation.title }}</span>\n </div>\n }\n </ng-template>\n\n <ax-footer class=\"dialog-footer\">\n <ax-suffix>\n <ax-button\n [text]=\"'@acorex:chat.actions.cancel' | translate | async\"\n [look]=\"'solid'\"\n [disabled]=\"isForwarding()\"\n (onClick)=\"onCancel()\"\n >\n </ax-button>\n <ax-button\n [text]=\"'@acorex:chat.actions.forward' | translate | async\"\n [look]=\"'solid'\"\n [color]=\"'primary'\"\n [disabled]=\"!canForward()\"\n (onClick)=\"onForward()\"\n >\n @if (isForwarding()) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n </ax-suffix>\n </ax-footer>\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-forward-message-dialog{display:block}ax-conversation-forward-message-dialog .forward-message-dialog{display:flex;width:100%;flex-direction:column;overflow:hidden}ax-conversation-forward-message-dialog .dialog-content{min-height:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden}ax-conversation-forward-message-dialog .forward-list-wrap{overflow:hidden;height:min(50vh,24rem)}ax-conversation-forward-message-dialog .forward-list{display:block;height:100%}ax-conversation-forward-message-dialog .forward-list-header{position:sticky;top:calc(var(--spacing, .25rem) * 0);z-index:10;display:block;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface))}ax-conversation-forward-message-dialog .forward-list-header-inner{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-forward-message-dialog .forward-item-content{display:flex;height:100%;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding:calc(var(--spacing, .25rem) * 2);transition:background-color .2s ease}ax-conversation-forward-message-dialog .forward-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: calc(var(--spacing, .25rem) * 5);line-height:calc(var(--spacing, .25rem) * 5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-forward-message-dialog .forward-list-empty{padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 5);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-forward-message-dialog .dialog-footer{flex-shrink:0}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXListComponent, selector: "ax-list", inputs: ["id", "name", "disabled", "readonly", "valueField", "textField", "textTemplate", "disabledField", "multiple", "selectionMode", "isItemTruncated", "showItemTooltip", "dataSource", "itemHeight", "itemTemplate", "emptyTemplate", "loadingTemplate", "checkbox"], outputs: ["onValueChanged", "disabledChange", "readonlyChange", "onBlur", "onFocus", "onItemClick", "onItemSelected", "onScrolledIndexChanged"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
7777
7999
|
}
|
|
7778
8000
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationForwardMessageDialogComponent, decorators: [{
|
|
7779
8001
|
type: Component,
|
|
@@ -7785,8 +8007,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
7785
8007
|
AXButtonComponent,
|
|
7786
8008
|
AXDecoratorGenericComponent,
|
|
7787
8009
|
AXConversationAvatarComponent,
|
|
8010
|
+
AXLoadingComponent,
|
|
7788
8011
|
AXTranslationModule,
|
|
7789
|
-
], providers: [{ provide: AXClosableComponent, useExisting: AXConversationForwardMessageDialogComponent }], template: "
|
|
8012
|
+
], providers: [{ provide: AXClosableComponent, useExisting: AXConversationForwardMessageDialogComponent }], template: "<div class=\"forward-message-dialog\">\n <ng-template #forwardListEmpty>\n <div class=\"forward-list-empty\">\n @if (forwardSearchQuery()) {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-search' | translate | async }}\n } @else {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-available' | translate | async }}\n }\n </div>\n </ng-template>\n\n <div class=\"dialog-content\">\n <div class=\"forward-list-wrap\">\n <ax-list\n #forwardList\n class=\"forward-list\"\n [dataSource]=\"forwardListDataSource\"\n [multiple]=\"true\"\n [valueField]=\"'id'\"\n [textField]=\"'title'\"\n [checkbox]=\"false\"\n [itemHeight]=\"52\"\n [ngModel]=\"selectedConversationIds()\"\n (ngModelChange)=\"selectedConversationIds.set($event ?? [])\"\n [emptyTemplate]=\"forwardListEmptyTpl()\"\n [itemTemplate]=\"forwardItemTpl\"\n >\n <ax-header class=\"forward-list-header\">\n <div class=\"forward-list-header-inner\">\n <ax-search-box\n [value]=\"forwardSearchQuery()\"\n (valueChange)=\"onForwardSearchChange($event)\"\n [placeholder]=\"'@acorex:chat.placeholders.search-conversations' | translate | async\"\n ></ax-search-box>\n </div>\n </ax-header>\n </ax-list>\n </div>\n </div>\n\n <ng-template #forwardItemTpl let-item>\n @if (conversationFromItem(item); as conversation) {\n <div class=\"forward-item-content\">\n <input class=\"ax-checkbox\" type=\"checkbox\" [checked]=\"isSelected(conversation.id)\" tabindex=\"0\" />\n <ax-conversation-avatar kind=\"auto\" [conversation]=\"conversation\" [size]=\"36\" />\n <span class=\"forward-title-text ax-truncated\">{{ conversation.title }}</span>\n </div>\n }\n </ng-template>\n\n <ax-footer class=\"dialog-footer\">\n <ax-suffix>\n <ax-button\n [text]=\"'@acorex:chat.actions.cancel' | translate | async\"\n [look]=\"'solid'\"\n [disabled]=\"isForwarding()\"\n (onClick)=\"onCancel()\"\n >\n </ax-button>\n <ax-button\n [text]=\"'@acorex:chat.actions.forward' | translate | async\"\n [look]=\"'solid'\"\n [color]=\"'primary'\"\n [disabled]=\"!canForward()\"\n (onClick)=\"onForward()\"\n >\n @if (isForwarding()) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n </ax-suffix>\n </ax-footer>\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-forward-message-dialog{display:block}ax-conversation-forward-message-dialog .forward-message-dialog{display:flex;width:100%;flex-direction:column;overflow:hidden}ax-conversation-forward-message-dialog .dialog-content{min-height:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden}ax-conversation-forward-message-dialog .forward-list-wrap{overflow:hidden;height:min(50vh,24rem)}ax-conversation-forward-message-dialog .forward-list{display:block;height:100%}ax-conversation-forward-message-dialog .forward-list-header{position:sticky;top:calc(var(--spacing, .25rem) * 0);z-index:10;display:block;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface))}ax-conversation-forward-message-dialog .forward-list-header-inner{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-forward-message-dialog .forward-item-content{display:flex;height:100%;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding:calc(var(--spacing, .25rem) * 2);transition:background-color .2s ease}ax-conversation-forward-message-dialog .forward-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: calc(var(--spacing, .25rem) * 5);line-height:calc(var(--spacing, .25rem) * 5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-forward-message-dialog .forward-list-empty{padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 5);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-forward-message-dialog .dialog-footer{flex-shrink:0}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
7790
8013
|
}], propDecorators: { __popup__: [{ type: i0.Input, args: [{ isSignal: true, alias: "__popup__", required: false }] }], forwardListEmptyTpl: [{ type: i0.ViewChild, args: ['forwardListEmpty', { isSignal: true }] }], forwardList: [{ type: i0.ViewChild, args: ['forwardList', { isSignal: true }] }] } });
|
|
7791
8014
|
|
|
7792
8015
|
var forwardMessageDialog_component = /*#__PURE__*/Object.freeze({
|
|
@@ -8365,13 +8588,14 @@ class AXConversationMessageListComponent {
|
|
|
8365
8588
|
return renderer?.component;
|
|
8366
8589
|
}
|
|
8367
8590
|
/** Resolve lazy renderer loader for message */
|
|
8591
|
+
static { this.fallbackRendererLoader = () => Promise.resolve().then(function () { return fallbackRenderer_component; }).then((m) => m.AXConversationFallbackRendererComponent); }
|
|
8368
8592
|
getRendererComponentLoader(message) {
|
|
8369
8593
|
const renderer = this.registry.messageRenderers.getRenderer(message);
|
|
8370
8594
|
if (renderer?.componentLoader) {
|
|
8371
8595
|
return renderer.componentLoader;
|
|
8372
8596
|
}
|
|
8373
8597
|
if (!renderer || !renderer.component) {
|
|
8374
|
-
return
|
|
8598
|
+
return AXConversationMessageListComponent.fallbackRendererLoader;
|
|
8375
8599
|
}
|
|
8376
8600
|
return undefined;
|
|
8377
8601
|
}
|
|
@@ -8758,11 +8982,10 @@ class AXConversationMessageListComponent {
|
|
|
8758
8982
|
}
|
|
8759
8983
|
/**
|
|
8760
8984
|
* TrackBy function for message groups.
|
|
8761
|
-
*
|
|
8985
|
+
* Track by date only — new messages in the same day are handled by the inner message @for.
|
|
8762
8986
|
*/
|
|
8763
8987
|
trackMessageGroup(index, group) {
|
|
8764
|
-
|
|
8765
|
-
return `${group.date}:${lastId}`;
|
|
8988
|
+
return group.date;
|
|
8766
8989
|
}
|
|
8767
8990
|
/**
|
|
8768
8991
|
* TrackBy function for messages
|
|
@@ -8772,7 +8995,7 @@ class AXConversationMessageListComponent {
|
|
|
8772
8995
|
return message.id;
|
|
8773
8996
|
}
|
|
8774
8997
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationMessageListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8775
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationMessageListComponent, isStandalone: true, selector: "ax-conversation-message-list", outputs: { messageAction: "messageAction" }, viewQueries: [{ propertyName: "reactionPopover", first: true, predicate: ["reactionPopover"], descendants: true, isSignal: true }, { propertyName: "messageListRef", first: true, predicate: ["messageList"], descendants: true, isSignal: true }, { propertyName: "messagesContainerRef", first: true, predicate: ["messagesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (activeConversation(); as conv) {\n @for (cid of [conv.id]; track cid) {\n <div\n class=\"message-list message-list--conversation-surface\"\n [class.message-list--drag]=\"messageListDragging()\"\n #messageList\n role=\"log\"\n [attr.aria-label]=\"'@acorex:chat.aria.message-list' | translate | async\"\n aria-live=\"polite\"\n [style.background]=\"messageListBackgroundStyle()\"\n axUploaderZone\n [disableBrowse]=\"true\"\n (dragEnter)=\"onMessageListDragEnter()\"\n (dragLeave)=\"onMessageListDragLeave()\"\n (fileChange)=\"onMessageListFilesDropped($event)\"\n >\n @if (loading()) {\n <div\n class=\"list-loading\"\n role=\"status\"\n aria-busy=\"true\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-messages' | translate | async\"\n >\n <div class=\"messages-skeleton\" aria-hidden=\"true\">\n @for (item of loadingSkeletonItems; track item) {\n <div class=\"message-skeleton\" [class.message-skeleton--own]=\"$odd\">\n @if ($even && isGroupConversation()) {\n <ax-skeleton class=\"message-skeleton-avatar\" [animated]=\"true\"></ax-skeleton>\n }\n <ax-skeleton\n class=\"message-skeleton-bubble\"\n [class.message-skeleton-bubble--short]=\"$index % 3 === 1\"\n [class.message-skeleton-bubble--medium]=\"$index % 3 === 2\"\n [animated]=\"true\"\n ></ax-skeleton>\n </div>\n }\n </div>\n </div>\n } @else if (messages().length === 0) {\n <div class=\"list-empty\" role=\"status\" [attr.aria-label]=\"'@acorex:chat.status.no-messages' | translate | async\">\n <ng-content select=\"ax-conversation-message-list-empty, [ax-conversation-message-list-empty]\">\n <ng-container\n *ngComponentOutlet=\"resolvedEmptyStateComponent(); inputs: { conversation: activeConversation()! }\"\n ></ng-container>\n </ng-content>\n </div>\n } @else {\n <div\n class=\"messages-container\"\n (scroll)=\"onScroll($event)\"\n axInfiniteScroll\n [threshold]=\"config.infiniteScrollThreshold\"\n [edge]=\"'top'\"\n [scrollDisabled]=\"loading() || loadingMore() || !hasMoreMessages()\"\n (scrollThreshold)=\"onScrollThreshold($event)\"\n #messagesContainer\n role=\"feed\"\n [attr.aria-label]=\"'@acorex:chat.aria.messages' | translate | async\"\n >\n @if (loadingMore()) {\n <div\n class=\"list-loading-more list-loading-more--prepend\"\n role=\"status\"\n animate.enter=\"load-more-enter\"\n animate.leave=\"load-more-leave\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-older-messages' | translate | async\"\n >\n <div class=\"load-more-indicator\" aria-hidden=\"true\">\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n </div>\n <ax-label class=\"load-more-label\">{{\n '@acorex:chat.status.loading-older-messages' | translate | async\n }}</ax-label>\n </div>\n }\n @for (group of messageGroups(); track trackMessageGroup($index, group)) {\n <!-- Date Separator -->\n <div class=\"date-separator\" role=\"separator\" [attr.aria-label]=\"getDateSeparatorAriaLabel(group.dateLabel)\">\n <span class=\"date-separator__label\">{{ group.dateLabel }}</span>\n </div>\n\n <!-- Messages in this date group -->\n @for (message of group.messages; track trackMessage($index, message)) {\n <div\n [class]=\"getMessageClasses(message)\"\n role=\"article\"\n [attr.aria-label]=\"getMessageAriaLabel(message)\"\n [id]=\"'message-' + message.id\"\n >\n <!-- Avatar (only for group conversations and received messages) -->\n @if (shouldShowAvatar(message)) {\n <div class=\"message-avatar\">\n <ax-conversation-avatar\n kind=\"user\"\n [userId]=\"message.senderId\"\n [conversation]=\"activeConversation()\"\n [message]=\"message\"\n [size]=\"32\"\n />\n </div>\n }\n\n <div class=\"message-content-row\" [class.message-content-row-own]=\"isOwnMessage(message)\">\n @if (messageSupportsReactions(message)) {\n <button\n type=\"button\"\n class=\"add-reaction-button add-reaction-outside\"\n [class.add-reaction-visible]=\"reactionPickerTarget() === message.id\"\n (click)=\"toggleReactionPicker(message, $event)\"\n [attr.aria-label]=\"'@acorex:chat.actions.add-reaction' | translate | async\"\n #reactionButton\n >\n <i class=\"fa-light fa-face-smile\"></i>\n </button>\n }\n\n <div\n class=\"message-bubble-container\"\n [id]=\"'message-bubble-' + message.id\"\n [attr.data-message-id]=\"message.id\"\n >\n <div\n [class]=\"getBubbleClasses(message)\"\n [class.message-bubble-sent]=\"message.senderId === currentUser()?.id\"\n [class.message-bubble-received]=\"message.senderId !== currentUser()?.id\"\n >\n <!-- Sender name (only for group conversations and received messages) -->\n @if (shouldShowSenderName(message)) {\n <div class=\"message-sender\">{{ getSenderName(message) }}:</div>\n }\n\n <!-- Reply Preview -->\n @if (message.replyTo) {\n <div\n class=\"reply-preview\"\n (click)=\"scrollToMessage(message.replyTo.id)\"\n role=\"button\"\n [attr.aria-label]=\"'Reply to ' + getSenderName(message.replyTo)\"\n (keydown.enter)=\"scrollToMessage(message.replyTo.id)\"\n (keydown.space)=\"scrollToMessage(message.replyTo.id)\"\n >\n <div class=\"reply-preview-content\">\n <div class=\"reply-preview-sender\">{{ getSenderName(message.replyTo) }}</div>\n <div class=\"reply-preview-text\">\n @if (getMessagePreviewText(message.replyTo); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i\n >{{ '@acorex:chat.' + preview.type | translate | async }}\n } @else {\n {{ preview.value }}\n }\n </span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Forwarded Indicator -->\n @if (message.forwarded) {\n <div class=\"forwarded-preview\">\n <i class=\"fa-solid fa-share\"></i>\n <span class=\"forwarded-text\">{{ getForwardedText(message) }}</span>\n </div>\n }\n\n <ax-conversation-registry-component-outlet\n [component]=\"getRendererComponent(message)\"\n [componentLoader]=\"getRendererComponentLoader(message)\"\n [inputs]=\"getRendererInputs(message)\"\n />\n\n @if (messageSupportsReactions(message) && message.reactions.length > 0) {\n <div class=\"message-reactions-container\">\n <div class=\"message-reactions-bubbles\">\n @for (reaction of getGroupedReactions(message); track reaction.emoji) {\n <button\n type=\"button\"\n class=\"reaction-bubble\"\n [class.reaction-bubble-active]=\"reaction.hasReacted\"\n (click)=\"onReactionClick(message, reaction.emoji)\"\n [attr.aria-label]=\"reaction.emoji + ' ' + reaction.count\"\n >\n <span class=\"reaction-emoji\">{{ reaction.emoji }}</span>\n @if (reaction.count > 1) {\n <span class=\"reaction-count\">{{ reaction.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Message Footer -->\n <div class=\"message-footer\">\n @let replyCount = getReplyCount(message);\n @let forwardCount = getForwardCount(message);\n @if (replyCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"replyCount + ' replies'\">\n <i class=\"fa-solid fa-message\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ replyCount }}</span>\n </span>\n }\n @if (forwardCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"forwardCount + ' forwards'\">\n <i class=\"fa-solid fa-share\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ forwardCount }}</span>\n </span>\n }\n @if (replyCount > 0 || forwardCount > 0) {\n <span class=\"message-footer-split\" aria-hidden=\"true\"></span>\n }\n <span class=\"message-time\">{{ message.timestamp | format: 'timeleft' | async }}</span>\n @if (message.editedAt) {\n <span class=\"edited-indicator\">\n <span>{{ '@acorex:chat.status.edited' | translate | async }}</span>\n </span>\n }\n @if (isOwnMessage(message)) {\n <span [class]=\"getStatusIconClasses(message)\">\n <ax-icon><i [class]=\"getStatusIcon(message)\"></i></ax-icon>\n </span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Message Actions -->\n <ax-context-menu\n [target]=\"'#message-bubble-' + message.id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleMessageContextMenuOpening($event, message)\"\n (onClose)=\"contextMenuMessageId.set(null)\"\n (onItemClick)=\"handleMessageContextMenuItemClick($event, message)\"\n >\n </ax-context-menu>\n </div>\n }\n }\n </div>\n\n <!-- Scroll to Bottom Button -->\n @if (showScrollButton()) {\n <div\n class=\"scroll-to-bottom-wrapper\"\n animate.enter=\"scroll-to-bottom-enter\"\n animate.leave=\"scroll-to-bottom-leave\"\n >\n <ax-fab\n class=\"scroll-to-bottom\"\n (onClick)=\"scrollToBottom()\"\n [attr.aria-label]=\"'@acorex:chat.actions.scroll-to-bottom' | translate | async\"\n >\n <ax-icon><i class=\"fa-light fa-arrow-down\" aria-hidden=\"true\"></i></ax-icon>\n </ax-fab>\n </div>\n }\n }\n </div>\n }\n\n <!-- Reaction Picker Popover -->\n @if (reactionsEnabled() && reactionPickerTarget()) {\n <ax-popover\n #reactionPopover\n [target]=\"reactionPickerElement()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"reactionPickerPlacement()\"\n (onClose)=\"closeReactionPicker()\"\n >\n <div class=\"reaction-picker-popup\">\n <div class=\"reaction-picker-header\">\n <span class=\"picker-title\">{{ '@acorex:chat.actions.react' | translate | async }}</span>\n <button\n type=\"button\"\n class=\"picker-close\"\n (click)=\"closeReactionPicker()\"\n [attr.aria-label]=\"'@acorex:chat.actions.close' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n <div\n class=\"reaction-picker-emojis\"\n role=\"listbox\"\n [attr.aria-label]=\"'@acorex:chat.actions.choose-reaction' | translate | async\"\n >\n @for (emoji of availableReactions(); track emoji) {\n <button\n type=\"button\"\n class=\"reaction-picker-emoji\"\n [class.reaction-picker-emoji-active]=\"hasUserReactedById(reactionPickerTarget()!, emoji)\"\n (click)=\"onReactionClickById(reactionPickerTarget()!, emoji); closeReactionPicker()\"\n [attr.aria-label]=\"emoji\"\n >\n {{ emoji }}\n </button>\n }\n </div>\n </div>\n </ax-popover>\n }\n} @else {\n <div\n class=\"message-list message-list--no-active\"\n role=\"region\"\n [attr.aria-label]=\"'@acorex:chat.status.no-conversation-selected' | translate | async\"\n >\n <div class=\"list-no-active\">\n <ng-content select=\"ax-conversation-message-list-no-active, [ax-conversation-message-list-no-active]\">\n <ng-container *ngComponentOutlet=\"noActiveFallbackComponent\"></ng-container>\n </ng-content>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-message-list{position:relative;display:block;height:100%;container-type:inline-size;@keyframes axConversationSurfaceIn{0%{opacity:0}to{opacity:1}}@keyframes axConversationSurfaceInReduced{0%{opacity:.92}to{opacity:1}}@keyframes messagesSkeletonIn{0%{opacity:0;transform:translateY(.75rem)}to{opacity:1;transform:translateY(0)}}@keyframes messagesSkeletonInReduced{0%{opacity:.85}to{opacity:1}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes axChatLoadMoreDot{0%,70%,to{transform:translateY(0) scale(1);opacity:.4}35%{transform:translateY(-.28rem) scale(1.08);opacity:1}}@keyframes axChatLoadMoreEnterPrepend{0%{opacity:0;transform:translateY(-.5rem)}to{opacity:1;transform:translateY(0)}}@keyframes axChatLoadMoreLeavePrepend{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-.35rem)}}@keyframes axScrollToBottomEnter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes axScrollToBottomLeave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}}ax-conversation-message-list .message-list{position:relative;display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden}ax-conversation-message-list .message-list.ax-drop-zone>.ax-uploader-overlay-state{display:none!important}ax-conversation-message-list .message-list--drag{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:rgba(var(--ax-sys-color-primary-surface));--tw-outline-style: dashed;outline-style:dashed;outline-offset:-2px}ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceIn .36s cubic-bezier(.22,1,.36,1) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceInReduced .18s ease both}}ax-conversation-message-list .list-loading{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;justify-content:flex-end;overflow:hidden}ax-conversation-message-list .messages-skeleton{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 6);animation:messagesSkeletonIn .42s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .message-skeleton{display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-message-list .message-skeleton--own{flex-direction:row-reverse}ax-conversation-message-list .message-skeleton-avatar{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);flex-shrink:0;border-radius:calc(infinity * 1px)}ax-conversation-message-list .message-skeleton-bubble{height:calc(var(--spacing, .25rem) * 10);border-radius:var(--radius-2xl, 1rem);width:min(62%,17.5rem)}ax-conversation-message-list .message-skeleton-bubble--short{height:calc(var(--spacing, .25rem) * 8);width:min(36%,9.5rem)}ax-conversation-message-list .message-skeleton-bubble--medium{height:calc(var(--spacing, .25rem) * 9);width:min(48%,13rem)}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .messages-skeleton{animation:messagesSkeletonInReduced .2s ease both}}ax-conversation-message-list .list-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 5);padding-inline:calc(var(--spacing, .25rem) * 8);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center;animation:fadeInUp .5s ease-out}ax-conversation-message-list .message-list--no-active{height:100%}ax-conversation-message-list .list-no-active{display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 48);flex-direction:column;align-items:center;justify-content:center}ax-conversation-message-list .empty-icon{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:5.5rem;--tw-leading: 1;line-height:1;opacity:35%;filter:grayscale(.2)}ax-conversation-message-list .empty-title{margin:calc(var(--spacing, .25rem) * 0);font-size:1.625rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-tight, -.025em);letter-spacing:var(--tracking-tight, -.025em);color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-message-list .empty-description{margin:calc(var(--spacing, .25rem) * 0);max-width:420px;font-size:1.0625rem;--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgba(var(--ax-sys-color-on-surface));opacity:.65}ax-conversation-message-list .spinner{margin-bottom:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:3px;border-color:rgba(var(--ax-sys-color-border-light-surface));border-top-color:rgb(var(--ax-sys-color-primary-500));animation:spin .8s linear infinite}ax-conversation-message-list .list-loading-more{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);padding-bottom:calc(var(--spacing, .25rem) * 2);text-align:center;color:rgba(var(--ax-sys-color-on-surface));opacity:85%}ax-conversation-message-list .load-more-indicator{display:flex;min-height:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;gap:.3rem}ax-conversation-message-list .load-more-dot{height:.4rem;width:.4rem;border-radius:calc(infinity * 1px);background-color:rgba(var(--ax-sys-color-primary-500));animation:axChatLoadMoreDot 1s ease-in-out infinite}ax-conversation-message-list .load-more-dot:nth-child(2){animation-delay:.14s}ax-conversation-message-list .load-more-dot:nth-child(3){animation-delay:.28s}ax-conversation-message-list .load-more-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%}ax-conversation-message-list .load-more-enter{animation:axChatLoadMoreEnterPrepend .32s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .load-more-leave{animation:axChatLoadMoreLeavePrepend .22s ease both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .load-more-dot{animation:none;opacity:.65}ax-conversation-message-list .load-more-enter,ax-conversation-message-list .load-more-leave{animation:none}}ax-conversation-message-list .messages-container{position:relative;min-height:calc(var(--spacing, .25rem) * 0);width:100%;flex:1;overflow-x:hidden;overflow-y:auto}ax-conversation-message-list .date-separator{pointer-events:none;position:sticky;z-index:150;display:flex;align-items:center;justify-content:center;top:.5rem;padding:.375rem 1rem .625rem;margin-block:.125rem .375rem}ax-conversation-message-list .date-separator__label{pointer-events:auto;display:inline-flex;width:calc(var(--spacing, .25rem) * 32);max-width:min(100%,18rem);align-items:center;justify-content:center;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1);text-align:center;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);white-space:nowrap;-webkit-user-select:none;user-select:none;color:rgba(var(--ax-sys-color-on-lightest-surface));background:rgba(var(--ax-sys-color-lightest-surface));border:1px solid rgba(var(--ax-sys-color-on-lightest-surface),.25)}ax-conversation-message-list .unread-separator{margin-block:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4)}ax-conversation-message-list .unread-separator-line{height:1px;flex:1;background-color:rgba(var(--ax-sys-color-primary-surface));opacity:30%}ax-conversation-message-list .unread-separator-text{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}ax-conversation-message-list .message-item{position:relative;display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 2);--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);transition:background-color .3s ease}ax-conversation-message-list .message-item-context-active{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.09);box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.22)}ax-conversation-message-list .message-own.message-item-context-active{background-color:rgba(var(--ax-sys-color-primary-500),.12)}ax-conversation-message-list .message-highlight{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-message-list .message-item.message-own{flex-direction:row-reverse}ax-conversation-message-list .message-avatar{flex-shrink:0}ax-conversation-message-list .message-avatar-icon{display:flex;height:100%;width:100%;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1}ax-conversation-message-list .message-content-row{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:0 1 auto;flex-direction:row;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 1);max-width:min(95%,50rem)}@container (min-width: 768px){ax-conversation-message-list .message-content-row{max-width:min(70%,50rem)}}ax-conversation-message-list .message-content-row-own{justify-content:flex-end}ax-conversation-message-list .message-item:not(.message-own) .message-content-row{justify-content:flex-start}ax-conversation-message-list .message-bubble-container{position:relative;display:flex;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex:1 1 auto;flex-direction:column}ax-conversation-message-list .message-own .message-bubble-container{align-items:flex-end}ax-conversation-message-list .message-sender{margin-bottom:.1rem;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-bubble{position:relative;display:flex;max-width:100%;flex-direction:column;border-radius:var(--radius-2xl, 1rem);background-color:rgba(var(--ax-sys-color-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);padding-bottom:.1rem;overflow-wrap:break-word;transition:background-color .3s ease}ax-conversation-message-list .reply-preview{margin-bottom:calc(var(--spacing, .25rem) * 2);cursor:pointer;border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .reply-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .reply-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .reply-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .reply-preview-line{width:3px;flex-shrink:0;border-radius:1.5px;background:currentColor;opacity:.5}ax-conversation-message-list .reply-preview-content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-message-list .reply-preview-sender{margin-bottom:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .reply-preview-text{overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .reply-preview-sender{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .reply-preview-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .last-message{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .forwarded-preview{margin-bottom:.1rem;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .forwarded-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .forwarded-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .forwarded-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .forwarded-preview i{flex-shrink:0;font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .forwarded-text{min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .forwarded-preview i{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .forwarded-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .message-bubble-received{border-end-start-radius:.125rem}ax-conversation-message-list .message-bubble-received:before,ax-conversation-message-list .message-bubble-sent:after{content:\"\";display:block;position:absolute;bottom:0;width:.8rem;height:.8rem;pointer-events:none;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;mask-mode:alpha}ax-conversation-message-list .message-bubble-received:before{background-color:rgba(var(--ax-sys-color-lightest-surface));inset-inline-start:-.7rem;-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list .message-bubble-sent{border-end-end-radius:.125rem}ax-conversation-message-list .message-bubble-sent:after{background:rgb(var(--ax-sys-color-primary-surface));inset-inline-end:-.7rem;-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}[dir=rtl] ax-conversation-message-list .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list:dir(rtl) .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list:dir(rtl) .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}[dir=ltr] ax-conversation-message-list .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}[dir=ltr] ax-conversation-message-list .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list .message-own .message-bubble{background:rgb(var(--ax-sys-color-primary-surface));color:rgb(var(--ax-sys-color-on-primary-surface))}ax-conversation-message-list .message-bubble.message-system{background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);max-width:100%}ax-conversation-message-list .message-bubble.message-system:before,ax-conversation-message-list .message-bubble.message-system:after{display:none}ax-conversation-message-list .message-item:has(.message-system){justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .message-item:has(.message-system) .message-content-row{max-width:100%;justify-content:center}ax-conversation-message-list .message-item:has(.message-system) .message-bubble-container{align-items:center}ax-conversation-message-list .message-content{font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);white-space:pre-wrap}ax-conversation-message-list ax-conversation-registry-component-outlet{display:block;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0)}ax-conversation-message-list .message-footer{margin-top:.1rem;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 1);padding-inline-start:calc(var(--spacing, .25rem) * 1);font-size:.6875rem;--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%;-webkit-user-select:none;user-select:none}ax-conversation-message-list .message-footer-count{display:inline-flex;align-items:center;gap:.2rem;font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .message-footer-count i{font-size:.625rem;opacity:90%}ax-conversation-message-list .message-footer-count-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-footer-split{margin-inline:.2rem;height:.65rem;width:1px;flex-shrink:0;align-self:center;background-color:rgba(var(--ax-sys-color-border-light-surface));opacity:90%}ax-conversation-message-list .message-time{font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .edited-indicator{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1);border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline-start:.35rem;font-size:.675rem;opacity:75%}ax-conversation-message-list .status-icon{display:inline-flex;align-items:center}ax-conversation-message-list .status-icon i{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}ax-conversation-message-list .status-read{color:rgba(var(--ax-sys-color-primary-200))}ax-conversation-message-list .status-failed{color:rgba(var(--ax-sys-color-danger-200))}ax-conversation-message-list .message-reactions-bubbles{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem}ax-conversation-message-list .reaction-bubble{margin:calc(var(--spacing, .25rem) * 0);display:inline-flex;min-height:1.375rem;cursor:pointer;align-items:center;justify-content:center;gap:.15rem;border-radius:var(--radius-xl, .75rem);padding-inline:.35rem;padding-block:.1rem;color:rgba(var(--ax-sys-color-on-surface));--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);background:rgba(var(--ax-sys-color-on-surface),.06);border:1px solid rgba(var(--ax-sys-color-on-surface),.1);transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}ax-conversation-message-list .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-surface),.1);border-color:rgba(var(--ax-sys-color-on-surface),.18)}ax-conversation-message-list .reaction-bubble-active{background:rgba(var(--ax-sys-color-primary-500),.12);border-color:rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-message-list .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-primary-500),.18);border-color:rgba(var(--ax-sys-color-primary-500),.55)}ax-conversation-message-list .reaction-emoji{display:inline-block;font-size:.8125rem;--tw-leading: 1;line-height:1}ax-conversation-message-list .reaction-count{font-size:.6875rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:.65}ax-conversation-message-list .reaction-bubble-active .reaction-count{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600));opacity:95%}ax-conversation-message-list .message-own .reaction-bubble{color:rgba(var(--ax-sys-color-on-primary-surface));background:rgba(var(--ax-sys-color-on-primary-surface),.12);border-color:rgba(var(--ax-sys-color-on-primary-surface),.2)}ax-conversation-message-list .message-own .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.2);border-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .reaction-bubble-active{background:rgba(var(--ax-sys-color-on-primary-surface),.28);border-color:rgba(var(--ax-sys-color-on-primary-surface),.5)}ax-conversation-message-list .message-own .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.34);border-color:rgba(var(--ax-sys-color-on-primary-surface),.6)}ax-conversation-message-list .message-own .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:80%}ax-conversation-message-list .message-own .reaction-bubble-active .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:100%}ax-conversation-message-list .message-reactions-container{margin-top:calc(var(--spacing, .25rem) * 1);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:.2rem}ax-conversation-message-list .message-own .message-reactions-container{justify-content:flex-end}ax-conversation-message-list .message-own .message-footer .edited-indicator{border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .message-footer .message-footer-split{background:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .add-reaction-button.add-reaction-outside{position:absolute;top:50%;margin:calc(var(--spacing, .25rem) * 0);box-sizing:border-box;display:none;height:1.8rem;width:1.8rem;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 0);inset-inline-end:-2.25rem;box-shadow:0 1px 2px #0000000f}ax-conversation-message-list .add-reaction-button{padding-inline-start:.05rem}ax-conversation-message-list .message-content-row-own .add-reaction-button.add-reaction-outside{inset-inline-start:-2.25rem;inset-inline-end:auto}ax-conversation-message-list .message-item:hover .add-reaction-button.add-reaction-outside,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{display:inline-flex}ax-conversation-message-list .add-reaction-button.add-reaction-outside:hover,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .add-reaction-button.add-reaction-outside i{font-size:.9rem;color:rgba(var(--ax-sys-color-on-surface));opacity:80%}ax-conversation-message-list .reaction-bubble:focus-visible,ax-conversation-message-list .add-reaction-button:focus-visible,ax-conversation-message-list .action-trigger:focus-visible,ax-conversation-message-list ax-fab.scroll-to-bottom ax-button:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .message-actions{z-index:10;padding-bottom:calc(var(--spacing, .25rem) * 6);opacity:0%;transition:opacity var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .message-item:hover .message-actions{opacity:100%}ax-conversation-message-list .action-trigger{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .action-trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-message-list .shortcut{font-size:.6875rem;opacity:70%}ax-conversation-message-list .scroll-to-bottom-wrapper{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * 4);bottom:calc(var(--spacing, .25rem) * 4);z-index:999}ax-conversation-message-list ax-fab.scroll-to-bottom ax-button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none}ax-conversation-message-list .scroll-to-bottom-enter{animation:axScrollToBottomEnter var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}ax-conversation-message-list .scroll-to-bottom-leave{animation:axScrollToBottomLeave var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .scroll-to-bottom-enter,ax-conversation-message-list .scroll-to-bottom-leave{animation:none}}.reaction-picker-popup{width:max-content;min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;border-radius:.65rem;background-color:rgba(var(--ax-sys-color-lightest-surface));max-width:min(260px,92vw)}.reaction-picker-header{display:flex;min-height:calc(var(--spacing, .25rem) * 0);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:.45rem;padding-inline-start:.7rem;padding-inline-end:calc(var(--spacing, .25rem) * 2)}.picker-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-on-surface));opacity:85%}.picker-close{display:flex;height:1.6rem;width:1.6rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:.95rem;color:rgba(var(--ax-sys-color-on-surface),.55);transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}.picker-close:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}.picker-close:focus-visible,.reaction-picker-emoji:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}.reaction-picker-emojis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.2rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:.45rem;padding-bottom:calc(var(--spacing, .25rem) * 2)}.reaction-picker-emoji{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);cursor:pointer;border-radius:.45rem;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:1.15rem;--tw-leading: 1;line-height:1;transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.reaction-picker-emoji:hover{background-color:rgba(var(--ax-sys-color-lighter-surface))}.reaction-picker-emoji-active{background-color:rgba(var(--ax-sys-color-surface))}.reaction-picker-emoji-active:hover{background:rgba(var(--ax-sys-color-primary-500),.25)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-outline-style: solid;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXFabComponent, selector: "ax-fab", inputs: ["label", "popupStyle", "popupPlacement", "size"], outputs: ["popupPlacementChange", "onClick", "onOpened", "onClosed"] }, { kind: "component", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: AXConversationInfiniteScrollDirective, selector: "[axInfiniteScroll]", inputs: ["threshold", "edge", "scrollDisabled", "cooldownMs"], outputs: ["scrollThreshold"] }, { kind: "directive", type: AXUploaderZoneDirective, selector: "[axUploaderZone]", inputs: ["multiple", "accept", "fileType", "overlayTemplate", "disableBrowse", "disableDragDrop"], outputs: ["fileChange", "onChanged", "dragEnter", "dragLeave", "dragOver", "onFileUploadComplete", "onFilesUploadComplete"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
8998
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationMessageListComponent, isStandalone: true, selector: "ax-conversation-message-list", outputs: { messageAction: "messageAction" }, viewQueries: [{ propertyName: "reactionPopover", first: true, predicate: ["reactionPopover"], descendants: true, isSignal: true }, { propertyName: "messageListRef", first: true, predicate: ["messageList"], descendants: true, isSignal: true }, { propertyName: "messagesContainerRef", first: true, predicate: ["messagesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (activeConversation(); as conv) {\n @for (cid of [conv.id]; track cid) {\n <div\n class=\"message-list message-list--conversation-surface\"\n [class.message-list--drag]=\"messageListDragging()\"\n #messageList\n role=\"log\"\n [attr.aria-label]=\"'@acorex:chat.aria.message-list' | translate | async\"\n aria-live=\"polite\"\n [style.background]=\"messageListBackgroundStyle()\"\n [style.--ax-comp-message-list-surface-bg]=\"messageListBackgroundStyle()\"\n axUploaderZone\n [disableBrowse]=\"true\"\n (dragEnter)=\"onMessageListDragEnter()\"\n (dragLeave)=\"onMessageListDragLeave()\"\n (fileChange)=\"onMessageListFilesDropped($event)\"\n >\n @if (loading()) {\n <div\n class=\"list-loading\"\n role=\"status\"\n aria-busy=\"true\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-messages' | translate | async\"\n >\n <div class=\"messages-skeleton\" aria-hidden=\"true\">\n @for (item of loadingSkeletonItems; track item) {\n <div class=\"message-skeleton\" [class.message-skeleton--own]=\"$odd\">\n @if ($even && isGroupConversation()) {\n <ax-skeleton class=\"message-skeleton-avatar\" [animated]=\"true\"></ax-skeleton>\n }\n <ax-skeleton\n class=\"message-skeleton-bubble\"\n [class.message-skeleton-bubble--short]=\"$index % 3 === 1\"\n [class.message-skeleton-bubble--medium]=\"$index % 3 === 2\"\n [animated]=\"true\"\n ></ax-skeleton>\n </div>\n }\n </div>\n </div>\n } @else if (messages().length === 0) {\n <div class=\"list-empty\" role=\"status\" [attr.aria-label]=\"'@acorex:chat.status.no-messages' | translate | async\">\n <ng-content select=\"ax-conversation-message-list-empty, [ax-conversation-message-list-empty]\">\n <ng-container\n *ngComponentOutlet=\"resolvedEmptyStateComponent(); inputs: { conversation: activeConversation()! }\"\n ></ng-container>\n </ng-content>\n </div>\n } @else {\n <div\n class=\"messages-container\"\n (scroll)=\"onScroll($event)\"\n axInfiniteScroll\n [threshold]=\"config.infiniteScrollThreshold\"\n [edge]=\"'top'\"\n [scrollDisabled]=\"loading() || loadingMore() || !hasMoreMessages()\"\n (scrollThreshold)=\"onScrollThreshold($event)\"\n #messagesContainer\n role=\"feed\"\n [attr.aria-label]=\"'@acorex:chat.aria.messages' | translate | async\"\n >\n @if (loadingMore()) {\n <div\n class=\"list-loading-more list-loading-more--prepend\"\n role=\"status\"\n animate.enter=\"load-more-enter\"\n animate.leave=\"load-more-leave\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-older-messages' | translate | async\"\n >\n <div class=\"load-more-indicator\" aria-hidden=\"true\">\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n </div>\n <ax-label class=\"load-more-label\">{{\n '@acorex:chat.status.loading-older-messages' | translate | async\n }}</ax-label>\n </div>\n }\n @for (group of messageGroups(); track trackMessageGroup($index, group)) {\n <!-- Date Separator -->\n <div class=\"date-separator\" role=\"separator\" [attr.aria-label]=\"getDateSeparatorAriaLabel(group.dateLabel)\">\n <span class=\"date-separator__label\">{{ group.dateLabel }}</span>\n </div>\n\n <!-- Messages in this date group -->\n @for (message of group.messages; track trackMessage($index, message)) {\n <div\n [class]=\"getMessageClasses(message)\"\n role=\"article\"\n [attr.aria-label]=\"getMessageAriaLabel(message)\"\n [id]=\"'message-' + message.id\"\n >\n <!-- Avatar (only for group conversations and received messages) -->\n @if (shouldShowAvatar(message)) {\n <div class=\"message-avatar\">\n <ax-conversation-avatar\n kind=\"user\"\n [userId]=\"message.senderId\"\n [conversation]=\"activeConversation()\"\n [message]=\"message\"\n [size]=\"32\"\n />\n </div>\n }\n\n <div class=\"message-content-row\" [class.message-content-row-own]=\"isOwnMessage(message)\">\n @if (messageSupportsReactions(message)) {\n <button\n type=\"button\"\n class=\"add-reaction-button add-reaction-outside\"\n [class.add-reaction-visible]=\"reactionPickerTarget() === message.id\"\n (click)=\"toggleReactionPicker(message, $event)\"\n [attr.aria-label]=\"'@acorex:chat.actions.add-reaction' | translate | async\"\n #reactionButton\n >\n <i class=\"fa-light fa-face-smile\"></i>\n </button>\n }\n\n <div\n class=\"message-bubble-container\"\n [id]=\"'message-bubble-' + message.id\"\n [attr.data-message-id]=\"message.id\"\n >\n <div\n [class]=\"getBubbleClasses(message)\"\n [class.message-bubble-sent]=\"message.senderId === currentUser()?.id\"\n [class.message-bubble-received]=\"message.senderId !== currentUser()?.id\"\n >\n <!-- Sender name (only for group conversations and received messages) -->\n @if (shouldShowSenderName(message)) {\n <div class=\"message-sender\">{{ getSenderName(message) }}:</div>\n }\n\n <!-- Reply Preview -->\n @if (message.replyTo) {\n <div\n class=\"reply-preview\"\n (click)=\"scrollToMessage(message.replyTo.id)\"\n role=\"button\"\n [attr.aria-label]=\"'Reply to ' + getSenderName(message.replyTo)\"\n (keydown.enter)=\"scrollToMessage(message.replyTo.id)\"\n (keydown.space)=\"scrollToMessage(message.replyTo.id)\"\n >\n <div class=\"reply-preview-content\">\n <div class=\"reply-preview-sender\">{{ getSenderName(message.replyTo) }}</div>\n <div class=\"reply-preview-text\">\n @if (getMessagePreviewText(message.replyTo); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i\n >{{ '@acorex:chat.' + preview.type | translate | async }}\n } @else {\n {{ preview.value }}\n }\n </span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Forwarded Indicator -->\n @if (message.forwarded) {\n <div class=\"forwarded-preview\">\n <i class=\"fa-solid fa-share\"></i>\n <span class=\"forwarded-text\">{{ getForwardedText(message) }}</span>\n </div>\n }\n\n <ax-conversation-registry-component-outlet\n [component]=\"getRendererComponent(message)\"\n [componentLoader]=\"getRendererComponentLoader(message)\"\n [inputs]=\"getRendererInputs(message)\"\n />\n\n @if (messageSupportsReactions(message) && message.reactions.length > 0) {\n <div class=\"message-reactions-container\">\n <div class=\"message-reactions-bubbles\">\n @for (reaction of getGroupedReactions(message); track reaction.emoji) {\n <button\n type=\"button\"\n class=\"reaction-bubble\"\n [class.reaction-bubble-active]=\"reaction.hasReacted\"\n (click)=\"onReactionClick(message, reaction.emoji)\"\n [attr.aria-label]=\"reaction.emoji + ' ' + reaction.count\"\n >\n <span class=\"reaction-emoji\">{{ reaction.emoji }}</span>\n @if (reaction.count > 1) {\n <span class=\"reaction-count\">{{ reaction.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Message Footer -->\n <div class=\"message-footer\">\n @let replyCount = getReplyCount(message);\n @let forwardCount = getForwardCount(message);\n @if (replyCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"replyCount + ' replies'\">\n <i class=\"fa-solid fa-message\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ replyCount }}</span>\n </span>\n }\n @if (forwardCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"forwardCount + ' forwards'\">\n <i class=\"fa-solid fa-share\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ forwardCount }}</span>\n </span>\n }\n @if (replyCount > 0 || forwardCount > 0) {\n <span class=\"message-footer-split\" aria-hidden=\"true\"></span>\n }\n <span class=\"message-time\">{{ message.timestamp | format: 'timeleft' | async }}</span>\n @if (message.editedAt) {\n <span class=\"edited-indicator\">\n <span>{{ '@acorex:chat.status.edited' | translate | async }}</span>\n </span>\n }\n @if (isOwnMessage(message)) {\n <span [class]=\"getStatusIconClasses(message)\">\n <ax-icon><i [class]=\"getStatusIcon(message)\"></i></ax-icon>\n </span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Message Actions -->\n <ax-context-menu\n [target]=\"'#message-bubble-' + message.id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleMessageContextMenuOpening($event, message)\"\n (onClose)=\"contextMenuMessageId.set(null)\"\n (onItemClick)=\"handleMessageContextMenuItemClick($event, message)\"\n >\n </ax-context-menu>\n </div>\n }\n }\n </div>\n\n <!-- Scroll to Bottom Button -->\n @if (showScrollButton()) {\n <div\n class=\"scroll-to-bottom-wrapper\"\n animate.enter=\"scroll-to-bottom-enter\"\n animate.leave=\"scroll-to-bottom-leave\"\n >\n <ax-fab\n class=\"scroll-to-bottom\"\n (onClick)=\"scrollToBottom()\"\n [attr.aria-label]=\"'@acorex:chat.actions.scroll-to-bottom' | translate | async\"\n >\n <ax-icon><i class=\"fa-light fa-arrow-down\" aria-hidden=\"true\"></i></ax-icon>\n </ax-fab>\n </div>\n }\n }\n </div>\n }\n\n <!-- Reaction Picker Popover -->\n @if (reactionsEnabled() && reactionPickerTarget()) {\n <ax-popover\n #reactionPopover\n [target]=\"reactionPickerElement()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"reactionPickerPlacement()\"\n (onClose)=\"closeReactionPicker()\"\n >\n <div class=\"reaction-picker-popup\">\n <div class=\"reaction-picker-header\">\n <span class=\"picker-title\">{{ '@acorex:chat.actions.react' | translate | async }}</span>\n <button\n type=\"button\"\n class=\"picker-close\"\n (click)=\"closeReactionPicker()\"\n [attr.aria-label]=\"'@acorex:chat.actions.close' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n <div\n class=\"reaction-picker-emojis\"\n role=\"listbox\"\n [attr.aria-label]=\"'@acorex:chat.actions.choose-reaction' | translate | async\"\n >\n @for (emoji of availableReactions(); track emoji) {\n <button\n type=\"button\"\n class=\"reaction-picker-emoji\"\n [class.reaction-picker-emoji-active]=\"hasUserReactedById(reactionPickerTarget()!, emoji)\"\n (click)=\"onReactionClickById(reactionPickerTarget()!, emoji); closeReactionPicker()\"\n [attr.aria-label]=\"emoji\"\n >\n {{ emoji }}\n </button>\n }\n </div>\n </div>\n </ax-popover>\n }\n} @else {\n <div\n class=\"message-list message-list--no-active\"\n role=\"region\"\n [attr.aria-label]=\"'@acorex:chat.status.no-conversation-selected' | translate | async\"\n >\n <div class=\"list-no-active\">\n <ng-content select=\"ax-conversation-message-list-no-active, [ax-conversation-message-list-no-active]\">\n <ng-container *ngComponentOutlet=\"noActiveFallbackComponent\"></ng-container>\n </ng-content>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-message-list{position:relative;display:block;height:100%;container-type:inline-size;--ax-comp-message-bubble-tail-height: 1.5625rem;--ax-comp-message-bubble-tail-fill-width: 1.25rem;--ax-comp-message-bubble-tail-fill-offset: -.4375rem;--ax-comp-message-bubble-tail-cutout-width: 1.625rem;--ax-comp-message-bubble-tail-cutout-offset: -1.625rem;--ax-comp-message-bubble-tail-curve: 1rem 0rem;--ax-comp-message-bubble-tail-cutout-curve: .625rem;@keyframes axConversationSurfaceIn{0%{opacity:0}to{opacity:1}}@keyframes axConversationSurfaceInReduced{0%{opacity:.92}to{opacity:1}}@keyframes messagesSkeletonIn{0%{opacity:0;transform:translateY(.75rem)}to{opacity:1;transform:translateY(0)}}@keyframes messagesSkeletonInReduced{0%{opacity:.85}to{opacity:1}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes axChatLoadMoreDot{0%,70%,to{transform:translateY(0) scale(1);opacity:.4}35%{transform:translateY(-.28rem) scale(1.08);opacity:1}}@keyframes axChatLoadMoreEnterPrepend{0%{opacity:0;transform:translateY(-.5rem)}to{opacity:1;transform:translateY(0)}}@keyframes axChatLoadMoreLeavePrepend{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-.35rem)}}@keyframes axScrollToBottomEnter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes axScrollToBottomLeave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}}ax-conversation-message-list .message-list{position:relative;display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden}ax-conversation-message-list .message-list.ax-drop-zone>.ax-uploader-overlay-state{display:none!important}ax-conversation-message-list .message-list--drag{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:rgba(var(--ax-sys-color-primary-surface));--tw-outline-style: dashed;outline-style:dashed;outline-offset:-2px}ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceIn .36s cubic-bezier(.22,1,.36,1) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceInReduced .18s ease both}}ax-conversation-message-list .list-loading{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;justify-content:flex-end;overflow:hidden}ax-conversation-message-list .messages-skeleton{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 6);animation:messagesSkeletonIn .42s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .message-skeleton{display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-message-list .message-skeleton--own{flex-direction:row-reverse}ax-conversation-message-list .message-skeleton-avatar{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);flex-shrink:0;border-radius:calc(infinity * 1px)}ax-conversation-message-list .message-skeleton-bubble{height:calc(var(--spacing, .25rem) * 10);border-radius:var(--radius-2xl, 1rem);width:min(62%,17.5rem)}ax-conversation-message-list .message-skeleton-bubble--short{height:calc(var(--spacing, .25rem) * 8);width:min(36%,9.5rem)}ax-conversation-message-list .message-skeleton-bubble--medium{height:calc(var(--spacing, .25rem) * 9);width:min(48%,13rem)}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .messages-skeleton{animation:messagesSkeletonInReduced .2s ease both}}ax-conversation-message-list .list-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 5);padding-inline:calc(var(--spacing, .25rem) * 8);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center;animation:fadeInUp .5s ease-out}ax-conversation-message-list .message-list--no-active{height:100%}ax-conversation-message-list .list-no-active{display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 48);flex-direction:column;align-items:center;justify-content:center}ax-conversation-message-list .empty-icon{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:5.5rem;--tw-leading: 1;line-height:1;opacity:35%;filter:grayscale(.2)}ax-conversation-message-list .empty-title{margin:calc(var(--spacing, .25rem) * 0);font-size:1.625rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-tight, -.025em);letter-spacing:var(--tracking-tight, -.025em);color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-message-list .empty-description{margin:calc(var(--spacing, .25rem) * 0);max-width:420px;font-size:1.0625rem;--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgba(var(--ax-sys-color-on-surface));opacity:.65}ax-conversation-message-list .spinner{margin-bottom:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:3px;border-color:rgba(var(--ax-sys-color-border-light-surface));border-top-color:rgb(var(--ax-sys-color-primary-500));animation:spin .8s linear infinite}ax-conversation-message-list .list-loading-more{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);padding-bottom:calc(var(--spacing, .25rem) * 2);text-align:center;color:rgba(var(--ax-sys-color-on-surface));opacity:85%}ax-conversation-message-list .load-more-indicator{display:flex;min-height:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;gap:.3rem}ax-conversation-message-list .load-more-dot{height:.4rem;width:.4rem;border-radius:calc(infinity * 1px);background-color:rgba(var(--ax-sys-color-primary-500));animation:axChatLoadMoreDot 1s ease-in-out infinite}ax-conversation-message-list .load-more-dot:nth-child(2){animation-delay:.14s}ax-conversation-message-list .load-more-dot:nth-child(3){animation-delay:.28s}ax-conversation-message-list .load-more-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%}ax-conversation-message-list .load-more-enter{animation:axChatLoadMoreEnterPrepend .32s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .load-more-leave{animation:axChatLoadMoreLeavePrepend .22s ease both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .load-more-dot{animation:none;opacity:.65}ax-conversation-message-list .load-more-enter,ax-conversation-message-list .load-more-leave{animation:none}}ax-conversation-message-list .messages-container{position:relative;min-height:calc(var(--spacing, .25rem) * 0);width:100%;flex:1;overflow-y:auto;overflow-x:visible}ax-conversation-message-list .date-separator{pointer-events:none;position:sticky;z-index:150;display:flex;align-items:center;justify-content:center;top:.5rem;padding:.375rem 1rem .625rem;margin-block:.125rem .375rem}ax-conversation-message-list .date-separator__label{pointer-events:auto;display:inline-flex;width:calc(var(--spacing, .25rem) * 32);max-width:min(100%,18rem);align-items:center;justify-content:center;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1);text-align:center;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);white-space:nowrap;-webkit-user-select:none;user-select:none;color:rgba(var(--ax-sys-color-on-lightest-surface));background:rgba(var(--ax-sys-color-lightest-surface));border:1px solid rgba(var(--ax-sys-color-on-lightest-surface),.25)}ax-conversation-message-list .unread-separator{margin-block:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4)}ax-conversation-message-list .unread-separator-line{height:1px;flex:1;background-color:rgba(var(--ax-sys-color-primary-surface));opacity:30%}ax-conversation-message-list .unread-separator-text{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}ax-conversation-message-list .message-item{position:relative;display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);padding-inline:1.75rem;transition:background-color .3s ease}ax-conversation-message-list .message-item-context-active{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.09);box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.22)}ax-conversation-message-list .message-own.message-item-context-active{background-color:rgba(var(--ax-sys-color-primary-500),.12)}ax-conversation-message-list .message-highlight{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-message-list .message-item.message-own{flex-direction:row-reverse}ax-conversation-message-list .message-avatar{z-index:5;flex-shrink:0}ax-conversation-message-list .message-avatar-icon{display:flex;height:100%;width:100%;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1}ax-conversation-message-list .message-content-row{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:0 1 auto;flex-direction:row;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 1);max-width:min(95%,50rem)}@container (min-width: 768px){ax-conversation-message-list .message-content-row{max-width:min(70%,50rem)}}ax-conversation-message-list .message-content-row-own{justify-content:flex-end}ax-conversation-message-list .message-item:not(.message-own) .message-content-row{justify-content:flex-start}ax-conversation-message-list .message-bubble-container{position:relative;display:flex;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex:1 1 auto;flex-direction:column}ax-conversation-message-list .message-own .message-bubble-container{align-items:flex-end}ax-conversation-message-list .message-sender{margin-bottom:.1rem;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-bubble{position:relative;display:flex;max-width:100%;flex-direction:column;border-radius:var(--radius-2xl, 1rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);padding-bottom:.1rem;overflow-wrap:break-word;transition:background-color .3s ease}ax-conversation-message-list .message-bubble>*{position:relative;z-index:1}ax-conversation-message-list .reply-preview{margin-bottom:calc(var(--spacing, .25rem) * 2);cursor:pointer;border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .reply-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .reply-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .reply-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .reply-preview-line{width:3px;flex-shrink:0;border-radius:1.5px;background:currentColor;opacity:.5}ax-conversation-message-list .reply-preview-content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-message-list .reply-preview-sender{margin-bottom:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .reply-preview-text{overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .reply-preview-sender{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .reply-preview-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .last-message{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .forwarded-preview{margin-bottom:.1rem;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .forwarded-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .forwarded-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .forwarded-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .forwarded-preview i{flex-shrink:0;font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .forwarded-text{min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .forwarded-preview i{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .forwarded-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .message-bubble-received:not(.message-system){--ax-comp-message-bubble-bg: rgb(var(--ax-sys-color-lightest-surface));background-color:var(--ax-comp-message-bubble-bg);border-bottom-left-radius:.25rem}ax-conversation-message-list .message-bubble-sent:not(.message-system){--ax-comp-message-bubble-bg: rgb(var(--ax-sys-color-primary-surface));background-color:var(--ax-comp-message-bubble-bg);color:rgb(var(--ax-sys-color-on-primary-surface));border-bottom-right-radius:.25rem}ax-conversation-message-list .message-bubble-received:not(.message-system):before,ax-conversation-message-list .message-bubble-received:not(.message-system):after,ax-conversation-message-list .message-bubble-sent:not(.message-system):before,ax-conversation-message-list .message-bubble-sent:not(.message-system):after{content:\"\";position:absolute;bottom:0;height:var(--ax-comp-message-bubble-tail-height);pointer-events:none;z-index:0}ax-conversation-message-list .message-bubble-received:not(.message-system):before,ax-conversation-message-list .message-bubble-sent:not(.message-system):before{width:var(--ax-comp-message-bubble-tail-fill-width);background-color:var(--ax-comp-message-bubble-bg)}ax-conversation-message-list .message-bubble-received:not(.message-system):after,ax-conversation-message-list .message-bubble-sent:not(.message-system):after{width:var(--ax-comp-message-bubble-tail-cutout-width);background:var(--ax-comp-message-list-surface-bg, rgb(var(--ax-sys-color-primary-lightest-surface)))}ax-conversation-message-list .message-bubble-received:not(.message-system):before{left:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-right-radius:var(--ax-comp-message-bubble-tail-curve)}ax-conversation-message-list .message-bubble-received:not(.message-system):after{left:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-right-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}ax-conversation-message-list .message-bubble-sent:not(.message-system):before{right:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-left-radius:var(--ax-comp-message-bubble-tail-curve)}ax-conversation-message-list .message-bubble-sent:not(.message-system):after{right:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-left-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system){border-bottom-left-radius:1rem;border-bottom-right-radius:.25rem}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system){border-bottom-right-radius:1rem;border-bottom-left-radius:.25rem}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system):before{left:auto;right:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-right-radius:0;border-bottom-left-radius:var(--ax-comp-message-bubble-tail-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system):after{left:auto;right:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-right-radius:0;border-bottom-left-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system):before{right:auto;left:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-left-radius:0;border-bottom-right-radius:var(--ax-comp-message-bubble-tail-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system):after{right:auto;left:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-left-radius:0;border-bottom-right-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}ax-conversation-message-list .message-bubble.message-system:before,ax-conversation-message-list .message-bubble.message-system:after{display:none}ax-conversation-message-list .message-own .message-bubble{color:rgb(var(--ax-sys-color-on-primary-surface))}ax-conversation-message-list .message-bubble.message-system{background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);max-width:100%}ax-conversation-message-list .message-item:has(.message-system){justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .message-item:has(.message-system) .message-content-row{max-width:100%;justify-content:center}ax-conversation-message-list .message-item:has(.message-system) .message-bubble-container{align-items:center}ax-conversation-message-list .message-content{font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);white-space:pre-wrap}ax-conversation-message-list ax-conversation-registry-component-outlet{display:block;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0)}ax-conversation-message-list .message-footer{margin-top:.1rem;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 1);padding-inline-start:calc(var(--spacing, .25rem) * 1);font-size:.6875rem;--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%;-webkit-user-select:none;user-select:none}ax-conversation-message-list .message-footer-count{display:inline-flex;align-items:center;gap:.2rem;font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .message-footer-count i{font-size:.625rem;opacity:90%}ax-conversation-message-list .message-footer-count-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-footer-split{margin-inline:.2rem;height:.65rem;width:1px;flex-shrink:0;align-self:center;background-color:rgba(var(--ax-sys-color-border-light-surface));opacity:90%}ax-conversation-message-list .message-time{font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .edited-indicator{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1);border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline-start:.35rem;font-size:.675rem;opacity:75%}ax-conversation-message-list .status-icon{display:inline-flex;align-items:center}ax-conversation-message-list .status-icon i{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}ax-conversation-message-list .status-read{color:rgba(var(--ax-sys-color-primary-200))}ax-conversation-message-list .status-failed{color:rgba(var(--ax-sys-color-danger-200))}ax-conversation-message-list .message-reactions-bubbles{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem}ax-conversation-message-list .reaction-bubble{margin:calc(var(--spacing, .25rem) * 0);display:inline-flex;min-height:1.375rem;cursor:pointer;align-items:center;justify-content:center;gap:.15rem;border-radius:var(--radius-xl, .75rem);padding-inline:.35rem;padding-block:.1rem;color:rgba(var(--ax-sys-color-on-surface));--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);background:rgba(var(--ax-sys-color-on-surface),.06);border:1px solid rgba(var(--ax-sys-color-on-surface),.1);transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}ax-conversation-message-list .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-surface),.1);border-color:rgba(var(--ax-sys-color-on-surface),.18)}ax-conversation-message-list .reaction-bubble-active{background:rgba(var(--ax-sys-color-primary-500),.12);border-color:rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-message-list .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-primary-500),.18);border-color:rgba(var(--ax-sys-color-primary-500),.55)}ax-conversation-message-list .reaction-emoji{display:inline-block;font-size:.8125rem;--tw-leading: 1;line-height:1}ax-conversation-message-list .reaction-count{font-size:.6875rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:.65}ax-conversation-message-list .reaction-bubble-active .reaction-count{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600));opacity:95%}ax-conversation-message-list .message-own .reaction-bubble{color:rgba(var(--ax-sys-color-on-primary-surface));background:rgba(var(--ax-sys-color-on-primary-surface),.12);border-color:rgba(var(--ax-sys-color-on-primary-surface),.2)}ax-conversation-message-list .message-own .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.2);border-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .reaction-bubble-active{background:rgba(var(--ax-sys-color-on-primary-surface),.28);border-color:rgba(var(--ax-sys-color-on-primary-surface),.5)}ax-conversation-message-list .message-own .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.34);border-color:rgba(var(--ax-sys-color-on-primary-surface),.6)}ax-conversation-message-list .message-own .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:80%}ax-conversation-message-list .message-own .reaction-bubble-active .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:100%}ax-conversation-message-list .message-reactions-container{margin-top:calc(var(--spacing, .25rem) * 1);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:.2rem}ax-conversation-message-list .message-own .message-reactions-container{justify-content:flex-end}ax-conversation-message-list .message-own .message-footer .edited-indicator{border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .message-footer .message-footer-split{background:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .add-reaction-button.add-reaction-outside{position:absolute;top:50%;margin:calc(var(--spacing, .25rem) * 0);box-sizing:border-box;display:none;height:1.8rem;width:1.8rem;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 0);inset-inline-end:-2.25rem;box-shadow:0 1px 2px #0000000f}ax-conversation-message-list .add-reaction-button{padding-inline-start:.05rem}ax-conversation-message-list .message-content-row-own .add-reaction-button.add-reaction-outside{inset-inline-start:-2.25rem;inset-inline-end:auto}ax-conversation-message-list .message-item:hover .add-reaction-button.add-reaction-outside,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{display:inline-flex}ax-conversation-message-list .add-reaction-button.add-reaction-outside:hover,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .add-reaction-button.add-reaction-outside i{font-size:.9rem;color:rgba(var(--ax-sys-color-on-surface));opacity:80%}ax-conversation-message-list .reaction-bubble:focus-visible,ax-conversation-message-list .add-reaction-button:focus-visible,ax-conversation-message-list .action-trigger:focus-visible,ax-conversation-message-list ax-fab.scroll-to-bottom ax-button:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .message-actions{z-index:10;padding-bottom:calc(var(--spacing, .25rem) * 6);opacity:0%;transition:opacity var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .message-item:hover .message-actions{opacity:100%}ax-conversation-message-list .action-trigger{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .action-trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-message-list .shortcut{font-size:.6875rem;opacity:70%}ax-conversation-message-list .scroll-to-bottom-wrapper{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * 4);bottom:calc(var(--spacing, .25rem) * 4);z-index:999}ax-conversation-message-list ax-fab.scroll-to-bottom ax-button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none}ax-conversation-message-list .scroll-to-bottom-enter{animation:axScrollToBottomEnter var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}ax-conversation-message-list .scroll-to-bottom-leave{animation:axScrollToBottomLeave var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .scroll-to-bottom-enter,ax-conversation-message-list .scroll-to-bottom-leave{animation:none}}.reaction-picker-popup{width:max-content;min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;border-radius:.65rem;background-color:rgba(var(--ax-sys-color-lightest-surface));max-width:min(260px,92vw)}.reaction-picker-header{display:flex;min-height:calc(var(--spacing, .25rem) * 0);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:.45rem;padding-inline-start:.7rem;padding-inline-end:calc(var(--spacing, .25rem) * 2)}.picker-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-on-surface));opacity:85%}.picker-close{display:flex;height:1.6rem;width:1.6rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:.95rem;color:rgba(var(--ax-sys-color-on-surface),.55);transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}.picker-close:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}.picker-close:focus-visible,.reaction-picker-emoji:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}.reaction-picker-emojis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.2rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:.45rem;padding-bottom:calc(var(--spacing, .25rem) * 2)}.reaction-picker-emoji{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);cursor:pointer;border-radius:.45rem;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:1.15rem;--tw-leading: 1;line-height:1;transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.reaction-picker-emoji:hover{background-color:rgba(var(--ax-sys-color-lighter-surface))}.reaction-picker-emoji-active{background-color:rgba(var(--ax-sys-color-surface))}.reaction-picker-emoji-active:hover{background:rgba(var(--ax-sys-color-primary-500),.25)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-outline-style: solid;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXFabComponent, selector: "ax-fab", inputs: ["label", "popupStyle", "popupPlacement", "size"], outputs: ["popupPlacementChange", "onClick", "onOpened", "onClosed"] }, { kind: "component", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: AXConversationInfiniteScrollDirective, selector: "[axInfiniteScroll]", inputs: ["threshold", "edge", "scrollDisabled", "cooldownMs"], outputs: ["scrollThreshold"] }, { kind: "directive", type: AXUploaderZoneDirective, selector: "[axUploaderZone]", inputs: ["multiple", "accept", "fileType", "overlayTemplate", "disableBrowse", "disableDragDrop"], outputs: ["fileChange", "onChanged", "dragEnter", "dragLeave", "dragOver", "onFileUploadComplete", "onFilesUploadComplete"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
8776
8999
|
}
|
|
8777
9000
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationMessageListComponent, decorators: [{
|
|
8778
9001
|
type: Component,
|
|
@@ -8791,7 +9014,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
8791
9014
|
AXUploaderZoneDirective,
|
|
8792
9015
|
AXConversationAvatarComponent,
|
|
8793
9016
|
AXConversationRegistryComponentOutletComponent,
|
|
8794
|
-
], template: "@if (activeConversation(); as conv) {\n @for (cid of [conv.id]; track cid) {\n <div\n class=\"message-list message-list--conversation-surface\"\n [class.message-list--drag]=\"messageListDragging()\"\n #messageList\n role=\"log\"\n [attr.aria-label]=\"'@acorex:chat.aria.message-list' | translate | async\"\n aria-live=\"polite\"\n [style.background]=\"messageListBackgroundStyle()\"\n axUploaderZone\n [disableBrowse]=\"true\"\n (dragEnter)=\"onMessageListDragEnter()\"\n (dragLeave)=\"onMessageListDragLeave()\"\n (fileChange)=\"onMessageListFilesDropped($event)\"\n >\n @if (loading()) {\n <div\n class=\"list-loading\"\n role=\"status\"\n aria-busy=\"true\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-messages' | translate | async\"\n >\n <div class=\"messages-skeleton\" aria-hidden=\"true\">\n @for (item of loadingSkeletonItems; track item) {\n <div class=\"message-skeleton\" [class.message-skeleton--own]=\"$odd\">\n @if ($even && isGroupConversation()) {\n <ax-skeleton class=\"message-skeleton-avatar\" [animated]=\"true\"></ax-skeleton>\n }\n <ax-skeleton\n class=\"message-skeleton-bubble\"\n [class.message-skeleton-bubble--short]=\"$index % 3 === 1\"\n [class.message-skeleton-bubble--medium]=\"$index % 3 === 2\"\n [animated]=\"true\"\n ></ax-skeleton>\n </div>\n }\n </div>\n </div>\n } @else if (messages().length === 0) {\n <div class=\"list-empty\" role=\"status\" [attr.aria-label]=\"'@acorex:chat.status.no-messages' | translate | async\">\n <ng-content select=\"ax-conversation-message-list-empty, [ax-conversation-message-list-empty]\">\n <ng-container\n *ngComponentOutlet=\"resolvedEmptyStateComponent(); inputs: { conversation: activeConversation()! }\"\n ></ng-container>\n </ng-content>\n </div>\n } @else {\n <div\n class=\"messages-container\"\n (scroll)=\"onScroll($event)\"\n axInfiniteScroll\n [threshold]=\"config.infiniteScrollThreshold\"\n [edge]=\"'top'\"\n [scrollDisabled]=\"loading() || loadingMore() || !hasMoreMessages()\"\n (scrollThreshold)=\"onScrollThreshold($event)\"\n #messagesContainer\n role=\"feed\"\n [attr.aria-label]=\"'@acorex:chat.aria.messages' | translate | async\"\n >\n @if (loadingMore()) {\n <div\n class=\"list-loading-more list-loading-more--prepend\"\n role=\"status\"\n animate.enter=\"load-more-enter\"\n animate.leave=\"load-more-leave\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-older-messages' | translate | async\"\n >\n <div class=\"load-more-indicator\" aria-hidden=\"true\">\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n </div>\n <ax-label class=\"load-more-label\">{{\n '@acorex:chat.status.loading-older-messages' | translate | async\n }}</ax-label>\n </div>\n }\n @for (group of messageGroups(); track trackMessageGroup($index, group)) {\n <!-- Date Separator -->\n <div class=\"date-separator\" role=\"separator\" [attr.aria-label]=\"getDateSeparatorAriaLabel(group.dateLabel)\">\n <span class=\"date-separator__label\">{{ group.dateLabel }}</span>\n </div>\n\n <!-- Messages in this date group -->\n @for (message of group.messages; track trackMessage($index, message)) {\n <div\n [class]=\"getMessageClasses(message)\"\n role=\"article\"\n [attr.aria-label]=\"getMessageAriaLabel(message)\"\n [id]=\"'message-' + message.id\"\n >\n <!-- Avatar (only for group conversations and received messages) -->\n @if (shouldShowAvatar(message)) {\n <div class=\"message-avatar\">\n <ax-conversation-avatar\n kind=\"user\"\n [userId]=\"message.senderId\"\n [conversation]=\"activeConversation()\"\n [message]=\"message\"\n [size]=\"32\"\n />\n </div>\n }\n\n <div class=\"message-content-row\" [class.message-content-row-own]=\"isOwnMessage(message)\">\n @if (messageSupportsReactions(message)) {\n <button\n type=\"button\"\n class=\"add-reaction-button add-reaction-outside\"\n [class.add-reaction-visible]=\"reactionPickerTarget() === message.id\"\n (click)=\"toggleReactionPicker(message, $event)\"\n [attr.aria-label]=\"'@acorex:chat.actions.add-reaction' | translate | async\"\n #reactionButton\n >\n <i class=\"fa-light fa-face-smile\"></i>\n </button>\n }\n\n <div\n class=\"message-bubble-container\"\n [id]=\"'message-bubble-' + message.id\"\n [attr.data-message-id]=\"message.id\"\n >\n <div\n [class]=\"getBubbleClasses(message)\"\n [class.message-bubble-sent]=\"message.senderId === currentUser()?.id\"\n [class.message-bubble-received]=\"message.senderId !== currentUser()?.id\"\n >\n <!-- Sender name (only for group conversations and received messages) -->\n @if (shouldShowSenderName(message)) {\n <div class=\"message-sender\">{{ getSenderName(message) }}:</div>\n }\n\n <!-- Reply Preview -->\n @if (message.replyTo) {\n <div\n class=\"reply-preview\"\n (click)=\"scrollToMessage(message.replyTo.id)\"\n role=\"button\"\n [attr.aria-label]=\"'Reply to ' + getSenderName(message.replyTo)\"\n (keydown.enter)=\"scrollToMessage(message.replyTo.id)\"\n (keydown.space)=\"scrollToMessage(message.replyTo.id)\"\n >\n <div class=\"reply-preview-content\">\n <div class=\"reply-preview-sender\">{{ getSenderName(message.replyTo) }}</div>\n <div class=\"reply-preview-text\">\n @if (getMessagePreviewText(message.replyTo); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i\n >{{ '@acorex:chat.' + preview.type | translate | async }}\n } @else {\n {{ preview.value }}\n }\n </span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Forwarded Indicator -->\n @if (message.forwarded) {\n <div class=\"forwarded-preview\">\n <i class=\"fa-solid fa-share\"></i>\n <span class=\"forwarded-text\">{{ getForwardedText(message) }}</span>\n </div>\n }\n\n <ax-conversation-registry-component-outlet\n [component]=\"getRendererComponent(message)\"\n [componentLoader]=\"getRendererComponentLoader(message)\"\n [inputs]=\"getRendererInputs(message)\"\n />\n\n @if (messageSupportsReactions(message) && message.reactions.length > 0) {\n <div class=\"message-reactions-container\">\n <div class=\"message-reactions-bubbles\">\n @for (reaction of getGroupedReactions(message); track reaction.emoji) {\n <button\n type=\"button\"\n class=\"reaction-bubble\"\n [class.reaction-bubble-active]=\"reaction.hasReacted\"\n (click)=\"onReactionClick(message, reaction.emoji)\"\n [attr.aria-label]=\"reaction.emoji + ' ' + reaction.count\"\n >\n <span class=\"reaction-emoji\">{{ reaction.emoji }}</span>\n @if (reaction.count > 1) {\n <span class=\"reaction-count\">{{ reaction.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Message Footer -->\n <div class=\"message-footer\">\n @let replyCount = getReplyCount(message);\n @let forwardCount = getForwardCount(message);\n @if (replyCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"replyCount + ' replies'\">\n <i class=\"fa-solid fa-message\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ replyCount }}</span>\n </span>\n }\n @if (forwardCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"forwardCount + ' forwards'\">\n <i class=\"fa-solid fa-share\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ forwardCount }}</span>\n </span>\n }\n @if (replyCount > 0 || forwardCount > 0) {\n <span class=\"message-footer-split\" aria-hidden=\"true\"></span>\n }\n <span class=\"message-time\">{{ message.timestamp | format: 'timeleft' | async }}</span>\n @if (message.editedAt) {\n <span class=\"edited-indicator\">\n <span>{{ '@acorex:chat.status.edited' | translate | async }}</span>\n </span>\n }\n @if (isOwnMessage(message)) {\n <span [class]=\"getStatusIconClasses(message)\">\n <ax-icon><i [class]=\"getStatusIcon(message)\"></i></ax-icon>\n </span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Message Actions -->\n <ax-context-menu\n [target]=\"'#message-bubble-' + message.id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleMessageContextMenuOpening($event, message)\"\n (onClose)=\"contextMenuMessageId.set(null)\"\n (onItemClick)=\"handleMessageContextMenuItemClick($event, message)\"\n >\n </ax-context-menu>\n </div>\n }\n }\n </div>\n\n <!-- Scroll to Bottom Button -->\n @if (showScrollButton()) {\n <div\n class=\"scroll-to-bottom-wrapper\"\n animate.enter=\"scroll-to-bottom-enter\"\n animate.leave=\"scroll-to-bottom-leave\"\n >\n <ax-fab\n class=\"scroll-to-bottom\"\n (onClick)=\"scrollToBottom()\"\n [attr.aria-label]=\"'@acorex:chat.actions.scroll-to-bottom' | translate | async\"\n >\n <ax-icon><i class=\"fa-light fa-arrow-down\" aria-hidden=\"true\"></i></ax-icon>\n </ax-fab>\n </div>\n }\n }\n </div>\n }\n\n <!-- Reaction Picker Popover -->\n @if (reactionsEnabled() && reactionPickerTarget()) {\n <ax-popover\n #reactionPopover\n [target]=\"reactionPickerElement()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"reactionPickerPlacement()\"\n (onClose)=\"closeReactionPicker()\"\n >\n <div class=\"reaction-picker-popup\">\n <div class=\"reaction-picker-header\">\n <span class=\"picker-title\">{{ '@acorex:chat.actions.react' | translate | async }}</span>\n <button\n type=\"button\"\n class=\"picker-close\"\n (click)=\"closeReactionPicker()\"\n [attr.aria-label]=\"'@acorex:chat.actions.close' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n <div\n class=\"reaction-picker-emojis\"\n role=\"listbox\"\n [attr.aria-label]=\"'@acorex:chat.actions.choose-reaction' | translate | async\"\n >\n @for (emoji of availableReactions(); track emoji) {\n <button\n type=\"button\"\n class=\"reaction-picker-emoji\"\n [class.reaction-picker-emoji-active]=\"hasUserReactedById(reactionPickerTarget()!, emoji)\"\n (click)=\"onReactionClickById(reactionPickerTarget()!, emoji); closeReactionPicker()\"\n [attr.aria-label]=\"emoji\"\n >\n {{ emoji }}\n </button>\n }\n </div>\n </div>\n </ax-popover>\n }\n} @else {\n <div\n class=\"message-list message-list--no-active\"\n role=\"region\"\n [attr.aria-label]=\"'@acorex:chat.status.no-conversation-selected' | translate | async\"\n >\n <div class=\"list-no-active\">\n <ng-content select=\"ax-conversation-message-list-no-active, [ax-conversation-message-list-no-active]\">\n <ng-container *ngComponentOutlet=\"noActiveFallbackComponent\"></ng-container>\n </ng-content>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-message-list{position:relative;display:block;height:100%;container-type:inline-size;@keyframes axConversationSurfaceIn{0%{opacity:0}to{opacity:1}}@keyframes axConversationSurfaceInReduced{0%{opacity:.92}to{opacity:1}}@keyframes messagesSkeletonIn{0%{opacity:0;transform:translateY(.75rem)}to{opacity:1;transform:translateY(0)}}@keyframes messagesSkeletonInReduced{0%{opacity:.85}to{opacity:1}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes axChatLoadMoreDot{0%,70%,to{transform:translateY(0) scale(1);opacity:.4}35%{transform:translateY(-.28rem) scale(1.08);opacity:1}}@keyframes axChatLoadMoreEnterPrepend{0%{opacity:0;transform:translateY(-.5rem)}to{opacity:1;transform:translateY(0)}}@keyframes axChatLoadMoreLeavePrepend{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-.35rem)}}@keyframes axScrollToBottomEnter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes axScrollToBottomLeave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}}ax-conversation-message-list .message-list{position:relative;display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden}ax-conversation-message-list .message-list.ax-drop-zone>.ax-uploader-overlay-state{display:none!important}ax-conversation-message-list .message-list--drag{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:rgba(var(--ax-sys-color-primary-surface));--tw-outline-style: dashed;outline-style:dashed;outline-offset:-2px}ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceIn .36s cubic-bezier(.22,1,.36,1) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceInReduced .18s ease both}}ax-conversation-message-list .list-loading{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;justify-content:flex-end;overflow:hidden}ax-conversation-message-list .messages-skeleton{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 6);animation:messagesSkeletonIn .42s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .message-skeleton{display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-message-list .message-skeleton--own{flex-direction:row-reverse}ax-conversation-message-list .message-skeleton-avatar{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);flex-shrink:0;border-radius:calc(infinity * 1px)}ax-conversation-message-list .message-skeleton-bubble{height:calc(var(--spacing, .25rem) * 10);border-radius:var(--radius-2xl, 1rem);width:min(62%,17.5rem)}ax-conversation-message-list .message-skeleton-bubble--short{height:calc(var(--spacing, .25rem) * 8);width:min(36%,9.5rem)}ax-conversation-message-list .message-skeleton-bubble--medium{height:calc(var(--spacing, .25rem) * 9);width:min(48%,13rem)}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .messages-skeleton{animation:messagesSkeletonInReduced .2s ease both}}ax-conversation-message-list .list-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 5);padding-inline:calc(var(--spacing, .25rem) * 8);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center;animation:fadeInUp .5s ease-out}ax-conversation-message-list .message-list--no-active{height:100%}ax-conversation-message-list .list-no-active{display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 48);flex-direction:column;align-items:center;justify-content:center}ax-conversation-message-list .empty-icon{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:5.5rem;--tw-leading: 1;line-height:1;opacity:35%;filter:grayscale(.2)}ax-conversation-message-list .empty-title{margin:calc(var(--spacing, .25rem) * 0);font-size:1.625rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-tight, -.025em);letter-spacing:var(--tracking-tight, -.025em);color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-message-list .empty-description{margin:calc(var(--spacing, .25rem) * 0);max-width:420px;font-size:1.0625rem;--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgba(var(--ax-sys-color-on-surface));opacity:.65}ax-conversation-message-list .spinner{margin-bottom:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:3px;border-color:rgba(var(--ax-sys-color-border-light-surface));border-top-color:rgb(var(--ax-sys-color-primary-500));animation:spin .8s linear infinite}ax-conversation-message-list .list-loading-more{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);padding-bottom:calc(var(--spacing, .25rem) * 2);text-align:center;color:rgba(var(--ax-sys-color-on-surface));opacity:85%}ax-conversation-message-list .load-more-indicator{display:flex;min-height:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;gap:.3rem}ax-conversation-message-list .load-more-dot{height:.4rem;width:.4rem;border-radius:calc(infinity * 1px);background-color:rgba(var(--ax-sys-color-primary-500));animation:axChatLoadMoreDot 1s ease-in-out infinite}ax-conversation-message-list .load-more-dot:nth-child(2){animation-delay:.14s}ax-conversation-message-list .load-more-dot:nth-child(3){animation-delay:.28s}ax-conversation-message-list .load-more-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%}ax-conversation-message-list .load-more-enter{animation:axChatLoadMoreEnterPrepend .32s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .load-more-leave{animation:axChatLoadMoreLeavePrepend .22s ease both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .load-more-dot{animation:none;opacity:.65}ax-conversation-message-list .load-more-enter,ax-conversation-message-list .load-more-leave{animation:none}}ax-conversation-message-list .messages-container{position:relative;min-height:calc(var(--spacing, .25rem) * 0);width:100%;flex:1;overflow-x:hidden;overflow-y:auto}ax-conversation-message-list .date-separator{pointer-events:none;position:sticky;z-index:150;display:flex;align-items:center;justify-content:center;top:.5rem;padding:.375rem 1rem .625rem;margin-block:.125rem .375rem}ax-conversation-message-list .date-separator__label{pointer-events:auto;display:inline-flex;width:calc(var(--spacing, .25rem) * 32);max-width:min(100%,18rem);align-items:center;justify-content:center;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1);text-align:center;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);white-space:nowrap;-webkit-user-select:none;user-select:none;color:rgba(var(--ax-sys-color-on-lightest-surface));background:rgba(var(--ax-sys-color-lightest-surface));border:1px solid rgba(var(--ax-sys-color-on-lightest-surface),.25)}ax-conversation-message-list .unread-separator{margin-block:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4)}ax-conversation-message-list .unread-separator-line{height:1px;flex:1;background-color:rgba(var(--ax-sys-color-primary-surface));opacity:30%}ax-conversation-message-list .unread-separator-text{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}ax-conversation-message-list .message-item{position:relative;display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 2);--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);transition:background-color .3s ease}ax-conversation-message-list .message-item-context-active{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.09);box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.22)}ax-conversation-message-list .message-own.message-item-context-active{background-color:rgba(var(--ax-sys-color-primary-500),.12)}ax-conversation-message-list .message-highlight{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-message-list .message-item.message-own{flex-direction:row-reverse}ax-conversation-message-list .message-avatar{flex-shrink:0}ax-conversation-message-list .message-avatar-icon{display:flex;height:100%;width:100%;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1}ax-conversation-message-list .message-content-row{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:0 1 auto;flex-direction:row;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 1);max-width:min(95%,50rem)}@container (min-width: 768px){ax-conversation-message-list .message-content-row{max-width:min(70%,50rem)}}ax-conversation-message-list .message-content-row-own{justify-content:flex-end}ax-conversation-message-list .message-item:not(.message-own) .message-content-row{justify-content:flex-start}ax-conversation-message-list .message-bubble-container{position:relative;display:flex;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex:1 1 auto;flex-direction:column}ax-conversation-message-list .message-own .message-bubble-container{align-items:flex-end}ax-conversation-message-list .message-sender{margin-bottom:.1rem;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-bubble{position:relative;display:flex;max-width:100%;flex-direction:column;border-radius:var(--radius-2xl, 1rem);background-color:rgba(var(--ax-sys-color-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);padding-bottom:.1rem;overflow-wrap:break-word;transition:background-color .3s ease}ax-conversation-message-list .reply-preview{margin-bottom:calc(var(--spacing, .25rem) * 2);cursor:pointer;border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .reply-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .reply-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .reply-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .reply-preview-line{width:3px;flex-shrink:0;border-radius:1.5px;background:currentColor;opacity:.5}ax-conversation-message-list .reply-preview-content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-message-list .reply-preview-sender{margin-bottom:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .reply-preview-text{overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .reply-preview-sender{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .reply-preview-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .last-message{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .forwarded-preview{margin-bottom:.1rem;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .forwarded-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .forwarded-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .forwarded-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .forwarded-preview i{flex-shrink:0;font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .forwarded-text{min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .forwarded-preview i{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .forwarded-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .message-bubble-received{border-end-start-radius:.125rem}ax-conversation-message-list .message-bubble-received:before,ax-conversation-message-list .message-bubble-sent:after{content:\"\";display:block;position:absolute;bottom:0;width:.8rem;height:.8rem;pointer-events:none;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;mask-mode:alpha}ax-conversation-message-list .message-bubble-received:before{background-color:rgba(var(--ax-sys-color-lightest-surface));inset-inline-start:-.7rem;-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list .message-bubble-sent{border-end-end-radius:.125rem}ax-conversation-message-list .message-bubble-sent:after{background:rgb(var(--ax-sys-color-primary-surface));inset-inline-end:-.7rem;-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}[dir=rtl] ax-conversation-message-list .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list:dir(rtl) .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list:dir(rtl) .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}[dir=ltr] ax-conversation-message-list .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}[dir=ltr] ax-conversation-message-list .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list .message-own .message-bubble{background:rgb(var(--ax-sys-color-primary-surface));color:rgb(var(--ax-sys-color-on-primary-surface))}ax-conversation-message-list .message-bubble.message-system{background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);max-width:100%}ax-conversation-message-list .message-bubble.message-system:before,ax-conversation-message-list .message-bubble.message-system:after{display:none}ax-conversation-message-list .message-item:has(.message-system){justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .message-item:has(.message-system) .message-content-row{max-width:100%;justify-content:center}ax-conversation-message-list .message-item:has(.message-system) .message-bubble-container{align-items:center}ax-conversation-message-list .message-content{font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);white-space:pre-wrap}ax-conversation-message-list ax-conversation-registry-component-outlet{display:block;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0)}ax-conversation-message-list .message-footer{margin-top:.1rem;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 1);padding-inline-start:calc(var(--spacing, .25rem) * 1);font-size:.6875rem;--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%;-webkit-user-select:none;user-select:none}ax-conversation-message-list .message-footer-count{display:inline-flex;align-items:center;gap:.2rem;font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .message-footer-count i{font-size:.625rem;opacity:90%}ax-conversation-message-list .message-footer-count-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-footer-split{margin-inline:.2rem;height:.65rem;width:1px;flex-shrink:0;align-self:center;background-color:rgba(var(--ax-sys-color-border-light-surface));opacity:90%}ax-conversation-message-list .message-time{font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .edited-indicator{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1);border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline-start:.35rem;font-size:.675rem;opacity:75%}ax-conversation-message-list .status-icon{display:inline-flex;align-items:center}ax-conversation-message-list .status-icon i{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}ax-conversation-message-list .status-read{color:rgba(var(--ax-sys-color-primary-200))}ax-conversation-message-list .status-failed{color:rgba(var(--ax-sys-color-danger-200))}ax-conversation-message-list .message-reactions-bubbles{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem}ax-conversation-message-list .reaction-bubble{margin:calc(var(--spacing, .25rem) * 0);display:inline-flex;min-height:1.375rem;cursor:pointer;align-items:center;justify-content:center;gap:.15rem;border-radius:var(--radius-xl, .75rem);padding-inline:.35rem;padding-block:.1rem;color:rgba(var(--ax-sys-color-on-surface));--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);background:rgba(var(--ax-sys-color-on-surface),.06);border:1px solid rgba(var(--ax-sys-color-on-surface),.1);transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}ax-conversation-message-list .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-surface),.1);border-color:rgba(var(--ax-sys-color-on-surface),.18)}ax-conversation-message-list .reaction-bubble-active{background:rgba(var(--ax-sys-color-primary-500),.12);border-color:rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-message-list .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-primary-500),.18);border-color:rgba(var(--ax-sys-color-primary-500),.55)}ax-conversation-message-list .reaction-emoji{display:inline-block;font-size:.8125rem;--tw-leading: 1;line-height:1}ax-conversation-message-list .reaction-count{font-size:.6875rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:.65}ax-conversation-message-list .reaction-bubble-active .reaction-count{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600));opacity:95%}ax-conversation-message-list .message-own .reaction-bubble{color:rgba(var(--ax-sys-color-on-primary-surface));background:rgba(var(--ax-sys-color-on-primary-surface),.12);border-color:rgba(var(--ax-sys-color-on-primary-surface),.2)}ax-conversation-message-list .message-own .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.2);border-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .reaction-bubble-active{background:rgba(var(--ax-sys-color-on-primary-surface),.28);border-color:rgba(var(--ax-sys-color-on-primary-surface),.5)}ax-conversation-message-list .message-own .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.34);border-color:rgba(var(--ax-sys-color-on-primary-surface),.6)}ax-conversation-message-list .message-own .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:80%}ax-conversation-message-list .message-own .reaction-bubble-active .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:100%}ax-conversation-message-list .message-reactions-container{margin-top:calc(var(--spacing, .25rem) * 1);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:.2rem}ax-conversation-message-list .message-own .message-reactions-container{justify-content:flex-end}ax-conversation-message-list .message-own .message-footer .edited-indicator{border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .message-footer .message-footer-split{background:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .add-reaction-button.add-reaction-outside{position:absolute;top:50%;margin:calc(var(--spacing, .25rem) * 0);box-sizing:border-box;display:none;height:1.8rem;width:1.8rem;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 0);inset-inline-end:-2.25rem;box-shadow:0 1px 2px #0000000f}ax-conversation-message-list .add-reaction-button{padding-inline-start:.05rem}ax-conversation-message-list .message-content-row-own .add-reaction-button.add-reaction-outside{inset-inline-start:-2.25rem;inset-inline-end:auto}ax-conversation-message-list .message-item:hover .add-reaction-button.add-reaction-outside,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{display:inline-flex}ax-conversation-message-list .add-reaction-button.add-reaction-outside:hover,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .add-reaction-button.add-reaction-outside i{font-size:.9rem;color:rgba(var(--ax-sys-color-on-surface));opacity:80%}ax-conversation-message-list .reaction-bubble:focus-visible,ax-conversation-message-list .add-reaction-button:focus-visible,ax-conversation-message-list .action-trigger:focus-visible,ax-conversation-message-list ax-fab.scroll-to-bottom ax-button:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .message-actions{z-index:10;padding-bottom:calc(var(--spacing, .25rem) * 6);opacity:0%;transition:opacity var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .message-item:hover .message-actions{opacity:100%}ax-conversation-message-list .action-trigger{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .action-trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-message-list .shortcut{font-size:.6875rem;opacity:70%}ax-conversation-message-list .scroll-to-bottom-wrapper{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * 4);bottom:calc(var(--spacing, .25rem) * 4);z-index:999}ax-conversation-message-list ax-fab.scroll-to-bottom ax-button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none}ax-conversation-message-list .scroll-to-bottom-enter{animation:axScrollToBottomEnter var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}ax-conversation-message-list .scroll-to-bottom-leave{animation:axScrollToBottomLeave var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .scroll-to-bottom-enter,ax-conversation-message-list .scroll-to-bottom-leave{animation:none}}.reaction-picker-popup{width:max-content;min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;border-radius:.65rem;background-color:rgba(var(--ax-sys-color-lightest-surface));max-width:min(260px,92vw)}.reaction-picker-header{display:flex;min-height:calc(var(--spacing, .25rem) * 0);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:.45rem;padding-inline-start:.7rem;padding-inline-end:calc(var(--spacing, .25rem) * 2)}.picker-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-on-surface));opacity:85%}.picker-close{display:flex;height:1.6rem;width:1.6rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:.95rem;color:rgba(var(--ax-sys-color-on-surface),.55);transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}.picker-close:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}.picker-close:focus-visible,.reaction-picker-emoji:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}.reaction-picker-emojis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.2rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:.45rem;padding-bottom:calc(var(--spacing, .25rem) * 2)}.reaction-picker-emoji{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);cursor:pointer;border-radius:.45rem;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:1.15rem;--tw-leading: 1;line-height:1;transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.reaction-picker-emoji:hover{background-color:rgba(var(--ax-sys-color-lighter-surface))}.reaction-picker-emoji-active{background-color:rgba(var(--ax-sys-color-surface))}.reaction-picker-emoji-active:hover{background:rgba(var(--ax-sys-color-primary-500),.25)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-outline-style: solid;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
9017
|
+
], template: "@if (activeConversation(); as conv) {\n @for (cid of [conv.id]; track cid) {\n <div\n class=\"message-list message-list--conversation-surface\"\n [class.message-list--drag]=\"messageListDragging()\"\n #messageList\n role=\"log\"\n [attr.aria-label]=\"'@acorex:chat.aria.message-list' | translate | async\"\n aria-live=\"polite\"\n [style.background]=\"messageListBackgroundStyle()\"\n [style.--ax-comp-message-list-surface-bg]=\"messageListBackgroundStyle()\"\n axUploaderZone\n [disableBrowse]=\"true\"\n (dragEnter)=\"onMessageListDragEnter()\"\n (dragLeave)=\"onMessageListDragLeave()\"\n (fileChange)=\"onMessageListFilesDropped($event)\"\n >\n @if (loading()) {\n <div\n class=\"list-loading\"\n role=\"status\"\n aria-busy=\"true\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-messages' | translate | async\"\n >\n <div class=\"messages-skeleton\" aria-hidden=\"true\">\n @for (item of loadingSkeletonItems; track item) {\n <div class=\"message-skeleton\" [class.message-skeleton--own]=\"$odd\">\n @if ($even && isGroupConversation()) {\n <ax-skeleton class=\"message-skeleton-avatar\" [animated]=\"true\"></ax-skeleton>\n }\n <ax-skeleton\n class=\"message-skeleton-bubble\"\n [class.message-skeleton-bubble--short]=\"$index % 3 === 1\"\n [class.message-skeleton-bubble--medium]=\"$index % 3 === 2\"\n [animated]=\"true\"\n ></ax-skeleton>\n </div>\n }\n </div>\n </div>\n } @else if (messages().length === 0) {\n <div class=\"list-empty\" role=\"status\" [attr.aria-label]=\"'@acorex:chat.status.no-messages' | translate | async\">\n <ng-content select=\"ax-conversation-message-list-empty, [ax-conversation-message-list-empty]\">\n <ng-container\n *ngComponentOutlet=\"resolvedEmptyStateComponent(); inputs: { conversation: activeConversation()! }\"\n ></ng-container>\n </ng-content>\n </div>\n } @else {\n <div\n class=\"messages-container\"\n (scroll)=\"onScroll($event)\"\n axInfiniteScroll\n [threshold]=\"config.infiniteScrollThreshold\"\n [edge]=\"'top'\"\n [scrollDisabled]=\"loading() || loadingMore() || !hasMoreMessages()\"\n (scrollThreshold)=\"onScrollThreshold($event)\"\n #messagesContainer\n role=\"feed\"\n [attr.aria-label]=\"'@acorex:chat.aria.messages' | translate | async\"\n >\n @if (loadingMore()) {\n <div\n class=\"list-loading-more list-loading-more--prepend\"\n role=\"status\"\n animate.enter=\"load-more-enter\"\n animate.leave=\"load-more-leave\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-older-messages' | translate | async\"\n >\n <div class=\"load-more-indicator\" aria-hidden=\"true\">\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n </div>\n <ax-label class=\"load-more-label\">{{\n '@acorex:chat.status.loading-older-messages' | translate | async\n }}</ax-label>\n </div>\n }\n @for (group of messageGroups(); track trackMessageGroup($index, group)) {\n <!-- Date Separator -->\n <div class=\"date-separator\" role=\"separator\" [attr.aria-label]=\"getDateSeparatorAriaLabel(group.dateLabel)\">\n <span class=\"date-separator__label\">{{ group.dateLabel }}</span>\n </div>\n\n <!-- Messages in this date group -->\n @for (message of group.messages; track trackMessage($index, message)) {\n <div\n [class]=\"getMessageClasses(message)\"\n role=\"article\"\n [attr.aria-label]=\"getMessageAriaLabel(message)\"\n [id]=\"'message-' + message.id\"\n >\n <!-- Avatar (only for group conversations and received messages) -->\n @if (shouldShowAvatar(message)) {\n <div class=\"message-avatar\">\n <ax-conversation-avatar\n kind=\"user\"\n [userId]=\"message.senderId\"\n [conversation]=\"activeConversation()\"\n [message]=\"message\"\n [size]=\"32\"\n />\n </div>\n }\n\n <div class=\"message-content-row\" [class.message-content-row-own]=\"isOwnMessage(message)\">\n @if (messageSupportsReactions(message)) {\n <button\n type=\"button\"\n class=\"add-reaction-button add-reaction-outside\"\n [class.add-reaction-visible]=\"reactionPickerTarget() === message.id\"\n (click)=\"toggleReactionPicker(message, $event)\"\n [attr.aria-label]=\"'@acorex:chat.actions.add-reaction' | translate | async\"\n #reactionButton\n >\n <i class=\"fa-light fa-face-smile\"></i>\n </button>\n }\n\n <div\n class=\"message-bubble-container\"\n [id]=\"'message-bubble-' + message.id\"\n [attr.data-message-id]=\"message.id\"\n >\n <div\n [class]=\"getBubbleClasses(message)\"\n [class.message-bubble-sent]=\"message.senderId === currentUser()?.id\"\n [class.message-bubble-received]=\"message.senderId !== currentUser()?.id\"\n >\n <!-- Sender name (only for group conversations and received messages) -->\n @if (shouldShowSenderName(message)) {\n <div class=\"message-sender\">{{ getSenderName(message) }}:</div>\n }\n\n <!-- Reply Preview -->\n @if (message.replyTo) {\n <div\n class=\"reply-preview\"\n (click)=\"scrollToMessage(message.replyTo.id)\"\n role=\"button\"\n [attr.aria-label]=\"'Reply to ' + getSenderName(message.replyTo)\"\n (keydown.enter)=\"scrollToMessage(message.replyTo.id)\"\n (keydown.space)=\"scrollToMessage(message.replyTo.id)\"\n >\n <div class=\"reply-preview-content\">\n <div class=\"reply-preview-sender\">{{ getSenderName(message.replyTo) }}</div>\n <div class=\"reply-preview-text\">\n @if (getMessagePreviewText(message.replyTo); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i\n >{{ '@acorex:chat.' + preview.type | translate | async }}\n } @else {\n {{ preview.value }}\n }\n </span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Forwarded Indicator -->\n @if (message.forwarded) {\n <div class=\"forwarded-preview\">\n <i class=\"fa-solid fa-share\"></i>\n <span class=\"forwarded-text\">{{ getForwardedText(message) }}</span>\n </div>\n }\n\n <ax-conversation-registry-component-outlet\n [component]=\"getRendererComponent(message)\"\n [componentLoader]=\"getRendererComponentLoader(message)\"\n [inputs]=\"getRendererInputs(message)\"\n />\n\n @if (messageSupportsReactions(message) && message.reactions.length > 0) {\n <div class=\"message-reactions-container\">\n <div class=\"message-reactions-bubbles\">\n @for (reaction of getGroupedReactions(message); track reaction.emoji) {\n <button\n type=\"button\"\n class=\"reaction-bubble\"\n [class.reaction-bubble-active]=\"reaction.hasReacted\"\n (click)=\"onReactionClick(message, reaction.emoji)\"\n [attr.aria-label]=\"reaction.emoji + ' ' + reaction.count\"\n >\n <span class=\"reaction-emoji\">{{ reaction.emoji }}</span>\n @if (reaction.count > 1) {\n <span class=\"reaction-count\">{{ reaction.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Message Footer -->\n <div class=\"message-footer\">\n @let replyCount = getReplyCount(message);\n @let forwardCount = getForwardCount(message);\n @if (replyCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"replyCount + ' replies'\">\n <i class=\"fa-solid fa-message\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ replyCount }}</span>\n </span>\n }\n @if (forwardCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"forwardCount + ' forwards'\">\n <i class=\"fa-solid fa-share\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ forwardCount }}</span>\n </span>\n }\n @if (replyCount > 0 || forwardCount > 0) {\n <span class=\"message-footer-split\" aria-hidden=\"true\"></span>\n }\n <span class=\"message-time\">{{ message.timestamp | format: 'timeleft' | async }}</span>\n @if (message.editedAt) {\n <span class=\"edited-indicator\">\n <span>{{ '@acorex:chat.status.edited' | translate | async }}</span>\n </span>\n }\n @if (isOwnMessage(message)) {\n <span [class]=\"getStatusIconClasses(message)\">\n <ax-icon><i [class]=\"getStatusIcon(message)\"></i></ax-icon>\n </span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Message Actions -->\n <ax-context-menu\n [target]=\"'#message-bubble-' + message.id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleMessageContextMenuOpening($event, message)\"\n (onClose)=\"contextMenuMessageId.set(null)\"\n (onItemClick)=\"handleMessageContextMenuItemClick($event, message)\"\n >\n </ax-context-menu>\n </div>\n }\n }\n </div>\n\n <!-- Scroll to Bottom Button -->\n @if (showScrollButton()) {\n <div\n class=\"scroll-to-bottom-wrapper\"\n animate.enter=\"scroll-to-bottom-enter\"\n animate.leave=\"scroll-to-bottom-leave\"\n >\n <ax-fab\n class=\"scroll-to-bottom\"\n (onClick)=\"scrollToBottom()\"\n [attr.aria-label]=\"'@acorex:chat.actions.scroll-to-bottom' | translate | async\"\n >\n <ax-icon><i class=\"fa-light fa-arrow-down\" aria-hidden=\"true\"></i></ax-icon>\n </ax-fab>\n </div>\n }\n }\n </div>\n }\n\n <!-- Reaction Picker Popover -->\n @if (reactionsEnabled() && reactionPickerTarget()) {\n <ax-popover\n #reactionPopover\n [target]=\"reactionPickerElement()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"reactionPickerPlacement()\"\n (onClose)=\"closeReactionPicker()\"\n >\n <div class=\"reaction-picker-popup\">\n <div class=\"reaction-picker-header\">\n <span class=\"picker-title\">{{ '@acorex:chat.actions.react' | translate | async }}</span>\n <button\n type=\"button\"\n class=\"picker-close\"\n (click)=\"closeReactionPicker()\"\n [attr.aria-label]=\"'@acorex:chat.actions.close' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n <div\n class=\"reaction-picker-emojis\"\n role=\"listbox\"\n [attr.aria-label]=\"'@acorex:chat.actions.choose-reaction' | translate | async\"\n >\n @for (emoji of availableReactions(); track emoji) {\n <button\n type=\"button\"\n class=\"reaction-picker-emoji\"\n [class.reaction-picker-emoji-active]=\"hasUserReactedById(reactionPickerTarget()!, emoji)\"\n (click)=\"onReactionClickById(reactionPickerTarget()!, emoji); closeReactionPicker()\"\n [attr.aria-label]=\"emoji\"\n >\n {{ emoji }}\n </button>\n }\n </div>\n </div>\n </ax-popover>\n }\n} @else {\n <div\n class=\"message-list message-list--no-active\"\n role=\"region\"\n [attr.aria-label]=\"'@acorex:chat.status.no-conversation-selected' | translate | async\"\n >\n <div class=\"list-no-active\">\n <ng-content select=\"ax-conversation-message-list-no-active, [ax-conversation-message-list-no-active]\">\n <ng-container *ngComponentOutlet=\"noActiveFallbackComponent\"></ng-container>\n </ng-content>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-message-list{position:relative;display:block;height:100%;container-type:inline-size;--ax-comp-message-bubble-tail-height: 1.5625rem;--ax-comp-message-bubble-tail-fill-width: 1.25rem;--ax-comp-message-bubble-tail-fill-offset: -.4375rem;--ax-comp-message-bubble-tail-cutout-width: 1.625rem;--ax-comp-message-bubble-tail-cutout-offset: -1.625rem;--ax-comp-message-bubble-tail-curve: 1rem 0rem;--ax-comp-message-bubble-tail-cutout-curve: .625rem;@keyframes axConversationSurfaceIn{0%{opacity:0}to{opacity:1}}@keyframes axConversationSurfaceInReduced{0%{opacity:.92}to{opacity:1}}@keyframes messagesSkeletonIn{0%{opacity:0;transform:translateY(.75rem)}to{opacity:1;transform:translateY(0)}}@keyframes messagesSkeletonInReduced{0%{opacity:.85}to{opacity:1}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes axChatLoadMoreDot{0%,70%,to{transform:translateY(0) scale(1);opacity:.4}35%{transform:translateY(-.28rem) scale(1.08);opacity:1}}@keyframes axChatLoadMoreEnterPrepend{0%{opacity:0;transform:translateY(-.5rem)}to{opacity:1;transform:translateY(0)}}@keyframes axChatLoadMoreLeavePrepend{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-.35rem)}}@keyframes axScrollToBottomEnter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes axScrollToBottomLeave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}}ax-conversation-message-list .message-list{position:relative;display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden}ax-conversation-message-list .message-list.ax-drop-zone>.ax-uploader-overlay-state{display:none!important}ax-conversation-message-list .message-list--drag{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:rgba(var(--ax-sys-color-primary-surface));--tw-outline-style: dashed;outline-style:dashed;outline-offset:-2px}ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceIn .36s cubic-bezier(.22,1,.36,1) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceInReduced .18s ease both}}ax-conversation-message-list .list-loading{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;justify-content:flex-end;overflow:hidden}ax-conversation-message-list .messages-skeleton{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 6);animation:messagesSkeletonIn .42s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .message-skeleton{display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-message-list .message-skeleton--own{flex-direction:row-reverse}ax-conversation-message-list .message-skeleton-avatar{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);flex-shrink:0;border-radius:calc(infinity * 1px)}ax-conversation-message-list .message-skeleton-bubble{height:calc(var(--spacing, .25rem) * 10);border-radius:var(--radius-2xl, 1rem);width:min(62%,17.5rem)}ax-conversation-message-list .message-skeleton-bubble--short{height:calc(var(--spacing, .25rem) * 8);width:min(36%,9.5rem)}ax-conversation-message-list .message-skeleton-bubble--medium{height:calc(var(--spacing, .25rem) * 9);width:min(48%,13rem)}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .messages-skeleton{animation:messagesSkeletonInReduced .2s ease both}}ax-conversation-message-list .list-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 5);padding-inline:calc(var(--spacing, .25rem) * 8);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center;animation:fadeInUp .5s ease-out}ax-conversation-message-list .message-list--no-active{height:100%}ax-conversation-message-list .list-no-active{display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 48);flex-direction:column;align-items:center;justify-content:center}ax-conversation-message-list .empty-icon{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:5.5rem;--tw-leading: 1;line-height:1;opacity:35%;filter:grayscale(.2)}ax-conversation-message-list .empty-title{margin:calc(var(--spacing, .25rem) * 0);font-size:1.625rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-tight, -.025em);letter-spacing:var(--tracking-tight, -.025em);color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-message-list .empty-description{margin:calc(var(--spacing, .25rem) * 0);max-width:420px;font-size:1.0625rem;--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgba(var(--ax-sys-color-on-surface));opacity:.65}ax-conversation-message-list .spinner{margin-bottom:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:3px;border-color:rgba(var(--ax-sys-color-border-light-surface));border-top-color:rgb(var(--ax-sys-color-primary-500));animation:spin .8s linear infinite}ax-conversation-message-list .list-loading-more{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);padding-bottom:calc(var(--spacing, .25rem) * 2);text-align:center;color:rgba(var(--ax-sys-color-on-surface));opacity:85%}ax-conversation-message-list .load-more-indicator{display:flex;min-height:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;gap:.3rem}ax-conversation-message-list .load-more-dot{height:.4rem;width:.4rem;border-radius:calc(infinity * 1px);background-color:rgba(var(--ax-sys-color-primary-500));animation:axChatLoadMoreDot 1s ease-in-out infinite}ax-conversation-message-list .load-more-dot:nth-child(2){animation-delay:.14s}ax-conversation-message-list .load-more-dot:nth-child(3){animation-delay:.28s}ax-conversation-message-list .load-more-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%}ax-conversation-message-list .load-more-enter{animation:axChatLoadMoreEnterPrepend .32s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .load-more-leave{animation:axChatLoadMoreLeavePrepend .22s ease both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .load-more-dot{animation:none;opacity:.65}ax-conversation-message-list .load-more-enter,ax-conversation-message-list .load-more-leave{animation:none}}ax-conversation-message-list .messages-container{position:relative;min-height:calc(var(--spacing, .25rem) * 0);width:100%;flex:1;overflow-y:auto;overflow-x:visible}ax-conversation-message-list .date-separator{pointer-events:none;position:sticky;z-index:150;display:flex;align-items:center;justify-content:center;top:.5rem;padding:.375rem 1rem .625rem;margin-block:.125rem .375rem}ax-conversation-message-list .date-separator__label{pointer-events:auto;display:inline-flex;width:calc(var(--spacing, .25rem) * 32);max-width:min(100%,18rem);align-items:center;justify-content:center;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1);text-align:center;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);white-space:nowrap;-webkit-user-select:none;user-select:none;color:rgba(var(--ax-sys-color-on-lightest-surface));background:rgba(var(--ax-sys-color-lightest-surface));border:1px solid rgba(var(--ax-sys-color-on-lightest-surface),.25)}ax-conversation-message-list .unread-separator{margin-block:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4)}ax-conversation-message-list .unread-separator-line{height:1px;flex:1;background-color:rgba(var(--ax-sys-color-primary-surface));opacity:30%}ax-conversation-message-list .unread-separator-text{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}ax-conversation-message-list .message-item{position:relative;display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);padding-inline:1.75rem;transition:background-color .3s ease}ax-conversation-message-list .message-item-context-active{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.09);box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.22)}ax-conversation-message-list .message-own.message-item-context-active{background-color:rgba(var(--ax-sys-color-primary-500),.12)}ax-conversation-message-list .message-highlight{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-message-list .message-item.message-own{flex-direction:row-reverse}ax-conversation-message-list .message-avatar{z-index:5;flex-shrink:0}ax-conversation-message-list .message-avatar-icon{display:flex;height:100%;width:100%;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1}ax-conversation-message-list .message-content-row{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:0 1 auto;flex-direction:row;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 1);max-width:min(95%,50rem)}@container (min-width: 768px){ax-conversation-message-list .message-content-row{max-width:min(70%,50rem)}}ax-conversation-message-list .message-content-row-own{justify-content:flex-end}ax-conversation-message-list .message-item:not(.message-own) .message-content-row{justify-content:flex-start}ax-conversation-message-list .message-bubble-container{position:relative;display:flex;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex:1 1 auto;flex-direction:column}ax-conversation-message-list .message-own .message-bubble-container{align-items:flex-end}ax-conversation-message-list .message-sender{margin-bottom:.1rem;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-bubble{position:relative;display:flex;max-width:100%;flex-direction:column;border-radius:var(--radius-2xl, 1rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);padding-bottom:.1rem;overflow-wrap:break-word;transition:background-color .3s ease}ax-conversation-message-list .message-bubble>*{position:relative;z-index:1}ax-conversation-message-list .reply-preview{margin-bottom:calc(var(--spacing, .25rem) * 2);cursor:pointer;border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .reply-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .reply-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .reply-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .reply-preview-line{width:3px;flex-shrink:0;border-radius:1.5px;background:currentColor;opacity:.5}ax-conversation-message-list .reply-preview-content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-message-list .reply-preview-sender{margin-bottom:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .reply-preview-text{overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .reply-preview-sender{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .reply-preview-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .last-message{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .forwarded-preview{margin-bottom:.1rem;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .forwarded-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .forwarded-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .forwarded-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .forwarded-preview i{flex-shrink:0;font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .forwarded-text{min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .forwarded-preview i{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .forwarded-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .message-bubble-received:not(.message-system){--ax-comp-message-bubble-bg: rgb(var(--ax-sys-color-lightest-surface));background-color:var(--ax-comp-message-bubble-bg);border-bottom-left-radius:.25rem}ax-conversation-message-list .message-bubble-sent:not(.message-system){--ax-comp-message-bubble-bg: rgb(var(--ax-sys-color-primary-surface));background-color:var(--ax-comp-message-bubble-bg);color:rgb(var(--ax-sys-color-on-primary-surface));border-bottom-right-radius:.25rem}ax-conversation-message-list .message-bubble-received:not(.message-system):before,ax-conversation-message-list .message-bubble-received:not(.message-system):after,ax-conversation-message-list .message-bubble-sent:not(.message-system):before,ax-conversation-message-list .message-bubble-sent:not(.message-system):after{content:\"\";position:absolute;bottom:0;height:var(--ax-comp-message-bubble-tail-height);pointer-events:none;z-index:0}ax-conversation-message-list .message-bubble-received:not(.message-system):before,ax-conversation-message-list .message-bubble-sent:not(.message-system):before{width:var(--ax-comp-message-bubble-tail-fill-width);background-color:var(--ax-comp-message-bubble-bg)}ax-conversation-message-list .message-bubble-received:not(.message-system):after,ax-conversation-message-list .message-bubble-sent:not(.message-system):after{width:var(--ax-comp-message-bubble-tail-cutout-width);background:var(--ax-comp-message-list-surface-bg, rgb(var(--ax-sys-color-primary-lightest-surface)))}ax-conversation-message-list .message-bubble-received:not(.message-system):before{left:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-right-radius:var(--ax-comp-message-bubble-tail-curve)}ax-conversation-message-list .message-bubble-received:not(.message-system):after{left:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-right-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}ax-conversation-message-list .message-bubble-sent:not(.message-system):before{right:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-left-radius:var(--ax-comp-message-bubble-tail-curve)}ax-conversation-message-list .message-bubble-sent:not(.message-system):after{right:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-left-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system){border-bottom-left-radius:1rem;border-bottom-right-radius:.25rem}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system){border-bottom-right-radius:1rem;border-bottom-left-radius:.25rem}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system):before{left:auto;right:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-right-radius:0;border-bottom-left-radius:var(--ax-comp-message-bubble-tail-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system):after{left:auto;right:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-right-radius:0;border-bottom-left-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system):before{right:auto;left:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-left-radius:0;border-bottom-right-radius:var(--ax-comp-message-bubble-tail-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system):after{right:auto;left:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-left-radius:0;border-bottom-right-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}ax-conversation-message-list .message-bubble.message-system:before,ax-conversation-message-list .message-bubble.message-system:after{display:none}ax-conversation-message-list .message-own .message-bubble{color:rgb(var(--ax-sys-color-on-primary-surface))}ax-conversation-message-list .message-bubble.message-system{background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);max-width:100%}ax-conversation-message-list .message-item:has(.message-system){justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .message-item:has(.message-system) .message-content-row{max-width:100%;justify-content:center}ax-conversation-message-list .message-item:has(.message-system) .message-bubble-container{align-items:center}ax-conversation-message-list .message-content{font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);white-space:pre-wrap}ax-conversation-message-list ax-conversation-registry-component-outlet{display:block;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0)}ax-conversation-message-list .message-footer{margin-top:.1rem;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 1);padding-inline-start:calc(var(--spacing, .25rem) * 1);font-size:.6875rem;--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%;-webkit-user-select:none;user-select:none}ax-conversation-message-list .message-footer-count{display:inline-flex;align-items:center;gap:.2rem;font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .message-footer-count i{font-size:.625rem;opacity:90%}ax-conversation-message-list .message-footer-count-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-footer-split{margin-inline:.2rem;height:.65rem;width:1px;flex-shrink:0;align-self:center;background-color:rgba(var(--ax-sys-color-border-light-surface));opacity:90%}ax-conversation-message-list .message-time{font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .edited-indicator{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1);border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline-start:.35rem;font-size:.675rem;opacity:75%}ax-conversation-message-list .status-icon{display:inline-flex;align-items:center}ax-conversation-message-list .status-icon i{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}ax-conversation-message-list .status-read{color:rgba(var(--ax-sys-color-primary-200))}ax-conversation-message-list .status-failed{color:rgba(var(--ax-sys-color-danger-200))}ax-conversation-message-list .message-reactions-bubbles{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem}ax-conversation-message-list .reaction-bubble{margin:calc(var(--spacing, .25rem) * 0);display:inline-flex;min-height:1.375rem;cursor:pointer;align-items:center;justify-content:center;gap:.15rem;border-radius:var(--radius-xl, .75rem);padding-inline:.35rem;padding-block:.1rem;color:rgba(var(--ax-sys-color-on-surface));--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);background:rgba(var(--ax-sys-color-on-surface),.06);border:1px solid rgba(var(--ax-sys-color-on-surface),.1);transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}ax-conversation-message-list .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-surface),.1);border-color:rgba(var(--ax-sys-color-on-surface),.18)}ax-conversation-message-list .reaction-bubble-active{background:rgba(var(--ax-sys-color-primary-500),.12);border-color:rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-message-list .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-primary-500),.18);border-color:rgba(var(--ax-sys-color-primary-500),.55)}ax-conversation-message-list .reaction-emoji{display:inline-block;font-size:.8125rem;--tw-leading: 1;line-height:1}ax-conversation-message-list .reaction-count{font-size:.6875rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:.65}ax-conversation-message-list .reaction-bubble-active .reaction-count{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600));opacity:95%}ax-conversation-message-list .message-own .reaction-bubble{color:rgba(var(--ax-sys-color-on-primary-surface));background:rgba(var(--ax-sys-color-on-primary-surface),.12);border-color:rgba(var(--ax-sys-color-on-primary-surface),.2)}ax-conversation-message-list .message-own .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.2);border-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .reaction-bubble-active{background:rgba(var(--ax-sys-color-on-primary-surface),.28);border-color:rgba(var(--ax-sys-color-on-primary-surface),.5)}ax-conversation-message-list .message-own .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.34);border-color:rgba(var(--ax-sys-color-on-primary-surface),.6)}ax-conversation-message-list .message-own .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:80%}ax-conversation-message-list .message-own .reaction-bubble-active .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:100%}ax-conversation-message-list .message-reactions-container{margin-top:calc(var(--spacing, .25rem) * 1);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:.2rem}ax-conversation-message-list .message-own .message-reactions-container{justify-content:flex-end}ax-conversation-message-list .message-own .message-footer .edited-indicator{border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .message-footer .message-footer-split{background:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .add-reaction-button.add-reaction-outside{position:absolute;top:50%;margin:calc(var(--spacing, .25rem) * 0);box-sizing:border-box;display:none;height:1.8rem;width:1.8rem;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 0);inset-inline-end:-2.25rem;box-shadow:0 1px 2px #0000000f}ax-conversation-message-list .add-reaction-button{padding-inline-start:.05rem}ax-conversation-message-list .message-content-row-own .add-reaction-button.add-reaction-outside{inset-inline-start:-2.25rem;inset-inline-end:auto}ax-conversation-message-list .message-item:hover .add-reaction-button.add-reaction-outside,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{display:inline-flex}ax-conversation-message-list .add-reaction-button.add-reaction-outside:hover,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .add-reaction-button.add-reaction-outside i{font-size:.9rem;color:rgba(var(--ax-sys-color-on-surface));opacity:80%}ax-conversation-message-list .reaction-bubble:focus-visible,ax-conversation-message-list .add-reaction-button:focus-visible,ax-conversation-message-list .action-trigger:focus-visible,ax-conversation-message-list ax-fab.scroll-to-bottom ax-button:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .message-actions{z-index:10;padding-bottom:calc(var(--spacing, .25rem) * 6);opacity:0%;transition:opacity var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .message-item:hover .message-actions{opacity:100%}ax-conversation-message-list .action-trigger{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .action-trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-message-list .shortcut{font-size:.6875rem;opacity:70%}ax-conversation-message-list .scroll-to-bottom-wrapper{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * 4);bottom:calc(var(--spacing, .25rem) * 4);z-index:999}ax-conversation-message-list ax-fab.scroll-to-bottom ax-button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none}ax-conversation-message-list .scroll-to-bottom-enter{animation:axScrollToBottomEnter var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}ax-conversation-message-list .scroll-to-bottom-leave{animation:axScrollToBottomLeave var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .scroll-to-bottom-enter,ax-conversation-message-list .scroll-to-bottom-leave{animation:none}}.reaction-picker-popup{width:max-content;min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;border-radius:.65rem;background-color:rgba(var(--ax-sys-color-lightest-surface));max-width:min(260px,92vw)}.reaction-picker-header{display:flex;min-height:calc(var(--spacing, .25rem) * 0);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:.45rem;padding-inline-start:.7rem;padding-inline-end:calc(var(--spacing, .25rem) * 2)}.picker-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-on-surface));opacity:85%}.picker-close{display:flex;height:1.6rem;width:1.6rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:.95rem;color:rgba(var(--ax-sys-color-on-surface),.55);transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}.picker-close:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}.picker-close:focus-visible,.reaction-picker-emoji:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}.reaction-picker-emojis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.2rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:.45rem;padding-bottom:calc(var(--spacing, .25rem) * 2)}.reaction-picker-emoji{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);cursor:pointer;border-radius:.45rem;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:1.15rem;--tw-leading: 1;line-height:1;transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.reaction-picker-emoji:hover{background-color:rgba(var(--ax-sys-color-lighter-surface))}.reaction-picker-emoji-active{background-color:rgba(var(--ax-sys-color-surface))}.reaction-picker-emoji-active:hover{background:rgba(var(--ax-sys-color-primary-500),.25)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-outline-style: solid;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
8795
9018
|
}], ctorParameters: () => [], propDecorators: { reactionPopover: [{ type: i0.ViewChild, args: ['reactionPopover', { isSignal: true }] }], messageListRef: [{ type: i0.ViewChild, args: ['messageList', { isSignal: true }] }], messagesContainerRef: [{ type: i0.ViewChild, args: ['messagesContainer', { isSignal: true }] }], messageAction: [{ type: i0.Output, args: ["messageAction"] }] } });
|
|
8796
9019
|
|
|
8797
9020
|
/**
|
|
@@ -8888,9 +9111,21 @@ class AXConversationItemComponent {
|
|
|
8888
9111
|
...(ngDevMode ? [{ debugName: "itemClasses" }] : /* istanbul ignore next */ []));
|
|
8889
9112
|
/** Typing indicator text - delegate to utils */
|
|
8890
9113
|
this.typingText = computed(() => {
|
|
8891
|
-
|
|
9114
|
+
this.conversationService.typingRevision();
|
|
9115
|
+
const conv = this.liveConversation();
|
|
9116
|
+
return AXConversationMessageUtilsService.getTypingText(conv, this.conversationService.getActiveTypingUserIds(conv.id));
|
|
8892
9117
|
}, /* @ts-ignore */
|
|
8893
9118
|
...(ngDevMode ? [{ debugName: "typingText" }] : /* istanbul ignore next */ []));
|
|
9119
|
+
this.isTyping = computed(() => {
|
|
9120
|
+
this.conversationService.typingRevision();
|
|
9121
|
+
return this.conversationService.isAnyoneTyping(this.liveConversation().id);
|
|
9122
|
+
}, /* @ts-ignore */
|
|
9123
|
+
...(ngDevMode ? [{ debugName: "isTyping" }] : /* istanbul ignore next */ []));
|
|
9124
|
+
this.roomPreferences = computed(() => {
|
|
9125
|
+
const conv = this.liveConversation();
|
|
9126
|
+
return this.conversationService.getRoomPreferences(conv.id);
|
|
9127
|
+
}, /* @ts-ignore */
|
|
9128
|
+
...(ngDevMode ? [{ debugName: "roomPreferences" }] : /* istanbul ignore next */ []));
|
|
8894
9129
|
/** Last message preview - delegate to utils */
|
|
8895
9130
|
this.lastMessagePreview = computed(() => {
|
|
8896
9131
|
const lastMessage = this.liveConversation().lastMessage;
|
|
@@ -8966,7 +9201,7 @@ class AXConversationItemComponent {
|
|
|
8966
9201
|
}
|
|
8967
9202
|
}
|
|
8968
9203
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8969
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationItemComponent, isStandalone: true, selector: "ax-conversation-item", inputs: { conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: " <div\n [class]=\"itemClasses()\"\n [id]=\"'conversation-item-' + conversation().id\"\n (click)=\"handleClick()\"\n (keydown.enter)=\"handleClick()\"\n (keydown.space)=\"handleClick()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Conversation with ' + conversation().title\"\n >\n <!-- Avatar -->\n <div class=\"item-avatar\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"liveConversation()\"\n [size]=\"48\"\n [showStatus]=\"conversation().type === 'private'\"\n />\n </div>\n\n <!-- Content -->\n <div class=\"item-content\">\n <div class=\"item-header\">\n <span class=\"item-title\">\n <p class=\"item-title-text\">{{ liveConversation().title }}</p>\n @if (
|
|
9204
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationItemComponent, isStandalone: true, selector: "ax-conversation-item", inputs: { conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: " <div\n [class]=\"itemClasses()\"\n [id]=\"'conversation-item-' + conversation().id\"\n (click)=\"handleClick()\"\n (keydown.enter)=\"handleClick()\"\n (keydown.space)=\"handleClick()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Conversation with ' + conversation().title\"\n >\n <!-- Avatar -->\n <div class=\"item-avatar\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"liveConversation()\"\n [size]=\"48\"\n [showStatus]=\"conversation().type === 'private'\"\n />\n </div>\n\n <!-- Content -->\n <div class=\"item-content\">\n <div class=\"item-header\">\n <span class=\"item-title\">\n <p class=\"item-title-text\">{{ liveConversation().title }}</p>\n @if (roomPreferences().notifications === false) {\n <i class=\"fa-light fa-bell-slash mute-icon\"></i>\n }\n @if (liveConversation()?.blocked) {\n <i class=\"fa-ban fa-light block-icon\"></i>\n }\n </span>\n @if (liveConversation().lastMessageAt) {\n <span class=\"item-time\">{{ liveConversation().lastMessageAt | format: 'timeleft' | async }}</span>\n }\n </div>\n\n <div class=\"item-description\">\n @if (isTyping()) {\n <span class=\"typing-indicator\">{{ typingText() }}</span>\n } @else if (liveConversation().lastMessage) {\n @if (lastMessagePreview(); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n @if (preview.type === 'text') {\n {{ preview.value }}\n } @else {\n {{ getPreviewTypeKey(preview.type) | translate | async }}\n }\n </span>\n }\n } @else {\n <span class=\"last-message no-message\">{{ '@acorex:chat.status.no-messages' | translate | async }}</span>\n }\n <!-- Badge -->\n @if (liveConversation().unreadCount > 0) {\n <div class=\"item-badge\">\n <ax-badge [text]=\"liveConversation().unreadCount.toString()\" [color]=\"'primary'\" />\n </div>\n }\n <!-- Pin Icon -->\n @if (liveConversation().pinned) {\n <i class=\"fa-light fa-thumbtack pin-icon\"></i>\n }\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Conversation Actions -->\n <ax-context-menu\n [target]=\"'#conversation-item-' + conversation().id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleContextMenuOpening($event)\"\n (onClose)=\"contextMenuOpen.set(false)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n", styles: ["@layer properties;@layer components{ax-conversation-item{display:block}ax-conversation-item .conversation-item{margin:calc(var(--spacing, .25rem) * 1.5);display:flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1.5);transition:background .2s}ax-conversation-item .conversation-item:focus-visible,ax-conversation-item .conversation-item:hover{background-color:rgba(var(--ax-sys-color-light-surface));--tw-outline-style: none;outline-style:none}ax-conversation-item .conversation-item-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface));color:rgba(var(--ax-sys-color-on-primary-lightest-surface))}ax-conversation-item .conversation-item-active:hover{background-color:rgba(var(--ax-sys-color-primary-lighter-surface))}ax-conversation-item .conversation-item-context-active{background-color:rgba(var(--ax-sys-color-light-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.35)}ax-conversation-item .conversation-item-active.conversation-item-context-active{background-color:rgba(var(--ax-sys-color-primary-lighter-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-item .item-avatar{flex-shrink:0}ax-conversation-item .item-content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 1);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-item .item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-item .item-title{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-item .item-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-time{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:70%}ax-conversation-item .item-description{display:flex;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 2);font-size:.8125rem;opacity:70%}ax-conversation-item .typing-indicator{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));font-style:italic}ax-conversation-item .last-message{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-badge{flex-shrink:0}ax-conversation-item .mute-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-warning-500));opacity:60%}ax-conversation-item .block-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-danger-500));opacity:60%}ax-conversation-item .pin-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-primary-surface));opacity:60%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "component", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
8970
9205
|
}
|
|
8971
9206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationItemComponent, decorators: [{
|
|
8972
9207
|
type: Component,
|
|
@@ -8979,7 +9214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
8979
9214
|
AXDateTimeModule,
|
|
8980
9215
|
AXTranslationModule,
|
|
8981
9216
|
AXConversationAvatarComponent,
|
|
8982
|
-
], template: " <div\n [class]=\"itemClasses()\"\n [id]=\"'conversation-item-' + conversation().id\"\n (click)=\"handleClick()\"\n (keydown.enter)=\"handleClick()\"\n (keydown.space)=\"handleClick()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Conversation with ' + conversation().title\"\n >\n <!-- Avatar -->\n <div class=\"item-avatar\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"liveConversation()\"\n [size]=\"48\"\n [showStatus]=\"conversation().type === 'private'\"\n />\n </div>\n\n <!-- Content -->\n <div class=\"item-content\">\n <div class=\"item-header\">\n <span class=\"item-title\">\n <p class=\"item-title-text\">{{ liveConversation().title }}</p>\n @if (
|
|
9217
|
+
], template: " <div\n [class]=\"itemClasses()\"\n [id]=\"'conversation-item-' + conversation().id\"\n (click)=\"handleClick()\"\n (keydown.enter)=\"handleClick()\"\n (keydown.space)=\"handleClick()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Conversation with ' + conversation().title\"\n >\n <!-- Avatar -->\n <div class=\"item-avatar\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"liveConversation()\"\n [size]=\"48\"\n [showStatus]=\"conversation().type === 'private'\"\n />\n </div>\n\n <!-- Content -->\n <div class=\"item-content\">\n <div class=\"item-header\">\n <span class=\"item-title\">\n <p class=\"item-title-text\">{{ liveConversation().title }}</p>\n @if (roomPreferences().notifications === false) {\n <i class=\"fa-light fa-bell-slash mute-icon\"></i>\n }\n @if (liveConversation()?.blocked) {\n <i class=\"fa-ban fa-light block-icon\"></i>\n }\n </span>\n @if (liveConversation().lastMessageAt) {\n <span class=\"item-time\">{{ liveConversation().lastMessageAt | format: 'timeleft' | async }}</span>\n }\n </div>\n\n <div class=\"item-description\">\n @if (isTyping()) {\n <span class=\"typing-indicator\">{{ typingText() }}</span>\n } @else if (liveConversation().lastMessage) {\n @if (lastMessagePreview(); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n @if (preview.type === 'text') {\n {{ preview.value }}\n } @else {\n {{ getPreviewTypeKey(preview.type) | translate | async }}\n }\n </span>\n }\n } @else {\n <span class=\"last-message no-message\">{{ '@acorex:chat.status.no-messages' | translate | async }}</span>\n }\n <!-- Badge -->\n @if (liveConversation().unreadCount > 0) {\n <div class=\"item-badge\">\n <ax-badge [text]=\"liveConversation().unreadCount.toString()\" [color]=\"'primary'\" />\n </div>\n }\n <!-- Pin Icon -->\n @if (liveConversation().pinned) {\n <i class=\"fa-light fa-thumbtack pin-icon\"></i>\n }\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Conversation Actions -->\n <ax-context-menu\n [target]=\"'#conversation-item-' + conversation().id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleContextMenuOpening($event)\"\n (onClose)=\"contextMenuOpen.set(false)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n", styles: ["@layer properties;@layer components{ax-conversation-item{display:block}ax-conversation-item .conversation-item{margin:calc(var(--spacing, .25rem) * 1.5);display:flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1.5);transition:background .2s}ax-conversation-item .conversation-item:focus-visible,ax-conversation-item .conversation-item:hover{background-color:rgba(var(--ax-sys-color-light-surface));--tw-outline-style: none;outline-style:none}ax-conversation-item .conversation-item-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface));color:rgba(var(--ax-sys-color-on-primary-lightest-surface))}ax-conversation-item .conversation-item-active:hover{background-color:rgba(var(--ax-sys-color-primary-lighter-surface))}ax-conversation-item .conversation-item-context-active{background-color:rgba(var(--ax-sys-color-light-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.35)}ax-conversation-item .conversation-item-active.conversation-item-context-active{background-color:rgba(var(--ax-sys-color-primary-lighter-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-item .item-avatar{flex-shrink:0}ax-conversation-item .item-content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 1);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-item .item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-item .item-title{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-item .item-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-time{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:70%}ax-conversation-item .item-description{display:flex;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 2);font-size:.8125rem;opacity:70%}ax-conversation-item .typing-indicator{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));font-style:italic}ax-conversation-item .last-message{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-badge{flex-shrink:0}ax-conversation-item .mute-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-warning-500));opacity:60%}ax-conversation-item .block-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-danger-500));opacity:60%}ax-conversation-item .pin-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-primary-surface));opacity:60%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
8983
9218
|
}], propDecorators: { conversation: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversation", required: true }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
|
|
8984
9219
|
|
|
8985
9220
|
/**
|
|
@@ -9464,7 +9699,11 @@ var newConversationDialog_component = /*#__PURE__*/Object.freeze({
|
|
|
9464
9699
|
|
|
9465
9700
|
/**
|
|
9466
9701
|
* Participant Model
|
|
9467
|
-
*
|
|
9702
|
+
* Membership in a conversation (identity fields are snapshots; live presence is on the user store).
|
|
9703
|
+
*/
|
|
9704
|
+
|
|
9705
|
+
/**
|
|
9706
|
+
* User presence — global per-user live state (not room-scoped).
|
|
9468
9707
|
*/
|
|
9469
9708
|
|
|
9470
9709
|
function formatFileSize(bytes) {
|
|
@@ -12629,13 +12868,21 @@ const AX_CONVERSATION_INFO_BAR_SEARCH_ACTION = {
|
|
|
12629
12868
|
*/
|
|
12630
12869
|
const AX_CONVERSATION_INFO_BAR_MUTE_ACTION = {
|
|
12631
12870
|
id: 'mute',
|
|
12632
|
-
label: (context) =>
|
|
12633
|
-
|
|
12871
|
+
label: (context) => {
|
|
12872
|
+
const notifications = inject(AXConversationService).getRoomPreferences(context.conversation.id).notifications;
|
|
12873
|
+
return notifications ? '@acorex:chat.actions.mute' : '@acorex:chat.actions.unmute';
|
|
12874
|
+
},
|
|
12875
|
+
icon: (context) => {
|
|
12876
|
+
const notifications = inject(AXConversationService).getRoomPreferences(context.conversation.id).notifications;
|
|
12877
|
+
return notifications ? 'fa-light fa-bell-slash' : 'fa-light fa-bell';
|
|
12878
|
+
},
|
|
12634
12879
|
location: 'menu',
|
|
12635
12880
|
priority: 90,
|
|
12636
12881
|
handler: async (context) => {
|
|
12637
|
-
|
|
12638
|
-
|
|
12882
|
+
const service = inject(AXConversationService);
|
|
12883
|
+
const currentNotifications = service.getRoomPreferences(context.conversation.id).notifications;
|
|
12884
|
+
await service.updateConversationSettings(context.conversation.id, {
|
|
12885
|
+
notifications: !currentNotifications,
|
|
12639
12886
|
});
|
|
12640
12887
|
},
|
|
12641
12888
|
};
|
|
@@ -12916,9 +13163,13 @@ class AXConversationImageAttachmentComponent {
|
|
|
12916
13163
|
this.displayUrl = computed(() => pickDisplayMediaUrl(this.resolvedUrl(), this.item().thumbnailUrl, this.item().url), /* @ts-ignore */
|
|
12917
13164
|
...(ngDevMode ? [{ debugName: "displayUrl" }] : /* istanbul ignore next */ []));
|
|
12918
13165
|
effect(() => {
|
|
12919
|
-
this.displayUrl();
|
|
12920
|
-
this.item().mediaId;
|
|
12921
|
-
untracked(() =>
|
|
13166
|
+
const url = this.displayUrl();
|
|
13167
|
+
const mediaId = this.item().mediaId;
|
|
13168
|
+
untracked(() => {
|
|
13169
|
+
if (!url) {
|
|
13170
|
+
this.ready.set(false);
|
|
13171
|
+
}
|
|
13172
|
+
});
|
|
12922
13173
|
});
|
|
12923
13174
|
}
|
|
12924
13175
|
onImageLoad() {
|
|
@@ -14132,9 +14383,12 @@ const AX_CONVERSATION_MESSAGE_FORWARD_ACTION = {
|
|
|
14132
14383
|
icon: 'fa-light fa-share',
|
|
14133
14384
|
priority: 75,
|
|
14134
14385
|
visible: () => true,
|
|
14135
|
-
enabled: () =>
|
|
14386
|
+
enabled: () => !inject(AXConversationService).isForwardingMessage(),
|
|
14136
14387
|
handler: async (context) => {
|
|
14137
14388
|
const conversationService = inject(AXConversationService);
|
|
14389
|
+
if (conversationService.isForwardingMessage()) {
|
|
14390
|
+
return;
|
|
14391
|
+
}
|
|
14138
14392
|
const { AXConversationForwardMessageDialogComponent } = await Promise.resolve().then(function () { return forwardMessageDialog_component; });
|
|
14139
14393
|
await conversationService.popupService.open(AXConversationForwardMessageDialogComponent, {
|
|
14140
14394
|
title: translateSync('@acorex:chat.dialog.forward-message.title'),
|
|
@@ -14337,15 +14591,20 @@ var fallbackRenderer_plugin = /*#__PURE__*/Object.freeze({
|
|
|
14337
14591
|
*/
|
|
14338
14592
|
const AX_CONVERSATION_ITEM_MUTE_ACTION = {
|
|
14339
14593
|
id: 'mute',
|
|
14340
|
-
label: (context) =>
|
|
14341
|
-
|
|
14342
|
-
: '@acorex:chat.actions.mute'
|
|
14343
|
-
|
|
14594
|
+
label: (context) => {
|
|
14595
|
+
const notifications = inject(AXConversationService).getRoomPreferences(context.conversation.id).notifications;
|
|
14596
|
+
return notifications === false ? '@acorex:chat.actions.unmute' : '@acorex:chat.actions.mute';
|
|
14597
|
+
},
|
|
14598
|
+
icon: (context) => {
|
|
14599
|
+
const notifications = inject(AXConversationService).getRoomPreferences(context.conversation.id).notifications;
|
|
14600
|
+
return notifications === false ? 'fa-light fa-bell-slash' : 'fa-light fa-bell';
|
|
14601
|
+
},
|
|
14344
14602
|
tooltip: '@acorex:chat.tooltips.toggle-notifications',
|
|
14345
14603
|
priority: 100,
|
|
14346
14604
|
handler: async (context) => {
|
|
14347
|
-
const
|
|
14348
|
-
|
|
14605
|
+
const service = inject(AXConversationService);
|
|
14606
|
+
const currentNotifications = service.getRoomPreferences(context.conversation.id).notifications;
|
|
14607
|
+
await service.updateConversationSettings(context.conversation.id, {
|
|
14349
14608
|
notifications: !currentNotifications,
|
|
14350
14609
|
});
|
|
14351
14610
|
},
|
|
@@ -14546,16 +14805,17 @@ class AXConversationDefaultConversationAvatarComponent {
|
|
|
14546
14805
|
return resolveConversationPeerUserId(conversation, this.currentUserId());
|
|
14547
14806
|
}, /* @ts-ignore */
|
|
14548
14807
|
...(ngDevMode ? [{ debugName: "peerUserId" }] : /* istanbul ignore next */ []));
|
|
14549
|
-
this.useUserAvatar = computed(() =>
|
|
14550
|
-
const component = this.userAvatarComponent;
|
|
14551
|
-
const peerId = this.peerUserId();
|
|
14552
|
-
return component && peerId ? component : null;
|
|
14553
|
-
}, /* @ts-ignore */
|
|
14808
|
+
this.useUserAvatar = computed(() => this.userAvatarComponent ?? null, /* @ts-ignore */
|
|
14554
14809
|
...(ngDevMode ? [{ debugName: "useUserAvatar" }] : /* istanbul ignore next */ []));
|
|
14555
14810
|
this.userAvatarInputs = computed(() => {
|
|
14556
|
-
const userId = this.peerUserId() ?? '';
|
|
14557
14811
|
const conversation = this.conversation();
|
|
14558
|
-
const
|
|
14812
|
+
const peerId = this.peerUserId();
|
|
14813
|
+
const userId = peerId ?? conversation?.id ?? '';
|
|
14814
|
+
const resolved = peerId && conversation
|
|
14815
|
+
? resolveUserAvatarDisplay(peerId, conversation)
|
|
14816
|
+
: conversation
|
|
14817
|
+
? resolveConversationAvatarDisplay(conversation, this.currentUserId())
|
|
14818
|
+
: { name: '?', avatar: undefined, icon: undefined };
|
|
14559
14819
|
return {
|
|
14560
14820
|
userId,
|
|
14561
14821
|
size: this.size(),
|
|
@@ -15013,5 +15273,5 @@ function getErrorMessage(code, params) {
|
|
|
15013
15273
|
* Generated bundle index. Do not edit.
|
|
15014
15274
|
*/
|
|
15015
15275
|
|
|
15016
|
-
export { AXConversationApi, AXConversationApiLoggerService, AXConversationAudioAttachmentComponent, AXConversationAudioFileTypeProvider, AXConversationAudioPickerComponent, AXConversationAudioRendererComponent, AXConversationAvatarComponent, AXConversationAvatarPickerComponent, AXConversationBaseRegistry, AXConversationComposerActionRegistry, AXConversationComposerComponent, AXConversationComposerFileTypesProvider, AXConversationComposerGenerationStateService, AXConversationComposerPopupComponent, AXConversationComposerService, AXConversationComposerTabRegistry, AXConversationContainerComponent, AXConversationContainerDirective, AXConversationDateUtilsService, AXConversationEmojiTabComponent, AXConversationErrorHandlerService, AXConversationFallbackRendererComponent, AXConversationFileAttachmentComponent, AXConversationFileFileTypeProvider, AXConversationFilePickerComponent, AXConversationFileRendererComponent, AXConversationForwardMessageDialogComponent, AXConversationImageAttachmentComponent, AXConversationImageFileTypeProvider, AXConversationImagePickerComponent, AXConversationImageRendererComponent, AXConversationInfiniteScrollDirective, AXConversationInfoBarActionRegistry, AXConversationInfoBarComponent, AXConversationInfoBarSearchComponent, AXConversationInfoBarService, AXConversationItemActionRegistry, AXConversationLocationPickerComponent, AXConversationLocationRendererComponent, AXConversationMediaPlaybackInfoBarBannerComponent, AXConversationMessageActionRegistry, AXConversationMessageApi, AXConversationMessageListComponent, AXConversationMessageListNoActiveDefaultComponent, AXConversationMessageListService, AXConversationMessageRendererCopyHostComponent, AXConversationMessageRendererRegistry, AXConversationMessageRendererStateComponent, AXConversationMessageUtilsService, AXConversationModule, AXConversationNewDialogComponent, AXConversationPickerCaptionComponent, AXConversationPickerEmptyComponent, AXConversationPickerFooterComponent, AXConversationPickerHeaderComponent, AXConversationPickerShellComponent, AXConversationPickerToolbarComponent, AXConversationRealtimeApi, AXConversationRegistryComponentOutletComponent, AXConversationRegistryService, AXConversationService, AXConversationSidebarComponent, AXConversationSidebarService, AXConversationStickerRendererComponent, AXConversationStickerTabComponent, AXConversationSystemRendererComponent, AXConversationTabRegistry, AXConversationTextRendererComponent, AXConversationUserApi, AXConversationVideoAttachmentComponent, AXConversationVideoFileTypeProvider, AXConversationVideoPickerComponent, AXConversationVideoRendererComponent, AXConversationVoiceFileTypeProvider, AXConversationVoiceRecorderComponent, AXConversationVoiceRendererComponent, AX_CONVERSATION_AUDIO_CATALOG, AX_CONVERSATION_AUDIO_PRESENTATION, AX_CONVERSATION_AUDIO_RENDERER, AX_CONVERSATION_BUILTIN_COMPOSER_TABS, AX_CONVERSATION_COMPOSER_AUDIO_ACTION, AX_CONVERSATION_COMPOSER_EMOJI_ACTION, AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_FILE_ACTION, AX_CONVERSATION_COMPOSER_IMAGE_ACTION, AX_CONVERSATION_COMPOSER_LOCATION_ACTION, AX_CONVERSATION_COMPOSER_STICKER_TAB, AX_CONVERSATION_COMPOSER_VIDEO_ACTION, AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION, AX_CONVERSATION_CONFIG, AX_CONVERSATION_CONNECTION_ERRORS, AX_CONVERSATION_CONVERSATION_AVATAR_COMPONENT, AX_CONVERSATION_DEFAULT_COMPOSER_ACTIONS, AX_CONVERSATION_DEFAULT_COMPOSER_TABS, AX_CONVERSATION_DEFAULT_CONVERSATION_ITEM_ACTIONS, AX_CONVERSATION_DEFAULT_CONVERSATION_TABS, AX_CONVERSATION_DEFAULT_GROUP_ICON, AX_CONVERSATION_DEFAULT_INFO_BAR_ACTIONS, AX_CONVERSATION_DEFAULT_MESSAGE_ACTIONS, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_BACKGROUND, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_BACKGROUND_PRESET_ID, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_THEME_BACKGROUND, AX_CONVERSATION_DEFAULT_MESSAGE_RENDERERS, AX_CONVERSATION_DEFAULT_USER_ICON, AX_CONVERSATION_ERRORS, AX_CONVERSATION_ERROR_HANDLER_CONFIG, AX_CONVERSATION_ERROR_MESSAGES, AX_CONVERSATION_FALLBACK_RENDERER, AX_CONVERSATION_FILE_CATALOG, AX_CONVERSATION_FILE_ERRORS, AX_CONVERSATION_FILE_PRESENTATION, AX_CONVERSATION_FILE_RENDERER, AX_CONVERSATION_FILE_TYPES_READY, AX_CONVERSATION_IMAGE_CATALOG, AX_CONVERSATION_IMAGE_PRESENTATION, AX_CONVERSATION_IMAGE_RENDERER, AX_CONVERSATION_INFO_BAR_ARCHIVE_ACTION, AX_CONVERSATION_INFO_BAR_BLOCK_ACTION, AX_CONVERSATION_INFO_BAR_DELETE_ACTION, AX_CONVERSATION_INFO_BAR_DIVIDER, AX_CONVERSATION_INFO_BAR_MUTE_ACTION, AX_CONVERSATION_INFO_BAR_SEARCH_ACTION, AX_CONVERSATION_ITEM_BLOCK_ACTION, AX_CONVERSATION_ITEM_DELETE_ACTION, AX_CONVERSATION_ITEM_DIVIDER, AX_CONVERSATION_ITEM_MARK_READ_ACTION, AX_CONVERSATION_ITEM_MUTE_ACTION, AX_CONVERSATION_ITEM_PIN_ACTION, AX_CONVERSATION_LOCATION_ERRORS, AX_CONVERSATION_LOCATION_RENDERER, AX_CONVERSATION_MESSAGE_DELETE_ACTION, AX_CONVERSATION_MESSAGE_EDIT_ACTION, AX_CONVERSATION_MESSAGE_ERRORS, AX_CONVERSATION_MESSAGE_FORWARD_ACTION, AX_CONVERSATION_MESSAGE_LIST_BACKGROUND_PRESETS, AX_CONVERSATION_MESSAGE_REPLY_ACTION, AX_CONVERSATION_MESSAGE_TYPE_FILE_TYPE, AX_CONVERSATION_PEER_AVATAR_TYPES, AX_CONVERSATION_REGISTRY_CONFIG, AX_CONVERSATION_STICKER_API_KEY, AX_CONVERSATION_STICKER_RENDERER, AX_CONVERSATION_SYSTEM_RENDERER, AX_CONVERSATION_TAB_ALL, AX_CONVERSATION_TAB_ARCHIVED, AX_CONVERSATION_TAB_BOT, AX_CONVERSATION_TAB_CHANNELS, AX_CONVERSATION_TAB_GROUPS, AX_CONVERSATION_TAB_PRIVATE, AX_CONVERSATION_TAB_UNREAD, AX_CONVERSATION_TEXT_RENDERER, AX_CONVERSATION_URL_ERRORS, AX_CONVERSATION_USER_AVATAR_COMPONENT, AX_CONVERSATION_USER_ERRORS, AX_CONVERSATION_VIDEO_CATALOG, AX_CONVERSATION_VIDEO_PRESENTATION, AX_CONVERSATION_VIDEO_RENDERER, AX_CONVERSATION_VOICE_CATALOG, AX_CONVERSATION_VOICE_PRESENTATION, AX_CONVERSATION_VOICE_RENDERER, AX_DEFAULT_CONVERSATION_CONFIG, abortPickerUploads, applyAudioLocalPreview, applyFileLocalPreview, applyLocalPreview, applyVideoLocalPreview, applyVoiceLocalPreview, audioItemFromUpload, bindMediaRendererContentState, buildMediaGalleryTiles, canShowRendererContentError, cleanupPickerUploads, conversationAudioUtilities, conversationFileUtilities, conversationImageUtilities, conversationVideoUtilities, conversationVoiceUtilities, copyWithFileTypeFallback, createConversationAudioFileType, createConversationFileFileType, createConversationImageFileType, createConversationVideoFileType, createConversationVoiceFileType, createLocalPreviewUrl, createObjectUrl, createPickerDragHandlers, createResolvedMediaUrlSignal, deleteUploadedPickerMedia, dismissComposerPickerHost, ensureConversationFileCatalogRegistered, fetchConversationMediaPage, fileItemFromUpload, filterMessagesByMediaCategory, filterSupplementalInfoPanelMessages, findExistingPrivateConversation, formatDuration, formatErrorMessage, formatFileByteSize, formatFileSize, formatMediaDuration, formatPickerValidationMessage, getConversationMediaCategories, getConversationProfileFields, getErrorMessage, getMessageAudioItems, getMessageVideoItems, getPickerCancelUploadLabel, getPrivatePeerParticipant, hasRegistryComponent, inferFileExtensionHintFromMessage, isAttachmentListCategory, isComposerTabEnabled, isConversationReactionsEnabled, isGenericPrivateConversationTitle, isGridMediaCategory, isMessageDeliveryPending, isMessageListThemeBackground, isNonPersistableMediaUrl, isPickerItemReadyToSend, isSameMessageListBackground, isUploadAborted, limitFilesToCapacity, mediaCopyText, mergeAudioUploadResult, mergeFileUploadResult, mergeInfoPanelMessages, mergeUploadResult, mergeVideoUploadResult, mergeVoiceUploadResult, mergeWithDefaults, messageContainsLink, normalizeAudioPayload, normalizeFilePayload, normalizeImagePayload, normalizeMessageListBackgroundValue, normalizeVideoPayload, notifyMaxFilesCapacityExceeded, notifyPickerValidationErrors, openWithFileType, pickDisplayMediaUrl, pickerItemToMediaReference, pickerItemToUploadResult, provideConversation, provideConversationComposerFileTypes, provideConversationFileCatalog, reportMediaLoadError, resolveComposerMaxFiles, resolveConversationAvatarDisplay, resolveConversationComposerTabs, resolveConversationForViewer, resolveConversationMessageFileType, resolveConversationPeerParticipant, resolveConversationPeerUserId, resolveConversationTitleForViewer, resolveGalleryImageUrl, resolveImageDisplayUrl, resolveMessageListBackgroundRaw, resolveMessageListBackgroundStyle, resolveParticipantProfile, resolvePersistableMediaUrl, resolvePersistedThumbnailUrl, resolvePrivatePeerParticipant, resolvePrivatePeerUserId, resolveUserAvatarDisplay, resolveVideoThumbnailUrl, revokeObjectUrl, revokePickerBlobPreviews, sanitizeInput, shouldUseUserAvatarForConversation, syncPlaybackInfoBarBanner, toUploaderReference as toMediaItemUploaderReference, toUploaderReference$1 as toUploaderReference, uploadPickerFile, validateConversationId, validateEmail, validateLatitude, validateLongitude, validateMessagePayload, validateMessageText, validateMessageType, validateUrl, validateUserId, validateUserIds, videoItemFromUpload };
|
|
15276
|
+
export { AXConversationApi, AXConversationApiLoggerService, AXConversationAudioAttachmentComponent, AXConversationAudioFileTypeProvider, AXConversationAudioPickerComponent, AXConversationAudioRendererComponent, AXConversationAvatarComponent, AXConversationAvatarPickerComponent, AXConversationBaseRegistry, AXConversationComposerActionRegistry, AXConversationComposerComponent, AXConversationComposerFileTypesProvider, AXConversationComposerGenerationStateService, AXConversationComposerPopupComponent, AXConversationComposerService, AXConversationComposerTabRegistry, AXConversationContainerComponent, AXConversationContainerDirective, AXConversationDateUtilsService, AXConversationEmojiTabComponent, AXConversationErrorHandlerService, AXConversationFallbackRendererComponent, AXConversationFileAttachmentComponent, AXConversationFileFileTypeProvider, AXConversationFilePickerComponent, AXConversationFileRendererComponent, AXConversationForwardMessageDialogComponent, AXConversationImageAttachmentComponent, AXConversationImageFileTypeProvider, AXConversationImagePickerComponent, AXConversationImageRendererComponent, AXConversationInfiniteScrollDirective, AXConversationInfoBarActionRegistry, AXConversationInfoBarComponent, AXConversationInfoBarSearchComponent, AXConversationInfoBarService, AXConversationItemActionRegistry, AXConversationLocationPickerComponent, AXConversationLocationRendererComponent, AXConversationMediaPlaybackInfoBarBannerComponent, AXConversationMessageActionRegistry, AXConversationMessageApi, AXConversationMessageListComponent, AXConversationMessageListNoActiveDefaultComponent, AXConversationMessageListService, AXConversationMessageRendererCopyHostComponent, AXConversationMessageRendererRegistry, AXConversationMessageRendererStateComponent, AXConversationMessageUtilsService, AXConversationModule, AXConversationNewDialogComponent, AXConversationPickerCaptionComponent, AXConversationPickerEmptyComponent, AXConversationPickerFooterComponent, AXConversationPickerHeaderComponent, AXConversationPickerShellComponent, AXConversationPickerToolbarComponent, AXConversationRealtimeApi, AXConversationRegistryComponentOutletComponent, AXConversationRegistryService, AXConversationService, AXConversationSidebarComponent, AXConversationSidebarService, AXConversationStickerRendererComponent, AXConversationStickerTabComponent, AXConversationSystemRendererComponent, AXConversationTabRegistry, AXConversationTextRendererComponent, AXConversationUserApi, AXConversationVideoAttachmentComponent, AXConversationVideoFileTypeProvider, AXConversationVideoPickerComponent, AXConversationVideoRendererComponent, AXConversationVoiceFileTypeProvider, AXConversationVoiceRecorderComponent, AXConversationVoiceRendererComponent, AX_CONVERSATION_AUDIO_CATALOG, AX_CONVERSATION_AUDIO_PRESENTATION, AX_CONVERSATION_AUDIO_RENDERER, AX_CONVERSATION_BUILTIN_COMPOSER_TABS, AX_CONVERSATION_COMPOSER_AUDIO_ACTION, AX_CONVERSATION_COMPOSER_EMOJI_ACTION, AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_FILE_ACTION, AX_CONVERSATION_COMPOSER_IMAGE_ACTION, AX_CONVERSATION_COMPOSER_LOCATION_ACTION, AX_CONVERSATION_COMPOSER_STICKER_TAB, AX_CONVERSATION_COMPOSER_VIDEO_ACTION, AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION, AX_CONVERSATION_CONFIG, AX_CONVERSATION_CONNECTION_ERRORS, AX_CONVERSATION_CONVERSATION_AVATAR_COMPONENT, AX_CONVERSATION_DEFAULT_COMPOSER_ACTIONS, AX_CONVERSATION_DEFAULT_COMPOSER_TABS, AX_CONVERSATION_DEFAULT_CONVERSATION_ITEM_ACTIONS, AX_CONVERSATION_DEFAULT_CONVERSATION_TABS, AX_CONVERSATION_DEFAULT_GROUP_ICON, AX_CONVERSATION_DEFAULT_INFO_BAR_ACTIONS, AX_CONVERSATION_DEFAULT_MESSAGE_ACTIONS, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_BACKGROUND, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_BACKGROUND_PRESET_ID, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_THEME_BACKGROUND, AX_CONVERSATION_DEFAULT_MESSAGE_RENDERERS, AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES, AX_CONVERSATION_DEFAULT_USER_ICON, AX_CONVERSATION_ERRORS, AX_CONVERSATION_ERROR_HANDLER_CONFIG, AX_CONVERSATION_ERROR_MESSAGES, AX_CONVERSATION_FALLBACK_RENDERER, AX_CONVERSATION_FILE_CATALOG, AX_CONVERSATION_FILE_ERRORS, AX_CONVERSATION_FILE_PRESENTATION, AX_CONVERSATION_FILE_RENDERER, AX_CONVERSATION_FILE_TYPES_READY, AX_CONVERSATION_IMAGE_CATALOG, AX_CONVERSATION_IMAGE_PRESENTATION, AX_CONVERSATION_IMAGE_RENDERER, AX_CONVERSATION_INFO_BAR_ARCHIVE_ACTION, AX_CONVERSATION_INFO_BAR_BLOCK_ACTION, AX_CONVERSATION_INFO_BAR_DELETE_ACTION, AX_CONVERSATION_INFO_BAR_DIVIDER, AX_CONVERSATION_INFO_BAR_MUTE_ACTION, AX_CONVERSATION_INFO_BAR_SEARCH_ACTION, AX_CONVERSATION_ITEM_BLOCK_ACTION, AX_CONVERSATION_ITEM_DELETE_ACTION, AX_CONVERSATION_ITEM_DIVIDER, AX_CONVERSATION_ITEM_MARK_READ_ACTION, AX_CONVERSATION_ITEM_MUTE_ACTION, AX_CONVERSATION_ITEM_PIN_ACTION, AX_CONVERSATION_LOCATION_ERRORS, AX_CONVERSATION_LOCATION_RENDERER, AX_CONVERSATION_MESSAGE_DELETE_ACTION, AX_CONVERSATION_MESSAGE_EDIT_ACTION, AX_CONVERSATION_MESSAGE_ERRORS, AX_CONVERSATION_MESSAGE_FORWARD_ACTION, AX_CONVERSATION_MESSAGE_LIST_BACKGROUND_PRESETS, AX_CONVERSATION_MESSAGE_REPLY_ACTION, AX_CONVERSATION_MESSAGE_TYPE_FILE_TYPE, AX_CONVERSATION_PEER_AVATAR_TYPES, AX_CONVERSATION_REGISTRY_CONFIG, AX_CONVERSATION_STICKER_API_KEY, AX_CONVERSATION_STICKER_RENDERER, AX_CONVERSATION_SYSTEM_RENDERER, AX_CONVERSATION_TAB_ALL, AX_CONVERSATION_TAB_ARCHIVED, AX_CONVERSATION_TAB_BOT, AX_CONVERSATION_TAB_CHANNELS, AX_CONVERSATION_TAB_GROUPS, AX_CONVERSATION_TAB_PRIVATE, AX_CONVERSATION_TAB_UNREAD, AX_CONVERSATION_TEXT_RENDERER, AX_CONVERSATION_URL_ERRORS, AX_CONVERSATION_USER_AVATAR_COMPONENT, AX_CONVERSATION_USER_ERRORS, AX_CONVERSATION_VIDEO_CATALOG, AX_CONVERSATION_VIDEO_PRESENTATION, AX_CONVERSATION_VIDEO_RENDERER, AX_CONVERSATION_VOICE_CATALOG, AX_CONVERSATION_VOICE_PRESENTATION, AX_CONVERSATION_VOICE_RENDERER, AX_DEFAULT_CONVERSATION_CONFIG, abortPickerUploads, applyAudioLocalPreview, applyFileLocalPreview, applyLocalPreview, applyVideoLocalPreview, applyVoiceLocalPreview, audioItemFromUpload, bindMediaRendererContentState, buildMediaGalleryTiles, canShowRendererContentError, cleanupPickerUploads, conversationAudioUtilities, conversationFileUtilities, conversationImageUtilities, conversationVideoUtilities, conversationVoiceUtilities, copyWithFileTypeFallback, createConversationAudioFileType, createConversationFileFileType, createConversationImageFileType, createConversationVideoFileType, createConversationVoiceFileType, createLocalPreviewUrl, createObjectUrl, createPickerDragHandlers, createResolvedMediaUrlSignal, deleteUploadedPickerMedia, dismissComposerPickerHost, ensureConversationFileCatalogRegistered, fetchConversationMediaPage, fileItemFromUpload, filterMessagesByMediaCategory, filterSupplementalInfoPanelMessages, findExistingPrivateConversation, formatDuration, formatErrorMessage, formatFileByteSize, formatFileSize, formatMediaDuration, formatPickerValidationMessage, getConversationMediaCategories, getConversationProfileFields, getErrorMessage, getMessageAudioItems, getMessageVideoItems, getPickerCancelUploadLabel, getPrivatePeerParticipant, hasRegistryComponent, inferFileExtensionHintFromMessage, isAttachmentListCategory, isComposerTabEnabled, isConversationReactionsEnabled, isGenericPrivateConversationTitle, isGridMediaCategory, isMessageDeliveryPending, isMessageListThemeBackground, isNonPersistableMediaUrl, isPickerItemReadyToSend, isSameMessageListBackground, isUploadAborted, limitFilesToCapacity, mediaCopyText, mergeAudioUploadResult, mergeFileUploadResult, mergeInfoPanelMessages, mergeUploadResult, mergeVideoUploadResult, mergeVoiceUploadResult, mergeWithDefaults, messageContainsLink, normalizeAudioPayload, normalizeFilePayload, normalizeImagePayload, normalizeMessageListBackgroundValue, normalizeVideoPayload, notifyMaxFilesCapacityExceeded, notifyPickerValidationErrors, openWithFileType, pickDisplayMediaUrl, pickerItemToMediaReference, pickerItemToUploadResult, provideConversation, provideConversationComposerFileTypes, provideConversationFileCatalog, reportMediaLoadError, resolveComposerMaxFiles, resolveConversationAvatarDisplay, resolveConversationComposerTabs, resolveConversationForViewer, resolveConversationMessageFileType, resolveConversationPeerParticipant, resolveConversationPeerUserId, resolveConversationTitleForViewer, resolveGalleryImageUrl, resolveImageDisplayUrl, resolveMessageListBackgroundRaw, resolveMessageListBackgroundStyle, resolveParticipantProfile, resolvePersistableMediaUrl, resolvePersistedThumbnailUrl, resolvePrivatePeerParticipant, resolvePrivatePeerUserId, resolveUserAvatarDisplay, resolveVideoThumbnailUrl, revokeObjectUrl, revokePickerBlobPreviews, sanitizeInput, shouldUseUserAvatarForConversation, syncPlaybackInfoBarBanner, toUploaderReference as toMediaItemUploaderReference, toUploaderReference$1 as toUploaderReference, uploadPickerFile, validateConversationId, validateEmail, validateLatitude, validateLongitude, validateMessagePayload, validateMessageText, validateMessageType, validateUrl, validateUserId, validateUserIds, videoItemFromUpload };
|
|
15017
15277
|
//# sourceMappingURL=acorex-components-conversation.mjs.map
|