mediasfu-angular 2.2.3 → 2.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, Input, Optional, Inject, Component, ViewChild, HostListener, Injector, EventEmitter, Output, ContentChildren, forwardRef, ViewEncapsulation, InjectionToken, TemplateRef, Directive } from '@angular/core';
3
- import { joinConsumeRoom, producerClosed, newPipeProducer, getOverlayPosition as getOverlayPosition$1, translationRoomConfig, translationConfigUpdated, translationLanguageSet, translationSubscribed, translationUnsubscribed, translationProducerReady, translationProducerClosed, translationChannelsAvailable, translationMemberState, translationError, translationTranscript, translationSpeakerOutputChanged, controlMedia, isSubtitleExpired, autoAdjust, calculateRowsAndColumns, changeVids, checkGrid, checkPermission, checkScreenShare, closeAndResize, compareActiveNames, compareScreenStates, connectIps, connectLocalIps, connectRecvTransport, connectSendTransport, connectSendTransportAudio, connectSendTransportScreen, connectSendTransportVideo, createSendTransport, disconnectSendTransportAudio, disconnectSendTransportVideo, disconnectSendTransportScreen, dispStreams, generatePageContent, getEstimate, getPipedProducersAlt, getProducersPiped, getVideos, mixStreams, onScreenChanges, processConsumerTransports, processConsumerTransportsAudio, readjust, receiveAllPipedTransports, reorderStreams, rePort, requestScreenShare, resumePauseAudioStreams, resumePauseStreams, resumeSendTransportAudio, reUpdateInter, signalNewConsumerTransport, startShareScreen, stopShareScreen, streamSuccessAudio, streamSuccessAudioSwitch, streamSuccessScreen, switchUserAudio, clickVideo, switchUserVideo, switchUserVideoAlt, trigger, updateMiniCardsGrid, updateParticipantAudioDecibels, aParams, hParams, screenParams, vParams, launchBackground, launchBreakoutRooms, breakoutRoomUpdated, launchCoHost as launchCoHost$1, modifyCoHostSettings, launchDisplaySettings, modifyDisplaySettings, launchConfirmExit, confirmExit, launchMediaSettings, launchMenuModal, launchMessages, sendMessage, launchParticipants, messageParticipants, muteParticipants, removeParticipants, handleCreatePoll, handleEndPoll, handleVotePoll, launchPoll, pollUpdated, checkPauseState, checkResumeState, confirmRecording, launchRecording, recordPauseTimer, recordResumeTimer, recordStartTimer, recordUpdateTimer, startRecording, stopRecording, updateRecording, launchRequests, respondToRequests, launchSettings, modifySettings, clickAudio, clickChat, clickScreenShare, switchAudio, switchVideo, switchVideoAlt, joinRoomOnMediaSFU, formatNumber, getModalPosition as getModalPosition$1, sleep as sleep$1, validateAlphanumeric, launchWaiting, respondToWaiting, launchConfigureWhiteboard, createDeviceClient, joinRoomClient, updateRoomParametersClient, joinConRoom, joinRoom, checkMediasfuURL, joinLocalRoom, allMembers, allMembersRest, allWaitingRoomMembers, banParticipant, controlMediaHost, disconnect, disconnectUserSelf, getDomains, hostRequestResponse, meetingEnded, meetingStillThere, meetingTimeRemaining, participantRequested, personJoined, producerMediaClosed, producerMediaPaused, producerMediaResumed, reInitiateRecording, receiveMessage, recordingNotice, roomRecordParams, screenProducerId, startRecords, stoppedRecording, timeLeftRecording, updateConsumingDomains, updateMediaSettings, updatedCoHost, userWaiting, connectSocket, connectLocalSocket, disconnectSocket, checkLimitsAndMakeRequest, createRoomOnMediaSFU, SUPPORTED_LANGUAGE_CODES as SUPPORTED_LANGUAGE_CODES$1, isLanguageSupported as isLanguageSupported$1, normalizeLanguageCode as normalizeLanguageCode$1, getLanguageName as getLanguageName$1, getLanguageNativeName as getLanguageNativeName$1, getSupportedLanguages as getSupportedLanguages$1, getLanguageMetadata, addPanelist, removePanelist, focusPanelists, updateParticipantPermission, bulkUpdateParticipantPermissions, updatePermissionConfig, isSpeakerInMyBreakoutRoom, pauseOriginalProducer, resumeOriginalProducer, isConsumingTranslationForSpeaker, getActiveTranslationConsumers, findOriginalProducerForSpeaker, stopConsumingTranslation, syncTranslationStateAfterBreakoutChange, panelistsUpdated, panelistFocusChanged, panelistControlMedia, addedAsPanelist, removedFromPanelists, permissionUpdated, permissionConfigUpdated, receiveRoomMessages, createResponseJoinRoom as createResponseJoinRoom$1, createLiveSubtitle, SoundPlayer as SoundPlayer$1 } from 'mediasfu-shared';
3
+ import { joinConsumeRoom, producerClosed, newPipeProducer, getOverlayPosition as getOverlayPosition$1, translationRoomConfig, translationConfigUpdated, translationLanguageSet, translationSubscribed, translationUnsubscribed, translationProducerReady, translationProducerClosed, translationChannelsAvailable, translationMemberState, translationError, translationTranscript, translationSpeakerOutputChanged, controlMedia, isSubtitleExpired, autoAdjust, calculateRowsAndColumns, changeVids, checkGrid, checkPermission, checkScreenShare, closeAndResize, compareActiveNames, compareScreenStates, connectIps, connectLocalIps, connectRecvTransport, connectSendTransport, connectSendTransportAudio, connectSendTransportScreen, connectSendTransportVideo, createSendTransport, disconnectSendTransportAudio, disconnectSendTransportVideo, disconnectSendTransportScreen, dispStreams, generatePageContent, getEstimate, getPipedProducersAlt, getProducersPiped, getVideos, mixStreams, onScreenChanges, processConsumerTransports, processConsumerTransportsAudio, readjust, receiveAllPipedTransports, reorderStreams, rePort, requestScreenShare, resumePauseAudioStreams, resumePauseStreams, resumeSendTransportAudio, reUpdateInter, signalNewConsumerTransport, startShareScreen, stopShareScreen, streamSuccessAudio, streamSuccessAudioSwitch, streamSuccessScreen, switchUserAudio, clickVideo, switchUserVideo, switchUserVideoAlt, trigger, updateMiniCardsGrid, updateParticipantAudioDecibels, aParams, hParams, screenParams, vParams, launchBackground, launchBreakoutRooms, breakoutRoomUpdated, launchCoHost as launchCoHost$1, modifyCoHostSettings, launchDisplaySettings, modifyDisplaySettings, launchConfirmExit, confirmExit, launchMediaSettings, launchMenuModal, launchMessages, launchParticipants, messageParticipants, muteParticipants, removeParticipants, handleCreatePoll, handleEndPoll, handleVotePoll, launchPoll, pollUpdated, checkPauseState, checkResumeState, confirmRecording, launchRecording, recordPauseTimer, recordResumeTimer, recordStartTimer, recordUpdateTimer, startRecording, stopRecording, updateRecording, launchRequests, respondToRequests, launchSettings, modifySettings, clickAudio, clickChat, clickScreenShare, switchAudio, switchVideo, switchVideoAlt, joinRoomOnMediaSFU, formatNumber, getModalPosition as getModalPosition$1, sleep as sleep$1, validateAlphanumeric, launchWaiting, respondToWaiting, launchConfigureWhiteboard, createDeviceClient, joinRoomClient, updateRoomParametersClient, joinConRoom, joinRoom, checkMediasfuURL, joinLocalRoom, allMembers, allMembersRest, allWaitingRoomMembers, banParticipant, controlMediaHost, disconnect, disconnectUserSelf, getDomains, hostRequestResponse, meetingEnded, meetingStillThere, meetingTimeRemaining, participantRequested, personJoined, producerMediaClosed, producerMediaPaused, producerMediaResumed, reInitiateRecording, receiveMessage, recordingNotice, roomRecordParams, screenProducerId, startRecords, stoppedRecording, timeLeftRecording, updateConsumingDomains, updateMediaSettings, updatedCoHost, userWaiting, connectSocket, connectLocalSocket, disconnectSocket, checkLimitsAndMakeRequest, createRoomOnMediaSFU, SUPPORTED_LANGUAGE_CODES as SUPPORTED_LANGUAGE_CODES$1, isLanguageSupported as isLanguageSupported$1, normalizeLanguageCode as normalizeLanguageCode$1, getLanguageName as getLanguageName$1, getLanguageNativeName as getLanguageNativeName$1, getSupportedLanguages as getSupportedLanguages$1, getLanguageMetadata, addPanelist, removePanelist, focusPanelists, updateParticipantPermission, bulkUpdateParticipantPermissions, updatePermissionConfig, isSpeakerInMyBreakoutRoom, pauseOriginalProducer, resumeOriginalProducer, isConsumingTranslationForSpeaker, getActiveTranslationConsumers, findOriginalProducerForSpeaker, stopConsumingTranslation, syncTranslationStateAfterBreakoutChange, panelistsUpdated, panelistFocusChanged, panelistControlMedia, addedAsPanelist, removedFromPanelists, permissionUpdated, permissionConfigUpdated, receiveRoomMessages, createResponseJoinRoom as createResponseJoinRoom$1, createLiveSubtitle, SoundPlayer as SoundPlayer$1 } from 'mediasfu-shared';
4
4
  export { createLiveSubtitle, isSubtitleExpired } from 'mediasfu-shared';
5
5
  import * as i1 from '@angular/common';
6
6
  import { CommonModule } from '@angular/common';
@@ -11292,23 +11292,59 @@ class SendMessage {
11292
11292
  * @throws Will throw an error if the message, sender, or receivers are not valid.
11293
11293
  * @throws Will throw an error if the user is not allowed to send a message in the event room.
11294
11294
  */
11295
- async sendMessage({ member, islevel, showAlert, coHostResponsibility, coHost, chatSetting, message, roomName, messagesLength, receivers, group, sender, socket, }) {
11296
- const normalizedEventType = roomName.startsWith('s') ? 'chat' : 'conference';
11297
- await sendMessage({
11298
- member,
11299
- islevel,
11300
- showAlert,
11301
- coHostResponsibility,
11302
- coHost,
11303
- chatSetting,
11295
+ async sendMessage({ message, receivers, group, messagesLength, member, sender, islevel, showAlert, coHostResponsibility, coHost, roomName, socket, chatSetting, }) {
11296
+ let chatValue = false;
11297
+ const normalizedReceivers = (receivers ?? []).filter((receiver) => typeof receiver === 'string' && receiver.trim().length > 0);
11298
+ if ((messagesLength > 100 && roomName.startsWith('d')) ||
11299
+ (messagesLength > 500 && roomName.startsWith('s')) ||
11300
+ (messagesLength > 100000 && roomName.startsWith('p'))) {
11301
+ showAlert?.({
11302
+ message: 'You have reached the maximum number of messages allowed.',
11303
+ type: 'danger',
11304
+ duration: 3000,
11305
+ });
11306
+ return;
11307
+ }
11308
+ if (!message || message === '') {
11309
+ showAlert?.({
11310
+ message: 'Message is not valid.',
11311
+ type: 'danger',
11312
+ duration: 3000,
11313
+ });
11314
+ return;
11315
+ }
11316
+ if (normalizedReceivers.length < 1 && group === false && islevel === '2') {
11317
+ showAlert?.({
11318
+ message: 'Please select a message to reply to',
11319
+ type: 'danger',
11320
+ duration: 3000,
11321
+ });
11322
+ return;
11323
+ }
11324
+ const messageObject = {
11325
+ sender: sender ? sender : member,
11326
+ receivers: normalizedReceivers,
11304
11327
  message,
11328
+ timestamp: new Date().toLocaleTimeString(),
11329
+ group: group !== undefined && group !== null ? group : false,
11330
+ };
11331
+ try {
11332
+ chatValue = coHostResponsibility.find((item) => item.name === 'chat')?.value ?? false;
11333
+ }
11334
+ catch (error) {
11335
+ console.error(error);
11336
+ }
11337
+ if (!(islevel === '2' || (coHost === member && chatValue === true)) && !chatSetting) {
11338
+ showAlert?.({
11339
+ message: 'You are not allowed to send a message in this event room',
11340
+ type: 'danger',
11341
+ duration: 3000,
11342
+ });
11343
+ return;
11344
+ }
11345
+ socket.emit('sendMessage', {
11346
+ messageObject,
11305
11347
  roomName,
11306
- messagesLength,
11307
- receivers,
11308
- group,
11309
- sender,
11310
- socket,
11311
- eventType: normalizedEventType,
11312
11348
  });
11313
11349
  }
11314
11350
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: SendMessage, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -24350,6 +24386,20 @@ class MessagePanel {
24350
24386
  };
24351
24387
  this.senderId = senderId;
24352
24388
  }
24389
+ getComposerPlaceholder() {
24390
+ if (this.type === 'direct') {
24391
+ if (this.senderId) {
24392
+ return `Send a direct message to ${this.senderId}`;
24393
+ }
24394
+ if (this.directMessageDetails) {
24395
+ return `Send a direct message to ${this.directMessageDetails.name}`;
24396
+ }
24397
+ return this.islevel === '2'
24398
+ ? 'Select a message to reply to'
24399
+ : 'Send a direct message to the host';
24400
+ }
24401
+ return this.eventType === 'chat' ? 'Send a message' : 'Send a message to everyone';
24402
+ }
24353
24403
  async handleSendButton() {
24354
24404
  const message = this.type === 'direct' ? this.directMessageText : this.groupMessageText;
24355
24405
  if (!message) {
@@ -24365,7 +24415,7 @@ class MessagePanel {
24365
24415
  return;
24366
24416
  }
24367
24417
  if (this.type === 'direct' && !this.senderId && this.islevel == '2') {
24368
- this.showAlert?.({ message: 'Please select a user to send a message to.', type: 'danger' });
24418
+ this.showAlert?.({ message: 'Please select a message to reply to.', type: 'danger' });
24369
24419
  return;
24370
24420
  }
24371
24421
  await this.onSendMessagePress({
@@ -24393,11 +24443,11 @@ class MessagePanel {
24393
24443
  this.senderId = null;
24394
24444
  }
24395
24445
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: MessagePanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
24396
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: MessagePanel, isStandalone: true, selector: "app-message-panel", inputs: { messages: "messages", messagesLength: "messagesLength", type: "type", username: "username", onSendMessagePress: "onSendMessagePress", backgroundColor: "backgroundColor", focusedInput: "focusedInput", eventType: "eventType", member: "member", islevel: "islevel", startDirectMessage: "startDirectMessage", updateStartDirectMessage: "updateStartDirectMessage", directMessageDetails: "directMessageDetails", updateDirectMessageDetails: "updateDirectMessageDetails", coHostResponsibility: "coHostResponsibility", coHost: "coHost", roomName: "roomName", socket: "socket", chatSetting: "chatSetting", showAlert: "showAlert" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"message-panel\" [style.background]=\"backgroundColor || 'transparent'\">\r\n <div class=\"message-panel__scroll\">\r\n <div *ngIf=\"!messages?.length\" class=\"message-panel__empty\">\r\n No messages yet.\r\n </div>\r\n\r\n <div\r\n *ngFor=\"let message of messages; let index = index\"\r\n class=\"message-panel__row\"\r\n [class.message-panel__row--self]=\"message.sender === username\"\r\n >\r\n <div class=\"message-panel__meta\">\r\n <span *ngIf=\"message.sender === username && !message.group\" class=\"message-panel__sender\">\r\n To: {{ message.receivers.join(', ') }}\r\n </span>\r\n <span *ngIf=\"message.sender !== username\" class=\"message-panel__sender\">\r\n {{ message.sender }}\r\n </span>\r\n <span class=\"message-panel__time\">{{ message.timestamp }}</span>\r\n <button\r\n *ngIf=\"message.sender !== username && !message.group\"\r\n type=\"button\"\r\n class=\"message-panel__reply\"\r\n (click)=\"openReplyInput(message.sender)\"\r\n aria-label=\"Reply\"\r\n >\r\n <fa-icon [icon]=\"faReply\" size=\"xs\"></fa-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"message-panel__bubble\" [class.message-panel__bubble--self]=\"message.sender === member\">\r\n {{ message.message }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"replyInfo\" class=\"message-panel__replying\">\r\n <span>Replying to</span>\r\n <strong>{{ replyInfo.username }}</strong>\r\n </div>\r\n\r\n <div class=\"message-panel__composer\">\r\n <input\r\n type=\"text\"\r\n class=\"message-panel__input\"\r\n placeholder=\"{{ type === 'direct' ? (focusedInput && startDirectMessage && directMessageDetails ? 'Send a direct message to ' + directMessageDetails.name : 'Select a message to reply to') : (eventType === 'chat' ? 'Send a message' : 'Send a message to everyone') }}\"\r\n maxLength=\"350\"\r\n (input)=\"handleTextInputChange($event)\"\r\n [value]=\"type === 'direct' ? directMessageText : groupMessageText\"\r\n />\r\n <button type=\"button\" class=\"message-panel__send\" (click)=\"handleSendButton()\" aria-label=\"Send message\">\r\n <fa-icon [icon]=\"faPaperPlane\" size=\"sm\"></fa-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".message-panel{display:flex;flex-direction:column;height:100%;max-height:100%;min-height:0;gap:12px;color:var(--ms-modern-text-primary, #e2e8f0);font-family:var(--ms-modern-font-family, \"Segoe UI\", \"Aptos\", sans-serif)}.message-panel__scroll{flex:1;min-height:0;overflow-y:auto;padding-right:4px}.message-panel__empty{padding:18px 12px;text-align:center;color:var(--ms-modern-text-secondary, #94a3b8);font-size:.86rem}.message-panel__row{display:flex;flex-direction:column;align-items:flex-start;gap:5px;margin-bottom:12px}.message-panel__row--self{align-items:flex-end}.message-panel__meta{display:inline-flex;align-items:center;gap:8px;max-width:84%;color:var(--ms-modern-text-secondary, #94a3b8);font-size:.72rem;font-weight:700}.message-panel__sender,.message-panel__time{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.message-panel__reply{width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--ms-modern-border-subtle, rgba(148, 163, 184, .24));border-radius:999px;background:var(--ms-modern-field-background, rgba(15, 23, 42, .48));color:var(--ms-modern-text-primary, #e2e8f0);cursor:pointer}.message-panel__bubble{max-width:min(82%,460px);padding:10px 13px;border-radius:16px 16px 16px 6px;background:color-mix(in srgb,var(--ms-modern-accent, #14b8a6) 18%,transparent);border:1px solid color-mix(in srgb,var(--ms-modern-accent, #14b8a6) 26%,transparent);color:var(--ms-modern-text-primary, #e2e8f0);font-size:.9rem;line-height:1.45;overflow-wrap:anywhere}.message-panel__bubble--self{border-radius:16px 16px 6px;background:color-mix(in srgb,var(--ms-modern-success, #22c55e) 18%,transparent);border-color:color-mix(in srgb,var(--ms-modern-success, #22c55e) 26%,transparent)}.message-panel__replying{display:inline-flex;align-items:center;gap:8px;padding:8px 10px;border-radius:12px;background:color-mix(in srgb,var(--ms-modern-info, #3b82f6) 10%,transparent);border:1px solid color-mix(in srgb,var(--ms-modern-info, #3b82f6) 24%,transparent);color:var(--ms-modern-text-secondary, #94a3b8);font-size:.78rem}.message-panel__replying strong{color:var(--ms-modern-text-primary, #e2e8f0)}.message-panel__composer{display:flex;align-items:center;gap:10px;padding-top:4px}.message-panel__input{flex:1;min-width:0;min-height:44px;padding:0 14px;border:1px solid var(--ms-modern-border-subtle, rgba(148, 163, 184, .24));border-radius:999px;outline:none;background:var(--ms-modern-field-background, rgba(15, 23, 42, .48));color:var(--ms-modern-text-primary, #e2e8f0)}.message-panel__input::placeholder{color:var(--ms-modern-text-secondary, #94a3b8)}.message-panel__send{width:44px;height:44px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:999px;background:var(--ms-modern-accent, #14b8a6);color:#fff;box-shadow:0 10px 24px #0f172a2e;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i2.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"] }, { kind: "ngmodule", type: FormsModule }] });
24446
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: MessagePanel, isStandalone: true, selector: "app-message-panel", inputs: { messages: "messages", messagesLength: "messagesLength", type: "type", username: "username", onSendMessagePress: "onSendMessagePress", backgroundColor: "backgroundColor", focusedInput: "focusedInput", eventType: "eventType", member: "member", islevel: "islevel", startDirectMessage: "startDirectMessage", updateStartDirectMessage: "updateStartDirectMessage", directMessageDetails: "directMessageDetails", updateDirectMessageDetails: "updateDirectMessageDetails", coHostResponsibility: "coHostResponsibility", coHost: "coHost", roomName: "roomName", socket: "socket", chatSetting: "chatSetting", showAlert: "showAlert" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"message-panel\" [style.background]=\"backgroundColor || 'transparent'\">\r\n <div class=\"message-panel__scroll\">\r\n <div *ngIf=\"!messages?.length\" class=\"message-panel__empty\">\r\n No messages yet.\r\n </div>\r\n\r\n <div\r\n *ngFor=\"let message of messages; let index = index\"\r\n class=\"message-panel__row\"\r\n [class.message-panel__row--self]=\"message.sender === username\"\r\n >\r\n <div class=\"message-panel__meta\">\r\n <span *ngIf=\"message.sender === username && !message.group\" class=\"message-panel__sender\">\r\n To: {{ message.receivers.join(', ') }}\r\n </span>\r\n <span *ngIf=\"message.sender !== username\" class=\"message-panel__sender\">\r\n {{ message.sender }}\r\n </span>\r\n <span class=\"message-panel__time\">{{ message.timestamp }}</span>\r\n <button\r\n *ngIf=\"message.sender !== username && !message.group\"\r\n type=\"button\"\r\n class=\"message-panel__reply\"\r\n (click)=\"openReplyInput(message.sender)\"\r\n aria-label=\"Reply\"\r\n >\r\n <fa-icon [icon]=\"faReply\" size=\"xs\"></fa-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"message-panel__bubble\" [class.message-panel__bubble--self]=\"message.sender === member\">\r\n {{ message.message }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"replyInfo\" class=\"message-panel__replying\">\r\n <span>Replying to</span>\r\n <strong>{{ replyInfo.username }}</strong>\r\n </div>\r\n\r\n <div class=\"message-panel__composer\">\r\n <input\r\n type=\"text\"\r\n class=\"message-panel__input\"\r\n [placeholder]=\"getComposerPlaceholder()\"\r\n maxLength=\"350\"\r\n (input)=\"handleTextInputChange($event)\"\r\n [value]=\"type === 'direct' ? directMessageText : groupMessageText\"\r\n />\r\n <button type=\"button\" class=\"message-panel__send\" (click)=\"handleSendButton()\" aria-label=\"Send message\">\r\n <fa-icon [icon]=\"faPaperPlane\" size=\"sm\"></fa-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".message-panel{display:flex;flex-direction:column;height:100%;max-height:100%;min-height:0;gap:12px;color:var(--ms-modern-text-primary, #e2e8f0);font-family:var(--ms-modern-font-family, \"Segoe UI\", \"Aptos\", sans-serif)}.message-panel__scroll{flex:1;min-height:0;overflow-y:auto;padding-right:4px}.message-panel__empty{padding:18px 12px;text-align:center;color:var(--ms-modern-text-secondary, #94a3b8);font-size:.86rem}.message-panel__row{display:flex;flex-direction:column;align-items:flex-start;gap:5px;margin-bottom:12px}.message-panel__row--self{align-items:flex-end}.message-panel__meta{display:inline-flex;align-items:center;gap:8px;max-width:84%;color:var(--ms-modern-text-secondary, #94a3b8);font-size:.72rem;font-weight:700}.message-panel__sender,.message-panel__time{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.message-panel__reply{width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--ms-modern-border-subtle, rgba(148, 163, 184, .24));border-radius:999px;background:var(--ms-modern-field-background, rgba(15, 23, 42, .48));color:var(--ms-modern-text-primary, #e2e8f0);cursor:pointer}.message-panel__bubble{max-width:min(82%,460px);padding:10px 13px;border-radius:16px 16px 16px 6px;background:color-mix(in srgb,var(--ms-modern-accent, #14b8a6) 18%,transparent);border:1px solid color-mix(in srgb,var(--ms-modern-accent, #14b8a6) 26%,transparent);color:var(--ms-modern-text-primary, #e2e8f0);font-size:.9rem;line-height:1.45;overflow-wrap:anywhere}.message-panel__bubble--self{border-radius:16px 16px 6px;background:color-mix(in srgb,var(--ms-modern-success, #22c55e) 18%,transparent);border-color:color-mix(in srgb,var(--ms-modern-success, #22c55e) 26%,transparent)}.message-panel__replying{display:inline-flex;align-items:center;gap:8px;padding:8px 10px;border-radius:12px;background:color-mix(in srgb,var(--ms-modern-info, #3b82f6) 10%,transparent);border:1px solid color-mix(in srgb,var(--ms-modern-info, #3b82f6) 24%,transparent);color:var(--ms-modern-text-secondary, #94a3b8);font-size:.78rem}.message-panel__replying strong{color:var(--ms-modern-text-primary, #e2e8f0)}.message-panel__composer{display:flex;align-items:center;gap:10px;padding-top:4px}.message-panel__input{flex:1;min-width:0;min-height:44px;padding:0 14px;border:1px solid var(--ms-modern-border-subtle, rgba(148, 163, 184, .24));border-radius:999px;outline:none;background:var(--ms-modern-field-background, rgba(15, 23, 42, .48));color:var(--ms-modern-text-primary, #e2e8f0)}.message-panel__input::placeholder{color:var(--ms-modern-text-secondary, #94a3b8)}.message-panel__send{width:44px;height:44px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:999px;background:var(--ms-modern-accent, #14b8a6);color:#fff;box-shadow:0 10px 24px #0f172a2e;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i2.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"] }, { kind: "ngmodule", type: FormsModule }] });
24397
24447
  }
24398
24448
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: MessagePanel, decorators: [{
24399
24449
  type: Component,
24400
- args: [{ selector: 'app-message-panel', imports: [CommonModule, FontAwesomeModule, FormsModule], template: "<div class=\"message-panel\" [style.background]=\"backgroundColor || 'transparent'\">\r\n <div class=\"message-panel__scroll\">\r\n <div *ngIf=\"!messages?.length\" class=\"message-panel__empty\">\r\n No messages yet.\r\n </div>\r\n\r\n <div\r\n *ngFor=\"let message of messages; let index = index\"\r\n class=\"message-panel__row\"\r\n [class.message-panel__row--self]=\"message.sender === username\"\r\n >\r\n <div class=\"message-panel__meta\">\r\n <span *ngIf=\"message.sender === username && !message.group\" class=\"message-panel__sender\">\r\n To: {{ message.receivers.join(', ') }}\r\n </span>\r\n <span *ngIf=\"message.sender !== username\" class=\"message-panel__sender\">\r\n {{ message.sender }}\r\n </span>\r\n <span class=\"message-panel__time\">{{ message.timestamp }}</span>\r\n <button\r\n *ngIf=\"message.sender !== username && !message.group\"\r\n type=\"button\"\r\n class=\"message-panel__reply\"\r\n (click)=\"openReplyInput(message.sender)\"\r\n aria-label=\"Reply\"\r\n >\r\n <fa-icon [icon]=\"faReply\" size=\"xs\"></fa-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"message-panel__bubble\" [class.message-panel__bubble--self]=\"message.sender === member\">\r\n {{ message.message }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"replyInfo\" class=\"message-panel__replying\">\r\n <span>Replying to</span>\r\n <strong>{{ replyInfo.username }}</strong>\r\n </div>\r\n\r\n <div class=\"message-panel__composer\">\r\n <input\r\n type=\"text\"\r\n class=\"message-panel__input\"\r\n placeholder=\"{{ type === 'direct' ? (focusedInput && startDirectMessage && directMessageDetails ? 'Send a direct message to ' + directMessageDetails.name : 'Select a message to reply to') : (eventType === 'chat' ? 'Send a message' : 'Send a message to everyone') }}\"\r\n maxLength=\"350\"\r\n (input)=\"handleTextInputChange($event)\"\r\n [value]=\"type === 'direct' ? directMessageText : groupMessageText\"\r\n />\r\n <button type=\"button\" class=\"message-panel__send\" (click)=\"handleSendButton()\" aria-label=\"Send message\">\r\n <fa-icon [icon]=\"faPaperPlane\" size=\"sm\"></fa-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".message-panel{display:flex;flex-direction:column;height:100%;max-height:100%;min-height:0;gap:12px;color:var(--ms-modern-text-primary, #e2e8f0);font-family:var(--ms-modern-font-family, \"Segoe UI\", \"Aptos\", sans-serif)}.message-panel__scroll{flex:1;min-height:0;overflow-y:auto;padding-right:4px}.message-panel__empty{padding:18px 12px;text-align:center;color:var(--ms-modern-text-secondary, #94a3b8);font-size:.86rem}.message-panel__row{display:flex;flex-direction:column;align-items:flex-start;gap:5px;margin-bottom:12px}.message-panel__row--self{align-items:flex-end}.message-panel__meta{display:inline-flex;align-items:center;gap:8px;max-width:84%;color:var(--ms-modern-text-secondary, #94a3b8);font-size:.72rem;font-weight:700}.message-panel__sender,.message-panel__time{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.message-panel__reply{width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--ms-modern-border-subtle, rgba(148, 163, 184, .24));border-radius:999px;background:var(--ms-modern-field-background, rgba(15, 23, 42, .48));color:var(--ms-modern-text-primary, #e2e8f0);cursor:pointer}.message-panel__bubble{max-width:min(82%,460px);padding:10px 13px;border-radius:16px 16px 16px 6px;background:color-mix(in srgb,var(--ms-modern-accent, #14b8a6) 18%,transparent);border:1px solid color-mix(in srgb,var(--ms-modern-accent, #14b8a6) 26%,transparent);color:var(--ms-modern-text-primary, #e2e8f0);font-size:.9rem;line-height:1.45;overflow-wrap:anywhere}.message-panel__bubble--self{border-radius:16px 16px 6px;background:color-mix(in srgb,var(--ms-modern-success, #22c55e) 18%,transparent);border-color:color-mix(in srgb,var(--ms-modern-success, #22c55e) 26%,transparent)}.message-panel__replying{display:inline-flex;align-items:center;gap:8px;padding:8px 10px;border-radius:12px;background:color-mix(in srgb,var(--ms-modern-info, #3b82f6) 10%,transparent);border:1px solid color-mix(in srgb,var(--ms-modern-info, #3b82f6) 24%,transparent);color:var(--ms-modern-text-secondary, #94a3b8);font-size:.78rem}.message-panel__replying strong{color:var(--ms-modern-text-primary, #e2e8f0)}.message-panel__composer{display:flex;align-items:center;gap:10px;padding-top:4px}.message-panel__input{flex:1;min-width:0;min-height:44px;padding:0 14px;border:1px solid var(--ms-modern-border-subtle, rgba(148, 163, 184, .24));border-radius:999px;outline:none;background:var(--ms-modern-field-background, rgba(15, 23, 42, .48));color:var(--ms-modern-text-primary, #e2e8f0)}.message-panel__input::placeholder{color:var(--ms-modern-text-secondary, #94a3b8)}.message-panel__send{width:44px;height:44px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:999px;background:var(--ms-modern-accent, #14b8a6);color:#fff;box-shadow:0 10px 24px #0f172a2e;cursor:pointer}\n"] }]
24450
+ args: [{ selector: 'app-message-panel', imports: [CommonModule, FontAwesomeModule, FormsModule], template: "<div class=\"message-panel\" [style.background]=\"backgroundColor || 'transparent'\">\r\n <div class=\"message-panel__scroll\">\r\n <div *ngIf=\"!messages?.length\" class=\"message-panel__empty\">\r\n No messages yet.\r\n </div>\r\n\r\n <div\r\n *ngFor=\"let message of messages; let index = index\"\r\n class=\"message-panel__row\"\r\n [class.message-panel__row--self]=\"message.sender === username\"\r\n >\r\n <div class=\"message-panel__meta\">\r\n <span *ngIf=\"message.sender === username && !message.group\" class=\"message-panel__sender\">\r\n To: {{ message.receivers.join(', ') }}\r\n </span>\r\n <span *ngIf=\"message.sender !== username\" class=\"message-panel__sender\">\r\n {{ message.sender }}\r\n </span>\r\n <span class=\"message-panel__time\">{{ message.timestamp }}</span>\r\n <button\r\n *ngIf=\"message.sender !== username && !message.group\"\r\n type=\"button\"\r\n class=\"message-panel__reply\"\r\n (click)=\"openReplyInput(message.sender)\"\r\n aria-label=\"Reply\"\r\n >\r\n <fa-icon [icon]=\"faReply\" size=\"xs\"></fa-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"message-panel__bubble\" [class.message-panel__bubble--self]=\"message.sender === member\">\r\n {{ message.message }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"replyInfo\" class=\"message-panel__replying\">\r\n <span>Replying to</span>\r\n <strong>{{ replyInfo.username }}</strong>\r\n </div>\r\n\r\n <div class=\"message-panel__composer\">\r\n <input\r\n type=\"text\"\r\n class=\"message-panel__input\"\r\n [placeholder]=\"getComposerPlaceholder()\"\r\n maxLength=\"350\"\r\n (input)=\"handleTextInputChange($event)\"\r\n [value]=\"type === 'direct' ? directMessageText : groupMessageText\"\r\n />\r\n <button type=\"button\" class=\"message-panel__send\" (click)=\"handleSendButton()\" aria-label=\"Send message\">\r\n <fa-icon [icon]=\"faPaperPlane\" size=\"sm\"></fa-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".message-panel{display:flex;flex-direction:column;height:100%;max-height:100%;min-height:0;gap:12px;color:var(--ms-modern-text-primary, #e2e8f0);font-family:var(--ms-modern-font-family, \"Segoe UI\", \"Aptos\", sans-serif)}.message-panel__scroll{flex:1;min-height:0;overflow-y:auto;padding-right:4px}.message-panel__empty{padding:18px 12px;text-align:center;color:var(--ms-modern-text-secondary, #94a3b8);font-size:.86rem}.message-panel__row{display:flex;flex-direction:column;align-items:flex-start;gap:5px;margin-bottom:12px}.message-panel__row--self{align-items:flex-end}.message-panel__meta{display:inline-flex;align-items:center;gap:8px;max-width:84%;color:var(--ms-modern-text-secondary, #94a3b8);font-size:.72rem;font-weight:700}.message-panel__sender,.message-panel__time{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.message-panel__reply{width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--ms-modern-border-subtle, rgba(148, 163, 184, .24));border-radius:999px;background:var(--ms-modern-field-background, rgba(15, 23, 42, .48));color:var(--ms-modern-text-primary, #e2e8f0);cursor:pointer}.message-panel__bubble{max-width:min(82%,460px);padding:10px 13px;border-radius:16px 16px 16px 6px;background:color-mix(in srgb,var(--ms-modern-accent, #14b8a6) 18%,transparent);border:1px solid color-mix(in srgb,var(--ms-modern-accent, #14b8a6) 26%,transparent);color:var(--ms-modern-text-primary, #e2e8f0);font-size:.9rem;line-height:1.45;overflow-wrap:anywhere}.message-panel__bubble--self{border-radius:16px 16px 6px;background:color-mix(in srgb,var(--ms-modern-success, #22c55e) 18%,transparent);border-color:color-mix(in srgb,var(--ms-modern-success, #22c55e) 26%,transparent)}.message-panel__replying{display:inline-flex;align-items:center;gap:8px;padding:8px 10px;border-radius:12px;background:color-mix(in srgb,var(--ms-modern-info, #3b82f6) 10%,transparent);border:1px solid color-mix(in srgb,var(--ms-modern-info, #3b82f6) 24%,transparent);color:var(--ms-modern-text-secondary, #94a3b8);font-size:.78rem}.message-panel__replying strong{color:var(--ms-modern-text-primary, #e2e8f0)}.message-panel__composer{display:flex;align-items:center;gap:10px;padding-top:4px}.message-panel__input{flex:1;min-width:0;min-height:44px;padding:0 14px;border:1px solid var(--ms-modern-border-subtle, rgba(148, 163, 184, .24));border-radius:999px;outline:none;background:var(--ms-modern-field-background, rgba(15, 23, 42, .48));color:var(--ms-modern-text-primary, #e2e8f0)}.message-panel__input::placeholder{color:var(--ms-modern-text-secondary, #94a3b8)}.message-panel__send{width:44px;height:44px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:999px;background:var(--ms-modern-accent, #14b8a6);color:#fff;box-shadow:0 10px 24px #0f172a2e;cursor:pointer}\n"] }]
24401
24451
  }], propDecorators: { messages: [{
24402
24452
  type: Input
24403
24453
  }], messagesLength: [{