@acorex/modules 20.6.0-next.7 → 20.6.0-next.9
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/conversation/index.d.ts +77 -240
- package/fesm2022/acorex-modules-conversation.mjs +193 -1750
- package/fesm2022/acorex-modules-conversation.mjs.map +1 -1
- package/fesm2022/{acorex-modules-dashboard-management-acorex-modules-dashboard-management-BXVW5pTF.mjs → acorex-modules-dashboard-management-acorex-modules-dashboard-management-JeQW5e5t.mjs} +4 -4
- package/fesm2022/{acorex-modules-dashboard-management-acorex-modules-dashboard-management-BXVW5pTF.mjs.map → acorex-modules-dashboard-management-acorex-modules-dashboard-management-JeQW5e5t.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-dashboard-management-permission-definition.provider-DTQ1D_Uh.mjs → acorex-modules-dashboard-management-permission-definition.provider-CP1sPn-5.mjs} +2 -2
- package/fesm2022/{acorex-modules-dashboard-management-permission-definition.provider-DTQ1D_Uh.mjs.map → acorex-modules-dashboard-management-permission-definition.provider-CP1sPn-5.mjs.map} +1 -1
- package/fesm2022/acorex-modules-dashboard-management.mjs +1 -1
- package/fesm2022/{acorex-modules-data-management-acorex-modules-data-management-Ci9W347D.mjs → acorex-modules-data-management-acorex-modules-data-management-BTZVbtCd.mjs} +4 -4
- package/fesm2022/acorex-modules-data-management-acorex-modules-data-management-BTZVbtCd.mjs.map +1 -0
- package/fesm2022/{acorex-modules-data-management-permission-definition.provider-BmfgERqu.mjs → acorex-modules-data-management-permission-definition.provider-Ba0RXefU.mjs} +2 -2
- package/fesm2022/{acorex-modules-data-management-permission-definition.provider-BmfgERqu.mjs.map → acorex-modules-data-management-permission-definition.provider-Ba0RXefU.mjs.map} +1 -1
- package/fesm2022/acorex-modules-data-management.mjs +1 -1
- package/fesm2022/{acorex-modules-document-management-acorex-modules-document-management-CTpQGWrH.mjs → acorex-modules-document-management-acorex-modules-document-management-ZU1fqI_q.mjs} +37 -27
- package/fesm2022/acorex-modules-document-management-acorex-modules-document-management-ZU1fqI_q.mjs.map +1 -0
- package/fesm2022/{acorex-modules-document-management-attachment-widget.component-DHnJ-wG_.mjs → acorex-modules-document-management-attachment-widget.component-DMCcZ53H.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-attachment-widget.component-DHnJ-wG_.mjs.map → acorex-modules-document-management-attachment-widget.component-DMCcZ53H.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-details-view.component-D4LY1WdL.mjs → acorex-modules-document-management-details-view.component-iov9ayCy.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-details-view.component-D4LY1WdL.mjs.map → acorex-modules-document-management-details-view.component-iov9ayCy.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-document-signature-popup.component-rsZh53Ys.mjs → acorex-modules-document-management-document-signature-popup.component-DoeU-5S2.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-document-signature-popup.component-rsZh53Ys.mjs.map → acorex-modules-document-management-document-signature-popup.component-DoeU-5S2.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-drive-choose.component-Lc6Kjy_S.mjs → acorex-modules-document-management-drive-choose.component-0UN17SNF.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-drive-choose.component-Lc6Kjy_S.mjs.map → acorex-modules-document-management-drive-choose.component-0UN17SNF.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-drive.component-D8MZClH0.mjs → acorex-modules-document-management-drive.component-DzikECQB.mjs} +3 -3
- package/fesm2022/acorex-modules-document-management-drive.component-DzikECQB.mjs.map +1 -0
- package/fesm2022/{acorex-modules-document-management-large-icons-view.component-BkZfQg0H.mjs → acorex-modules-document-management-large-icons-view.component-B2zaP-ye.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-large-icons-view.component-BkZfQg0H.mjs.map → acorex-modules-document-management-large-icons-view.component-B2zaP-ye.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-large-tiles-view.component-DSnB8pwb.mjs → acorex-modules-document-management-large-tiles-view.component-h0N92C7a.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-large-tiles-view.component-DSnB8pwb.mjs.map → acorex-modules-document-management-large-tiles-view.component-h0N92C7a.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-list-view.component-CCWk2Ulv.mjs → acorex-modules-document-management-list-view.component-Cq-FBKuo.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-list-view.component-CCWk2Ulv.mjs.map → acorex-modules-document-management-list-view.component-Cq-FBKuo.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-permission-definition.provider-BC7Og6_y.mjs → acorex-modules-document-management-permission-definition.provider-DWID2ajQ.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-permission-definition.provider-BC7Og6_y.mjs.map → acorex-modules-document-management-permission-definition.provider-DWID2ajQ.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-small-icons-view.component-D6hWuJG8.mjs → acorex-modules-document-management-small-icons-view.component-Crb7NDuY.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-small-icons-view.component-D6hWuJG8.mjs.map → acorex-modules-document-management-small-icons-view.component-Crb7NDuY.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-small-tiles-view.component-DVEftaGK.mjs → acorex-modules-document-management-small-tiles-view.component-AhGebx78.mjs} +2 -2
- package/fesm2022/{acorex-modules-document-management-small-tiles-view.component-DVEftaGK.mjs.map → acorex-modules-document-management-small-tiles-view.component-AhGebx78.mjs.map} +1 -1
- package/fesm2022/acorex-modules-document-management.mjs +1 -1
- package/fesm2022/acorex-modules-locale-management.mjs +1 -1
- package/fesm2022/acorex-modules-locale-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-notification-management-notification-page.component-BTSv9-bI.mjs → acorex-modules-notification-management-notification-page.component-Lz8J7q4k.mjs} +2 -2
- package/fesm2022/acorex-modules-notification-management-notification-page.component-Lz8J7q4k.mjs.map +1 -0
- package/fesm2022/acorex-modules-notification-management.mjs +1 -1
- package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-Nq9gX7zW.mjs → acorex-modules-platform-management-acorex-modules-platform-management-BSFwJPkW.mjs} +5 -5
- package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-Nq9gX7zW.mjs.map → acorex-modules-platform-management-acorex-modules-platform-management-BSFwJPkW.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-platform-management-list-version.component-CtJOnijq.mjs → acorex-modules-platform-management-list-version.component-CcrYZek9.mjs} +2 -2
- package/fesm2022/{acorex-modules-platform-management-list-version.component-CtJOnijq.mjs.map → acorex-modules-platform-management-list-version.component-CcrYZek9.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-platform-management-menu-list.component-BwnDs_72.mjs → acorex-modules-platform-management-menu-list.component-CaQSt7lg.mjs} +3 -3
- package/fesm2022/acorex-modules-platform-management-menu-list.component-CaQSt7lg.mjs.map +1 -0
- package/fesm2022/{acorex-modules-platform-management-permission-definition.provider-DJ5bCaS9.mjs → acorex-modules-platform-management-permission-definition.provider-Oa9-EQjN.mjs} +2 -2
- package/fesm2022/{acorex-modules-platform-management-permission-definition.provider-DJ5bCaS9.mjs.map → acorex-modules-platform-management-permission-definition.provider-Oa9-EQjN.mjs.map} +1 -1
- package/fesm2022/acorex-modules-platform-management.mjs +1 -1
- package/fesm2022/acorex-modules-report-management.mjs +2 -2
- package/fesm2022/acorex-modules-report-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-security-management-acorex-modules-security-management-B6bWjwlY.mjs → acorex-modules-security-management-acorex-modules-security-management-Dh6b7amt.mjs} +32 -48
- package/fesm2022/{acorex-modules-security-management-acorex-modules-security-management-B6bWjwlY.mjs.map → acorex-modules-security-management-acorex-modules-security-management-Dh6b7amt.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-security-management-permission-definition.provider-DPI8gT7K.mjs → acorex-modules-security-management-permission-definition.provider-DJvuPqFx.mjs} +2 -2
- package/fesm2022/{acorex-modules-security-management-permission-definition.provider-DPI8gT7K.mjs.map → acorex-modules-security-management-permission-definition.provider-DJvuPqFx.mjs.map} +1 -1
- package/fesm2022/acorex-modules-security-management.mjs +1 -1
- package/package.json +10 -10
- package/report-management/index.d.ts +3 -4
- package/fesm2022/acorex-modules-data-management-acorex-modules-data-management-Ci9W347D.mjs.map +0 -1
- package/fesm2022/acorex-modules-document-management-acorex-modules-document-management-CTpQGWrH.mjs.map +0 -1
- package/fesm2022/acorex-modules-document-management-drive.component-D8MZClH0.mjs.map +0 -1
- package/fesm2022/acorex-modules-notification-management-notification-page.component-BTSv9-bI.mjs.map +0 -1
- package/fesm2022/acorex-modules-platform-management-menu-list.component-BwnDs_72.mjs.map +0 -1
|
@@ -1,72 +1,54 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { AXConversationModule, AXConversationInputComponent } from '@acorex/components/conversation';
|
|
1
|
+
import { AXConversationModule } from '@acorex/components/conversation';
|
|
3
2
|
import { AXPSessionService, AXPAuthGuard, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex/platform/auth';
|
|
4
|
-
import { AXMEntityCrudServiceImpl, entityMasterCrudActions, entityMasterRecordActions,
|
|
3
|
+
import { AXMEntityCrudServiceImpl, entityMasterCrudActions, entityMasterRecordActions, ensureListActions, actionExists, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
5
4
|
import { AXPRootLayoutComponent } from '@acorex/platform/themes/default';
|
|
6
|
-
import * as
|
|
7
|
-
import {
|
|
5
|
+
import * as i3 from '@angular/common';
|
|
6
|
+
import { CommonModule, AsyncPipe, DatePipe } from '@angular/common';
|
|
8
7
|
import * as i0 from '@angular/core';
|
|
9
|
-
import { Injectable, NgModule, inject,
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import * as i1$3 from '@acorex/platform/layout/widget-core';
|
|
8
|
+
import { Injectable, NgModule, inject, signal, computed, effect, ChangeDetectionStrategy, Component, input, viewChild, DestroyRef, ViewEncapsulation, output, Injector, importProvidersFrom } from '@angular/core';
|
|
9
|
+
import { Router, ActivatedRoute, RouterModule, ROUTES } from '@angular/router';
|
|
10
|
+
import { createAllQueryView, AXPEntityQueryType, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, AXP_MENU_PROVIDER } from '@acorex/platform/common';
|
|
11
|
+
import * as i1$2 from '@acorex/platform/layout/widget-core';
|
|
14
12
|
import { AXPWidgetsCatalog, AXPValueWidgetComponent, AXPWidgetGroupEnum, AXPWidgetCoreModule } from '@acorex/platform/layout/widget-core';
|
|
15
|
-
import {
|
|
16
|
-
import * as i2$
|
|
13
|
+
import { AXPThemeLayoutBlockComponent, AXPThemeLayoutStartSideComponent, AXPThemeLayoutHeaderComponent, AXPUserAvatarComponent, AXP_TASK_BADGE_PROVIDERS } from '@acorex/platform/layout/components';
|
|
14
|
+
import * as i2$1 from '@acorex/platform/workflow';
|
|
17
15
|
import { AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
18
16
|
import { AXMNotificationConnectorService, AXP_NOTIFICATION_DEFINITION_PROVIDER } from '@acorex/modules/notification-management';
|
|
19
17
|
import { AXMUsersEntityService } from '@acorex/modules/security-management';
|
|
20
|
-
import { Subject, filter
|
|
21
|
-
import * as
|
|
22
|
-
import {
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import * as i5$1 from '@acorex/components/button';
|
|
26
|
-
import { AXButtonModule } from '@acorex/components/button';
|
|
27
|
-
import * as i4$2 from '@acorex/components/comment';
|
|
28
|
-
import { AXCommentModule } from '@acorex/components/comment';
|
|
29
|
-
import * as i5 from '@acorex/components/decorators';
|
|
18
|
+
import { Subject, filter } from 'rxjs';
|
|
19
|
+
import * as i5 from '@acorex/components/button';
|
|
20
|
+
import { AXButtonComponent, AXButtonModule } from '@acorex/components/button';
|
|
21
|
+
import { AXConversationService, AXConversationContainerDirective, AXSidebarComponent, AXInfoBarComponent, AXMessageListComponent, AXComposerComponent, provideConversation, AX_CONVERSATION_ITEM_MUTE_ACTION, AX_CONVERSATION_ITEM_PIN_ACTION, AX_CONVERSATION_ITEM_MARK_READ_ACTION, AX_CONVERSATION_ITEM_DIVIDER, AX_CONVERSATION_ITEM_DELETE_ACTION, AX_CONVERSATION_ITEM_BLOCK_ACTION, AX_CONVERSATION_INFO_BAR_SEARCH_ACTION, AX_CONVERSATION_INFO_BAR_INFO_ACTION, AX_CONVERSATION_INFO_BAR_MUTE_ACTION, AX_CONVERSATION_INFO_BAR_DIVIDER, AX_CONVERSATION_INFO_BAR_DELETE_ACTION, AX_CONVERSATION_INFO_BAR_BLOCK_ACTION, AX_CONVERSATION_TAB_ALL, AX_CONVERSATION_TAB_PRIVATE, AX_CONVERSATION_TAB_GROUPS, AX_CONVERSATION_TAB_CHANNELS, AX_CONVERSATION_TAB_UNREAD, AX_CONVERSATION_TAB_ARCHIVED, AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_STICKER_TAB, AX_CONVERSATION_COMPOSER_EMOJI_ACTION, AX_CONVERSATION_COMPOSER_IMAGE_ACTION, AX_CONVERSATION_COMPOSER_VIDEO_ACTION, AX_CONVERSATION_COMPOSER_FILE_ACTION, AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION, AX_CONVERSATION_COMPOSER_AUDIO_ACTION, AX_CONVERSATION_COMPOSER_CONTACT_ACTION, AX_CONVERSATION_COMPOSER_LOCATION_ACTION, AX_CONVERSATION_MESSAGE_REPLY_ACTION, AX_CONVERSATION_MESSAGE_FORWARD_ACTION, AX_CONVERSATION_MESSAGE_EDIT_ACTION, AX_CONVERSATION_MESSAGE_DELETE_ACTION, AX_CONVERSATION_TEXT_RENDERER, AX_CONVERSATION_IMAGE_RENDERER, AX_CONVERSATION_VIDEO_RENDERER, AX_CONVERSATION_AUDIO_RENDERER, AX_CONVERSATION_VOICE_RENDERER, AX_CONVERSATION_FILE_RENDERER, AX_CONVERSATION_LOCATION_RENDERER, AX_CONVERSATION_STICKER_RENDERER, AX_CONVERSATION_CONTACT_RENDERER, AXIndexedDBRealtimeApi, AXIndexedDBMessageAIApi, AXIndexedDBConversationApi, AXIndexedDBUserApi } from '@acorex/components/conversation2';
|
|
22
|
+
import * as i1 from '@acorex/components/decorators';
|
|
30
23
|
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
24
|
+
import * as i4$1 from '@acorex/core/translation';
|
|
25
|
+
import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
|
|
26
|
+
import { AXPPageLayoutComponent } from '@acorex/platform/layout/views';
|
|
27
|
+
import * as i1$1 from '@acorex/components/wysiwyg';
|
|
28
|
+
import { AXWysiwygModule } from '@acorex/components/wysiwyg';
|
|
31
29
|
import { AXDialogService } from '@acorex/components/dialog';
|
|
32
|
-
import
|
|
30
|
+
import { AXToastService } from '@acorex/components/toast';
|
|
31
|
+
import { trigger, transition, style, animate } from '@angular/animations';
|
|
32
|
+
import { DomSanitizer } from '@angular/platform-browser';
|
|
33
|
+
import { AXAvatarModule } from '@acorex/components/avatar';
|
|
34
|
+
import * as i4 from '@acorex/components/comment';
|
|
35
|
+
import { AXCommentModule } from '@acorex/components/comment';
|
|
36
|
+
import * as i7 from '@acorex/components/dropdown';
|
|
33
37
|
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
34
|
-
import * as i9
|
|
38
|
+
import * as i9 from '@acorex/components/dropdown-button';
|
|
35
39
|
import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
|
|
36
40
|
import { AXFormModule } from '@acorex/components/form';
|
|
37
41
|
import { AXImageModule } from '@acorex/components/image';
|
|
38
|
-
import
|
|
39
|
-
import * as i3$1 from '@acorex/components/loading';
|
|
42
|
+
import * as i6 from '@acorex/components/loading';
|
|
40
43
|
import { AXLoadingModule } from '@acorex/components/loading';
|
|
41
|
-
import
|
|
42
|
-
import * as i6 from '@acorex/components/search-box';
|
|
43
|
-
import { AXSearchBoxModule } from '@acorex/components/search-box';
|
|
44
|
-
import { AXSelectBoxModule } from '@acorex/components/select-box';
|
|
45
|
-
import * as i9 from '@acorex/components/skeleton';
|
|
44
|
+
import * as i2 from '@acorex/components/skeleton';
|
|
46
45
|
import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
47
|
-
import * as i4$1 from '@acorex/components/sliding-item';
|
|
48
|
-
import { AXSlidingItemModule } from '@acorex/components/sliding-item';
|
|
49
|
-
import * as i7 from '@acorex/components/tabs';
|
|
50
|
-
import { AXTabsModule } from '@acorex/components/tabs';
|
|
51
|
-
import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
52
46
|
import { AXToolBarModule } from '@acorex/components/toolbar';
|
|
53
|
-
import * as i1$2 from '@acorex/components/wysiwyg';
|
|
54
|
-
import { AXWysiwygModule } from '@acorex/components/wysiwyg';
|
|
55
47
|
import * as i10 from '@acorex/core/format';
|
|
56
48
|
import { AXFormatModule } from '@acorex/core/format';
|
|
57
|
-
import * as i4 from '@acorex/core/translation';
|
|
58
|
-
import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
|
|
59
|
-
import { AXUnsubscriber } from '@acorex/core/utils';
|
|
60
|
-
import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
|
|
61
|
-
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageLayoutBase } from '@acorex/platform/layout/views';
|
|
62
|
-
import { trigger, transition, style, animate } from '@angular/animations';
|
|
63
|
-
import * as i1$1 from '@angular/forms';
|
|
64
|
-
import { FormsModule } from '@angular/forms';
|
|
65
|
-
import { AXDomChangeDirective } from '@acorex/cdk/dom';
|
|
66
|
-
import { AXToastService } from '@acorex/components/toast';
|
|
67
|
-
import { AXFileService } from '@acorex/core/file';
|
|
68
|
-
import { DomSanitizer } from '@angular/platform-browser';
|
|
69
49
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
50
|
+
import * as i8 from '@angular/forms';
|
|
51
|
+
import { FormsModule } from '@angular/forms';
|
|
70
52
|
import { AXBasePageComponent } from '@acorex/components/page';
|
|
71
53
|
import { AXPopupService } from '@acorex/components/popup';
|
|
72
54
|
|
|
@@ -1487,1719 +1469,180 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
1487
1469
|
}]
|
|
1488
1470
|
}] });
|
|
1489
1471
|
|
|
1490
|
-
class
|
|
1472
|
+
class AXMChatComponent {
|
|
1491
1473
|
constructor() {
|
|
1492
|
-
|
|
1493
|
-
this.
|
|
1494
|
-
this.
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
this.fileStorage = inject(AXPFileStorageService);
|
|
1502
|
-
this.chatName = signal({
|
|
1503
|
-
fullName: 'Loading...',
|
|
1504
|
-
id: '',
|
|
1505
|
-
isPrivate: false,
|
|
1506
|
-
}, ...(ngDevMode ? [{ debugName: "chatName" }] : []));
|
|
1507
|
-
this.#chatInfoEffect = effect(async () => {
|
|
1508
|
-
const { members, title, id } = this.data();
|
|
1509
|
-
if (members.length > 1) {
|
|
1510
|
-
this.chatName.set({
|
|
1511
|
-
fullName: title || 'Group Chat',
|
|
1512
|
-
id,
|
|
1513
|
-
isPrivate: false,
|
|
1514
|
-
});
|
|
1515
|
-
return;
|
|
1516
|
-
}
|
|
1517
|
-
const member = members[0];
|
|
1518
|
-
if (!member) {
|
|
1519
|
-
this.chatName.set({ fullName: 'Unknown User', id: '', isPrivate: true });
|
|
1520
|
-
return;
|
|
1521
|
-
}
|
|
1522
|
-
this.chatName.set({
|
|
1523
|
-
fullName: member.fullName || 'Unknown User',
|
|
1524
|
-
id: member.id,
|
|
1525
|
-
isPrivate: true,
|
|
1526
|
-
});
|
|
1527
|
-
}, ...(ngDevMode ? [{ debugName: "#chatInfoEffect" }] : []));
|
|
1528
|
-
// Group avatar preview handling
|
|
1529
|
-
this.groupAvatarUrl = signal(null, ...(ngDevMode ? [{ debugName: "groupAvatarUrl" }] : []));
|
|
1530
|
-
this.groupBlobUrl = signal(null, ...(ngDevMode ? [{ debugName: "groupBlobUrl" }] : []));
|
|
1531
|
-
this.isGroupAvatarLoading = signal(true, ...(ngDevMode ? [{ debugName: "isGroupAvatarLoading" }] : []));
|
|
1532
|
-
this.#groupAvatarEffect = effect(async () => {
|
|
1533
|
-
const room = this.data();
|
|
1534
|
-
// Only for group chats
|
|
1535
|
-
if (!room || (room.members?.length ?? 0) <= 1) {
|
|
1536
|
-
this.groupAvatarUrl.set(null);
|
|
1537
|
-
this.isGroupAvatarLoading.set(false);
|
|
1538
|
-
return;
|
|
1539
|
-
}
|
|
1540
|
-
const avatar = room.avatar;
|
|
1541
|
-
if (!avatar) {
|
|
1542
|
-
this.groupAvatarUrl.set(null);
|
|
1543
|
-
this.isGroupAvatarLoading.set(false);
|
|
1544
|
-
return;
|
|
1474
|
+
this.conversationService = inject(AXConversationService);
|
|
1475
|
+
this.mobileView = signal('list', ...(ngDevMode ? [{ debugName: "mobileView" }] : []));
|
|
1476
|
+
this.hasActiveConversation = computed(() => {
|
|
1477
|
+
return this.conversationService.activeConversationId() !== null;
|
|
1478
|
+
}, ...(ngDevMode ? [{ debugName: "hasActiveConversation" }] : []));
|
|
1479
|
+
effect(() => {
|
|
1480
|
+
const activeId = this.conversationService.activeConversationId();
|
|
1481
|
+
if (activeId && this.isMobile()) {
|
|
1482
|
+
this.mobileView.set('chat');
|
|
1545
1483
|
}
|
|
1546
|
-
if (typeof avatar === 'string') {
|
|
1547
|
-
const val = avatar.trim();
|
|
1548
|
-
// Resolve stored file identifiers like "file:<id>" or bare file IDs
|
|
1549
|
-
if (val.startsWith('file:')) {
|
|
1550
|
-
try {
|
|
1551
|
-
const fileId = val.substring(5);
|
|
1552
|
-
const info = await this.fileStorage.getInfo(fileId);
|
|
1553
|
-
const url = info?.url ? String(info.url) : null;
|
|
1554
|
-
if (url) {
|
|
1555
|
-
await this.preloadAndSetGroupAvatar(url);
|
|
1556
|
-
}
|
|
1557
|
-
else {
|
|
1558
|
-
this.groupAvatarUrl.set(null);
|
|
1559
|
-
this.isGroupAvatarLoading.set(false);
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
catch {
|
|
1563
|
-
this.groupAvatarUrl.set(null);
|
|
1564
|
-
this.isGroupAvatarLoading.set(false);
|
|
1565
|
-
}
|
|
1566
|
-
return;
|
|
1567
|
-
}
|
|
1568
|
-
// If it's a full URL or data URI, use as-is; otherwise treat as a fileId
|
|
1569
|
-
if (/^(https?:)?\/\//i.test(val) || val.startsWith('data:')) {
|
|
1570
|
-
await this.preloadAndSetGroupAvatar(val);
|
|
1571
|
-
return;
|
|
1572
|
-
}
|
|
1573
|
-
try {
|
|
1574
|
-
const info = await this.fileStorage.getInfo(val);
|
|
1575
|
-
const url = info?.url ? String(info.url) : null;
|
|
1576
|
-
if (url) {
|
|
1577
|
-
await this.preloadAndSetGroupAvatar(url);
|
|
1578
|
-
}
|
|
1579
|
-
else {
|
|
1580
|
-
this.groupAvatarUrl.set(null);
|
|
1581
|
-
this.isGroupAvatarLoading.set(false);
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
catch {
|
|
1585
|
-
this.groupAvatarUrl.set(null);
|
|
1586
|
-
this.isGroupAvatarLoading.set(false);
|
|
1587
|
-
}
|
|
1588
|
-
return;
|
|
1589
|
-
}
|
|
1590
|
-
const source = avatar.source;
|
|
1591
|
-
if (!source) {
|
|
1592
|
-
this.groupAvatarUrl.set(null);
|
|
1593
|
-
this.isGroupAvatarLoading.set(false);
|
|
1594
|
-
return;
|
|
1595
|
-
}
|
|
1596
|
-
switch (source.kind) {
|
|
1597
|
-
case 'url':
|
|
1598
|
-
await this.preloadAndSetGroupAvatar(String(source.value));
|
|
1599
|
-
return;
|
|
1600
|
-
case 'blob': {
|
|
1601
|
-
const prev = this.groupBlobUrl();
|
|
1602
|
-
if (prev)
|
|
1603
|
-
URL.revokeObjectURL(prev);
|
|
1604
|
-
const blob = source.value;
|
|
1605
|
-
const next = URL.createObjectURL(blob);
|
|
1606
|
-
this.groupBlobUrl.set(next);
|
|
1607
|
-
await this.preloadAndSetGroupAvatar(next);
|
|
1608
|
-
return;
|
|
1609
|
-
}
|
|
1610
|
-
case 'fileId': {
|
|
1611
|
-
try {
|
|
1612
|
-
const info = await this.fileStorage.getInfo(String(source.value));
|
|
1613
|
-
const url = info?.url ? String(info.url) : null;
|
|
1614
|
-
if (url) {
|
|
1615
|
-
await this.preloadAndSetGroupAvatar(url);
|
|
1616
|
-
}
|
|
1617
|
-
else {
|
|
1618
|
-
this.groupAvatarUrl.set(null);
|
|
1619
|
-
this.isGroupAvatarLoading.set(false);
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
catch {
|
|
1623
|
-
this.groupAvatarUrl.set(null);
|
|
1624
|
-
this.isGroupAvatarLoading.set(false);
|
|
1625
|
-
}
|
|
1626
|
-
return;
|
|
1627
|
-
}
|
|
1628
|
-
default:
|
|
1629
|
-
this.groupAvatarUrl.set(null);
|
|
1630
|
-
this.isGroupAvatarLoading.set(false);
|
|
1631
|
-
return;
|
|
1632
|
-
}
|
|
1633
|
-
}, ...(ngDevMode ? [{ debugName: "#groupAvatarEffect" }] : []));
|
|
1634
|
-
this.formattedLastMessageDate = computed(() => {
|
|
1635
|
-
const lastMessage = this.data().lastMessage;
|
|
1636
|
-
const createdAt = lastMessage?.auditInfo?.created?.at;
|
|
1637
|
-
if (!createdAt) {
|
|
1638
|
-
return '';
|
|
1639
|
-
}
|
|
1640
|
-
const messageDate = new Date(createdAt);
|
|
1641
|
-
const today = new Date();
|
|
1642
|
-
const isToday = messageDate.getFullYear() === today.getFullYear() &&
|
|
1643
|
-
messageDate.getMonth() === today.getMonth() &&
|
|
1644
|
-
messageDate.getDate() === today.getDate();
|
|
1645
|
-
if (isToday) {
|
|
1646
|
-
return this.datePipe.transform(messageDate, 'shortTime');
|
|
1647
|
-
}
|
|
1648
|
-
else {
|
|
1649
|
-
return this.datePipe.transform(messageDate, 'mediumDate');
|
|
1650
|
-
}
|
|
1651
|
-
}, ...(ngDevMode ? [{ debugName: "formattedLastMessageDate" }] : []));
|
|
1652
|
-
this.lastMessage = computed(() => {
|
|
1653
|
-
const message = this.data().lastMessage;
|
|
1654
|
-
if (!message)
|
|
1655
|
-
return { content: 'No messages yet', contentType: 'text', reactions: [] };
|
|
1656
|
-
return {
|
|
1657
|
-
content: message.message.contentType === 'text' ? message.message.content : message.message.contentType,
|
|
1658
|
-
contentType: message.message.contentType,
|
|
1659
|
-
reactions: message.reactions || [],
|
|
1660
|
-
author: message.author,
|
|
1661
|
-
};
|
|
1662
|
-
}, ...(ngDevMode ? [{ debugName: "lastMessage" }] : []));
|
|
1663
|
-
this.hasUnread = computed(() => {
|
|
1664
|
-
return this.data().unreadCount > 0;
|
|
1665
|
-
}, ...(ngDevMode ? [{ debugName: "hasUnread" }] : []));
|
|
1666
|
-
this.unreadCount = computed(() => {
|
|
1667
|
-
return this.data().unreadCount.toString();
|
|
1668
|
-
}, ...(ngDevMode ? [{ debugName: "unreadCount" }] : []));
|
|
1669
|
-
}
|
|
1670
|
-
#chatInfoEffect;
|
|
1671
|
-
async preloadAndSetGroupAvatar(url) {
|
|
1672
|
-
this.isGroupAvatarLoading.set(true);
|
|
1673
|
-
await new Promise((resolve) => {
|
|
1674
|
-
const img = new Image();
|
|
1675
|
-
img.onload = () => {
|
|
1676
|
-
this.groupAvatarUrl.set(url);
|
|
1677
|
-
this.isGroupAvatarLoading.set(false);
|
|
1678
|
-
resolve();
|
|
1679
|
-
};
|
|
1680
|
-
img.onerror = () => {
|
|
1681
|
-
this.groupAvatarUrl.set(null);
|
|
1682
|
-
this.isGroupAvatarLoading.set(false);
|
|
1683
|
-
resolve();
|
|
1684
|
-
};
|
|
1685
|
-
img.src = url;
|
|
1686
1484
|
});
|
|
1687
1485
|
}
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
// Localized labels (preloaded for sync menu building)
|
|
1756
|
-
this.tOpen = signal('Open', ...(ngDevMode ? [{ debugName: "tOpen" }] : []));
|
|
1757
|
-
this.tMarkSeen = signal('Mark as seen', ...(ngDevMode ? [{ debugName: "tMarkSeen" }] : []));
|
|
1758
|
-
this.tTab = signal('Tab', ...(ngDevMode ? [{ debugName: "tTab" }] : []));
|
|
1759
|
-
this.tRemoveFromTab = signal('Remove from tab', ...(ngDevMode ? [{ debugName: "tRemoveFromTab" }] : []));
|
|
1760
|
-
this.tDelete = signal('Delete', ...(ngDevMode ? [{ debugName: "tDelete" }] : []));
|
|
1761
|
-
this.tRemoveChat = signal('Remove Chat', ...(ngDevMode ? [{ debugName: "tRemoveChat" }] : []));
|
|
1762
|
-
// Computed signals
|
|
1763
|
-
this.activeTab = computed(() => {
|
|
1764
|
-
const tabs = this.tabs();
|
|
1765
|
-
const index = this.activeTabIndex();
|
|
1766
|
-
if (tabs.length > 0 && index >= 0 && index < tabs.length) {
|
|
1767
|
-
return tabs[index];
|
|
1768
|
-
}
|
|
1769
|
-
return undefined;
|
|
1770
|
-
}, ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
1771
|
-
this.filteredRooms = signal([], ...(ngDevMode ? [{ debugName: "filteredRooms" }] : []));
|
|
1772
|
-
this.searchEffect = effect(() => {
|
|
1773
|
-
const allRooms = this.allRooms();
|
|
1774
|
-
let chatRooms = [...allRooms]; // Start with all rooms
|
|
1775
|
-
// Tab filter
|
|
1776
|
-
const activeTab = this.activeTab();
|
|
1777
|
-
if (activeTab) {
|
|
1778
|
-
if (activeTab.name === 'unread') {
|
|
1779
|
-
// Special local state for unread
|
|
1780
|
-
chatRooms = allRooms.filter((room) => room.unreadCount > 0);
|
|
1781
|
-
}
|
|
1782
|
-
else if (activeTab.name === 'all') {
|
|
1783
|
-
// Local state for all
|
|
1784
|
-
chatRooms = allRooms;
|
|
1785
|
-
}
|
|
1786
|
-
else {
|
|
1787
|
-
// For other tabs defined by the service
|
|
1788
|
-
const includedIds = new Set(activeTab.includeRooms.map((r) => r.id));
|
|
1789
|
-
chatRooms = allRooms.filter((room) => includedIds.has(room.id));
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
// Search filter (applies on top of tab filter)
|
|
1793
|
-
const query = (this.searchQuery() || '').toLowerCase();
|
|
1794
|
-
if (query) {
|
|
1795
|
-
const filtered = [];
|
|
1796
|
-
for (const room of chatRooms) {
|
|
1797
|
-
try {
|
|
1798
|
-
let roomName = '';
|
|
1799
|
-
// Handle group chats vs. single-user chats
|
|
1800
|
-
if (room.members && room.members.length > 1) {
|
|
1801
|
-
roomName = room.title || '';
|
|
1802
|
-
}
|
|
1803
|
-
else if (room.members && room.members.length === 1) {
|
|
1804
|
-
const member = room.members[0];
|
|
1805
|
-
if (member) {
|
|
1806
|
-
roomName = member.fullName || '';
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1809
|
-
const lastMessage = room.lastMessage?.message?.content || '';
|
|
1810
|
-
if (roomName.toLowerCase().includes(query) || lastMessage.toLowerCase().includes(query)) {
|
|
1811
|
-
filtered.push(room);
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
catch (error) {
|
|
1815
|
-
console.error(`Failed to process search for room ${room.id}`, error);
|
|
1816
|
-
}
|
|
1817
|
-
}
|
|
1818
|
-
chatRooms = filtered;
|
|
1819
|
-
}
|
|
1820
|
-
this.filteredRooms.set(chatRooms);
|
|
1821
|
-
}, ...(ngDevMode ? [{ debugName: "searchEffect" }] : []));
|
|
1822
|
-
this.unreadCount = computed(() => this.allRooms().filter((i) => i.unreadCount > 0).length, ...(ngDevMode ? [{ debugName: "unreadCount" }] : []));
|
|
1823
|
-
this.allCount = computed(() => this.allRooms().length, ...(ngDevMode ? [{ debugName: "allCount" }] : []));
|
|
1824
|
-
this.hasUnread = computed(() => this.allRooms().some((i) => i.unreadCount > 0), ...(ngDevMode ? [{ debugName: "hasUnread" }] : []));
|
|
1825
|
-
this.totalCount = computed(() => this.allRooms().length || 0, ...(ngDevMode ? [{ debugName: "totalCount" }] : []));
|
|
1826
|
-
// Context menus (desktop)
|
|
1827
|
-
this.contextRoom = null;
|
|
1828
|
-
this.contextTab = null;
|
|
1829
|
-
this.contextTabIndex = -1;
|
|
1830
|
-
}
|
|
1831
|
-
async deleteTab(tab) {
|
|
1832
|
-
const result = await this.dialogService.confirm(await this.translateService.translateAsync('@conversation:confirmations.delete-tab.title'), await this.translateService.translateAsync('@conversation:confirmations.delete-tab.message', {
|
|
1833
|
-
params: { title: tab.title },
|
|
1834
|
-
}));
|
|
1835
|
-
if (result.result) {
|
|
1836
|
-
await this.chatService.deleteTab(tab.id);
|
|
1837
|
-
await this.loadTabs();
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
async ngOnInit() {
|
|
1841
|
-
super.ngOnInit();
|
|
1842
|
-
this.isLoading.set(true);
|
|
1843
|
-
this.error.set(null);
|
|
1844
|
-
const [openText, markSeenText, tabText, removeFromTabText, deleteText, removeChatText] = await Promise.all([
|
|
1845
|
-
this.translateService.translateAsync('@conversation:actions.open'),
|
|
1846
|
-
this.translateService.translateAsync('@conversation:actions.mark-seen'),
|
|
1847
|
-
this.translateService.translateAsync('@conversation:actions.tab'),
|
|
1848
|
-
this.translateService.translateAsync('@conversation:actions.remove-from-tab'),
|
|
1849
|
-
this.translateService.translateAsync('@conversation:actions.delete'),
|
|
1850
|
-
this.translateService.translateAsync('@conversation:remove-chat'),
|
|
1851
|
-
]);
|
|
1852
|
-
this.tOpen.set(openText);
|
|
1853
|
-
this.tMarkSeen.set(markSeenText);
|
|
1854
|
-
this.tTab.set(tabText);
|
|
1855
|
-
this.tRemoveFromTab.set(removeFromTabText);
|
|
1856
|
-
this.tDelete.set(deleteText);
|
|
1857
|
-
this.tRemoveChat.set(removeChatText);
|
|
1858
|
-
await Promise.all([this.loadChats(), this.loadTabs()]);
|
|
1859
|
-
this.isLoading.set(false);
|
|
1860
|
-
//
|
|
1861
|
-
this.router.events
|
|
1862
|
-
.pipe(this.unsubscribe.takeUntilDestroy, filter((event) => event instanceof NavigationEnd), startWith(null))
|
|
1863
|
-
.subscribe(async () => {
|
|
1864
|
-
await this.loadFromRoute();
|
|
1865
|
-
});
|
|
1866
|
-
//
|
|
1867
|
-
this.realtimeService.room$.pipe(this.unsubscribe.takeUntilDestroy).subscribe((event) => {
|
|
1868
|
-
switch (event.type) {
|
|
1869
|
-
case 'add':
|
|
1870
|
-
this.allRooms.update((rooms) => [event.payload, ...rooms.filter((r) => r.id !== event.payload.id)]);
|
|
1871
|
-
break;
|
|
1872
|
-
case 'remove':
|
|
1873
|
-
this.allRooms.update((rooms) => rooms.filter((r) => r.id !== event.payload));
|
|
1874
|
-
if (event.payload === this.selectedRoom()?.id) {
|
|
1875
|
-
this.selectedRoom.set(null);
|
|
1876
|
-
this.router.navigate(['./'], { relativeTo: this.activatedRoute });
|
|
1877
|
-
}
|
|
1878
|
-
break;
|
|
1879
|
-
case 'update':
|
|
1880
|
-
this.allRooms.update((rooms) => rooms.map((r) => (r.id === event.payload.id ? event.payload : r)));
|
|
1881
|
-
break;
|
|
1882
|
-
case 'seen':
|
|
1883
|
-
this.allRooms.update((rooms) => rooms.map((room) => (room.id === event.payload ? { ...room, unreadCount: 0 } : room)));
|
|
1884
|
-
break;
|
|
1885
|
-
}
|
|
1886
|
-
});
|
|
1887
|
-
this.realtimeService.message$.pipe(this.unsubscribe.takeUntilDestroy).subscribe((event) => {
|
|
1888
|
-
switch (event.type) {
|
|
1889
|
-
case 'add': {
|
|
1890
|
-
const message = event.payload;
|
|
1891
|
-
const rooms = this.allRooms();
|
|
1892
|
-
const roomIndex = rooms.findIndex((r) => r.id === message.roomId);
|
|
1893
|
-
if (roomIndex > -1) {
|
|
1894
|
-
const roomToUpdate = rooms[roomIndex];
|
|
1895
|
-
const isCurrentUser = message.author.id === this.sessionService.user?.id;
|
|
1896
|
-
const updatedRoom = {
|
|
1897
|
-
...roomToUpdate,
|
|
1898
|
-
lastMessage: message,
|
|
1899
|
-
unreadCount: !isCurrentUser ? (roomToUpdate.unreadCount || 0) + 1 : roomToUpdate.unreadCount,
|
|
1900
|
-
};
|
|
1901
|
-
const newRooms = [updatedRoom, ...rooms.filter((r) => r.id !== message.roomId)];
|
|
1902
|
-
this.allRooms.set(newRooms);
|
|
1903
|
-
if (!isCurrentUser && (this.selectedRoom()?.id !== message.roomId || document.hidden)) {
|
|
1904
|
-
const notification = convertChatMessageToNotification(roomToUpdate, message, this.sessionService.user);
|
|
1905
|
-
this.notificationConnectorService.create({
|
|
1906
|
-
...notification,
|
|
1907
|
-
id: message.id,
|
|
1908
|
-
entityName: 'notifications',
|
|
1909
|
-
createAt: new Date(),
|
|
1910
|
-
}, {
|
|
1911
|
-
onClick: () => {
|
|
1912
|
-
this.router.navigate([roomToUpdate.id], { relativeTo: this.activatedRoute });
|
|
1913
|
-
},
|
|
1914
|
-
activeWindow: true,
|
|
1915
|
-
});
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
else {
|
|
1919
|
-
this.chatService.getRoom(message.roomId).then((newRoom) => {
|
|
1920
|
-
this.allRooms.update((currentRooms) => [newRoom, ...currentRooms]);
|
|
1921
|
-
});
|
|
1922
|
-
}
|
|
1923
|
-
break;
|
|
1924
|
-
}
|
|
1925
|
-
case 'update': {
|
|
1926
|
-
const message = event.payload;
|
|
1927
|
-
this.allRooms.update((rooms) => {
|
|
1928
|
-
return rooms.map((room) => {
|
|
1929
|
-
if (room.lastMessage?.id === message.id) {
|
|
1930
|
-
return {
|
|
1931
|
-
...room,
|
|
1932
|
-
lastMessage: {
|
|
1933
|
-
...room.lastMessage,
|
|
1934
|
-
...message,
|
|
1935
|
-
},
|
|
1936
|
-
};
|
|
1937
|
-
}
|
|
1938
|
-
return room;
|
|
1939
|
-
});
|
|
1940
|
-
});
|
|
1941
|
-
break;
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
|
-
});
|
|
1945
|
-
this.realtimeService.typingStatus$.pipe(this.unsubscribe.takeUntilDestroy).subscribe(async (status) => {
|
|
1946
|
-
const currentUserId = this.sessionService.user?.id;
|
|
1947
|
-
if (status.user.id !== currentUserId) {
|
|
1948
|
-
if (status.isTyping) {
|
|
1949
|
-
this.typingStatus.update((value) => ({
|
|
1950
|
-
...value,
|
|
1951
|
-
[status.roomId]: { user: status.user.fullName || '', isTyping: true },
|
|
1952
|
-
}));
|
|
1953
|
-
}
|
|
1954
|
-
else {
|
|
1955
|
-
this.typingStatus.update((value) => {
|
|
1956
|
-
const { [status.roomId]: _, ...rest } = value;
|
|
1957
|
-
return rest;
|
|
1958
|
-
});
|
|
1959
|
-
}
|
|
1960
|
-
}
|
|
1961
|
-
});
|
|
1962
|
-
}
|
|
1963
|
-
async loadFromRoute() {
|
|
1964
|
-
const chatId = this.activatedRoute.snapshot.firstChild?.paramMap.get('id');
|
|
1965
|
-
if (chatId) {
|
|
1966
|
-
this.openChat(chatId);
|
|
1967
|
-
}
|
|
1968
|
-
else {
|
|
1969
|
-
this.selectedRoom.set(null);
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
// Page Interface Implementation
|
|
1973
|
-
async getPageTitle() {
|
|
1974
|
-
const room = this.selectedRoom();
|
|
1975
|
-
if (!room && this.layoutService.isMobileDevice()) {
|
|
1976
|
-
return await this.translateService.translateAsync('@conversation:plural-title');
|
|
1977
|
-
}
|
|
1978
|
-
if (!room) {
|
|
1979
|
-
return '';
|
|
1980
|
-
}
|
|
1981
|
-
const { members, title, id } = room;
|
|
1982
|
-
if (members.length > 1) {
|
|
1983
|
-
return title || (await this.translateService.translateAsync('@conversation:labels.group-chat'));
|
|
1984
|
-
}
|
|
1985
|
-
const member = members[0];
|
|
1986
|
-
if (!member) {
|
|
1987
|
-
return await this.translateService.translateAsync('@conversation:labels.unknown-user');
|
|
1988
|
-
}
|
|
1989
|
-
return member.fullName || (await this.translateService.translateAsync('@conversation:labels.unknown-user'));
|
|
1990
|
-
}
|
|
1991
|
-
getPageDescription() {
|
|
1992
|
-
const typing = this.typingStatus();
|
|
1993
|
-
const selectedRoomId = this.selectedRoom()?.id;
|
|
1994
|
-
if (selectedRoomId && typing[selectedRoomId]?.isTyping) {
|
|
1995
|
-
return `${typing[selectedRoomId].user} is typing...`;
|
|
1996
|
-
}
|
|
1997
|
-
const room = this.selectedRoom();
|
|
1998
|
-
return room?.topic || '';
|
|
1999
|
-
}
|
|
2000
|
-
async getBackButton() {
|
|
2001
|
-
if (this.selectedRoom()) {
|
|
2002
|
-
return {
|
|
2003
|
-
title: await this.translateService.translateAsync('@conversation:back-to-chat-list'),
|
|
2004
|
-
};
|
|
2005
|
-
}
|
|
2006
|
-
else
|
|
2007
|
-
return null;
|
|
2008
|
-
}
|
|
2009
|
-
async getSecondaryMenuItems() {
|
|
2010
|
-
const items = [];
|
|
2011
|
-
const hasRoom = !!this.selectedRoom();
|
|
2012
|
-
if (hasRoom) {
|
|
2013
|
-
const room = this.selectedRoom();
|
|
2014
|
-
const currentUserId = this.sessionService.user?.id;
|
|
2015
|
-
const creatorId = room.auditInfo?.created?.by?.id;
|
|
2016
|
-
const isCreator = !!currentUserId && !!creatorId && currentUserId === creatorId;
|
|
2017
|
-
const isGroup = (room.members?.length ?? 0) > 1;
|
|
2018
|
-
const isChannel = room.topic === 'channel';
|
|
2019
|
-
const kindKey = isGroup ? '@conversation:labels.group-chat' : '@conversation:room.individual-title';
|
|
2020
|
-
const kindText = await this.translateService.translateAsync(kindKey);
|
|
2021
|
-
const deleteText = await this.translateService.translateAsync('@conversation:actions.delete');
|
|
2022
|
-
const removeChatText = await this.translateService.translateAsync('@conversation:remove-chat');
|
|
2023
|
-
items.push({
|
|
2024
|
-
title: 'Edit Room',
|
|
2025
|
-
icon: 'fa-light fa-pen-to-square',
|
|
2026
|
-
command: { name: 'edit-room' },
|
|
2027
|
-
}, {
|
|
2028
|
-
title: isCreator ? `${deleteText} ${kindText}` : removeChatText,
|
|
2029
|
-
icon: 'fa-light fa-trash-can',
|
|
2030
|
-
color: 'danger',
|
|
2031
|
-
command: { name: isCreator ? 'delete-room' : 'leave-room' },
|
|
2032
|
-
});
|
|
2033
|
-
}
|
|
2034
|
-
return items;
|
|
2035
|
-
}
|
|
2036
|
-
async execute(command) {
|
|
2037
|
-
switch (command.name) {
|
|
2038
|
-
case 'remove-chat':
|
|
2039
|
-
const response = await this.dialogService.confirm(await this.translateService.translateAsync('@conversation:confirmations.remove-chat.title'), await this.translateService.translateAsync('@conversation:confirmations.remove-chat.message'));
|
|
2040
|
-
if (response.result) {
|
|
2041
|
-
await this.chatService.deleteRoom(this.selectedRoom()?.id);
|
|
2042
|
-
this.router.navigate(['./'], { relativeTo: this.activatedRoute });
|
|
2043
|
-
}
|
|
2044
|
-
break;
|
|
2045
|
-
case 'edit-room': {
|
|
2046
|
-
const room = await this.chatService.getRoom(this.selectedRoom()?.id);
|
|
2047
|
-
if (!room)
|
|
2048
|
-
return;
|
|
2049
|
-
const currentMemberIds = (room.members || []).map((m) => m.id);
|
|
2050
|
-
const dialogRef = await this.layoutBuilder
|
|
2051
|
-
.create()
|
|
2052
|
-
.dialog(dialog => {
|
|
2053
|
-
dialog
|
|
2054
|
-
.setTitle('Edit Room')
|
|
2055
|
-
.setSize('sm')
|
|
2056
|
-
.setContext({ title: room.title || '', members: currentMemberIds, avatar: room.avatar })
|
|
2057
|
-
.content(layoutBuilder => {
|
|
2058
|
-
layoutBuilder.flex(flex => {
|
|
2059
|
-
flex
|
|
2060
|
-
.setDirection('column')
|
|
2061
|
-
.formField('@conversation:new-conversation.title.label', field => {
|
|
2062
|
-
field.path('title');
|
|
2063
|
-
field.textBox({ placeholder: '@conversation:new-conversation.title.placeholder' });
|
|
2064
|
-
})
|
|
2065
|
-
.formField('@conversation:new-conversation.lookup.label', field => {
|
|
2066
|
-
field.path('members');
|
|
2067
|
-
field.lookupBox({
|
|
2068
|
-
entity: 'SecurityManagement.User',
|
|
2069
|
-
multiple: true,
|
|
2070
|
-
customFilter: {
|
|
2071
|
-
field: 'id',
|
|
2072
|
-
operator: { type: 'notEqual' },
|
|
2073
|
-
value: this.sessionService.user?.id,
|
|
2074
|
-
},
|
|
2075
|
-
});
|
|
2076
|
-
})
|
|
2077
|
-
.formField('Avatar', field => {
|
|
2078
|
-
field.path('avatar');
|
|
2079
|
-
field.customWidget('avatar', {});
|
|
2080
|
-
});
|
|
2081
|
-
});
|
|
2082
|
-
})
|
|
2083
|
-
.setActions(actions => {
|
|
2084
|
-
actions.cancel('@general:actions.cancel.title').submit('Save');
|
|
2085
|
-
});
|
|
2086
|
-
})
|
|
2087
|
-
.show();
|
|
2088
|
-
const ctx = dialogRef.context();
|
|
2089
|
-
const action = dialogRef.action();
|
|
2090
|
-
dialogRef.close();
|
|
2091
|
-
if (action === 'cancel')
|
|
2092
|
-
return;
|
|
2093
|
-
const selectedIds = Array.isArray(ctx.members) ? ctx.members : [];
|
|
2094
|
-
const toAdd = selectedIds.filter((id) => !currentMemberIds.includes(id));
|
|
2095
|
-
const toRemove = currentMemberIds.filter((id) => !selectedIds.includes(id));
|
|
2096
|
-
const trimmedTitle = typeof ctx.title === 'string' ? ctx.title.trim() : undefined;
|
|
2097
|
-
const titleChanged = typeof trimmedTitle === 'string' && trimmedTitle !== (room.title || '').trim();
|
|
2098
|
-
const avatarChanged = (ctx.avatar ?? null) !== (room.avatar ?? null);
|
|
2099
|
-
const updatePayload = {};
|
|
2100
|
-
if (titleChanged) {
|
|
2101
|
-
updatePayload.title = trimmedTitle;
|
|
2102
|
-
}
|
|
2103
|
-
if (avatarChanged) {
|
|
2104
|
-
updatePayload.avatar = ctx.avatar ?? null;
|
|
2105
|
-
}
|
|
2106
|
-
const ops = [];
|
|
2107
|
-
if (Object.keys(updatePayload).length > 0) {
|
|
2108
|
-
ops.push(this.chatService.updateRoom(room.id, updatePayload));
|
|
2109
|
-
}
|
|
2110
|
-
toAdd.forEach((id) => ops.push(this.chatService.addParticipant(room.id, id)));
|
|
2111
|
-
toRemove.forEach((id) => ops.push(this.chatService.removeParticipant(room.id, id)));
|
|
2112
|
-
try {
|
|
2113
|
-
if (ops.length) {
|
|
2114
|
-
await Promise.all(ops);
|
|
2115
|
-
await this.loadChats();
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2118
|
-
catch (e) {
|
|
2119
|
-
this.toastService.danger('Failed to update room');
|
|
2120
|
-
}
|
|
2121
|
-
break;
|
|
2122
|
-
}
|
|
2123
|
-
case 'delete-room': {
|
|
2124
|
-
const room = this.selectedRoom();
|
|
2125
|
-
if (!room)
|
|
2126
|
-
return;
|
|
2127
|
-
const response = await this.dialogService.confirm(await this.translateService.translateAsync('@conversation:confirmations.delete-room.title'), await this.translateService.translateAsync('@conversation:confirmations.delete-room.message'));
|
|
2128
|
-
if (response.result) {
|
|
2129
|
-
await this.chatService.deleteRoom(room.id);
|
|
2130
|
-
this.router.navigate(['./'], { relativeTo: this.activatedRoute });
|
|
2131
|
-
}
|
|
2132
|
-
break;
|
|
2133
|
-
}
|
|
2134
|
-
case 'leave-room': {
|
|
2135
|
-
const room = this.selectedRoom();
|
|
2136
|
-
if (!room)
|
|
2137
|
-
return;
|
|
2138
|
-
const currentUserId = this.sessionService.user?.id;
|
|
2139
|
-
const response = await this.dialogService.confirm(await this.translateService.translateAsync('@conversation:confirmations.remove-chat.title'), await this.translateService.translateAsync('@conversation:confirmations.remove-chat.message'));
|
|
2140
|
-
if (response.result) {
|
|
2141
|
-
await this.chatService.removeParticipant(room.id, currentUserId);
|
|
2142
|
-
this.router.navigate(['./'], { relativeTo: this.activatedRoute });
|
|
2143
|
-
}
|
|
2144
|
-
break;
|
|
2145
|
-
}
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
onBackButtonClick() {
|
|
2149
|
-
this.selectedRoom.set(null);
|
|
2150
|
-
this.typingStatus.update((value) => {
|
|
2151
|
-
const { [this.selectedRoom()?.id]: _, ...rest } = value;
|
|
2152
|
-
return rest;
|
|
2153
|
-
});
|
|
2154
|
-
this.router.navigate(['./'], { relativeTo: this.activatedRoute });
|
|
2155
|
-
}
|
|
2156
|
-
// Methods
|
|
2157
|
-
getRoomCountForTab(tab) {
|
|
2158
|
-
const allRooms = this.allRooms();
|
|
2159
|
-
// For all tab types, only count rooms that have unread messages
|
|
2160
|
-
if (tab.name === 'all' || tab.name === 'unread') {
|
|
2161
|
-
return allRooms.filter((room) => room.unreadCount > 0).length;
|
|
2162
|
-
}
|
|
2163
|
-
const includedIds = new Set(tab.includeRooms.map((r) => r.id));
|
|
2164
|
-
return allRooms.filter((room) => includedIds.has(room.id) && room.unreadCount > 0).length;
|
|
2165
|
-
}
|
|
2166
|
-
async loadTabs() {
|
|
2167
|
-
const localTabs = [
|
|
2168
|
-
{
|
|
2169
|
-
id: 'all-local',
|
|
2170
|
-
name: 'all',
|
|
2171
|
-
title: 'All',
|
|
2172
|
-
excludeRooms: [],
|
|
2173
|
-
includeRooms: [],
|
|
2174
|
-
},
|
|
2175
|
-
{
|
|
2176
|
-
id: 'unread-local',
|
|
2177
|
-
name: 'unread',
|
|
2178
|
-
title: 'Unread',
|
|
2179
|
-
excludeRooms: [],
|
|
2180
|
-
includeRooms: [],
|
|
2181
|
-
},
|
|
2182
|
-
];
|
|
2183
|
-
try {
|
|
2184
|
-
const result = await this.chatService.listTabs();
|
|
2185
|
-
this.tabs.set([...localTabs, ...result.items]);
|
|
2186
|
-
}
|
|
2187
|
-
catch (error) {
|
|
2188
|
-
console.error('Failed to load tabs:', error);
|
|
2189
|
-
this.tabs.set(localTabs);
|
|
2190
|
-
}
|
|
2191
|
-
}
|
|
2192
|
-
async loadChats() {
|
|
2193
|
-
try {
|
|
2194
|
-
// Use the updated service method to get rooms with last messages
|
|
2195
|
-
const response = await this.chatService.listRooms();
|
|
2196
|
-
// Sort rooms by last message created.at timestamp in descending order
|
|
2197
|
-
const sortedRooms = response.items.sort((a, b) => {
|
|
2198
|
-
const dateA = a.lastMessage?.auditInfo?.created?.at || a.auditInfo?.created?.at || 0;
|
|
2199
|
-
const dateB = b.lastMessage?.auditInfo?.created?.at || b.auditInfo?.created?.at || 0;
|
|
2200
|
-
return new Date(dateB).getTime() - new Date(dateA).getTime();
|
|
2201
|
-
});
|
|
2202
|
-
this.allRooms.set(sortedRooms);
|
|
2203
|
-
this.rooms.set(sortedRooms);
|
|
2204
|
-
}
|
|
2205
|
-
catch (error) {
|
|
2206
|
-
this.error.set('Failed to load chats. Please try again.');
|
|
2207
|
-
console.error('Error loading chats:', error);
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
async refreshChat() {
|
|
2211
|
-
await this.loadChats();
|
|
2212
|
-
}
|
|
2213
|
-
async openChat(chatId) {
|
|
2214
|
-
try {
|
|
2215
|
-
this.typingStatus.update((value) => {
|
|
2216
|
-
const { [chatId]: _, ...rest } = value;
|
|
2217
|
-
return rest;
|
|
2218
|
-
});
|
|
2219
|
-
// Use the service method to mark chat as read
|
|
2220
|
-
await this.chatService.markRoomSeen(chatId);
|
|
2221
|
-
// Update local state without making another network request
|
|
2222
|
-
const currentRooms = this.allRooms();
|
|
2223
|
-
const updatedRooms = currentRooms.map((room) => {
|
|
2224
|
-
if (room.id === chatId) {
|
|
2225
|
-
// Reset unread count for the selected room
|
|
2226
|
-
return { ...room, unreadCount: 0 };
|
|
2227
|
-
}
|
|
2228
|
-
return room;
|
|
2229
|
-
});
|
|
2230
|
-
// Update the rooms signals
|
|
2231
|
-
this.allRooms.set(updatedRooms);
|
|
2232
|
-
this.rooms.set(updatedRooms);
|
|
2233
|
-
// Find the selected room
|
|
2234
|
-
const selectedRoom = updatedRooms.find((room) => room.id === chatId) || null;
|
|
2235
|
-
this.selectedRoom.set(selectedRoom);
|
|
2236
|
-
// Navigate to the chat details
|
|
2237
|
-
this.router.navigate([chatId], { relativeTo: this.activatedRoute });
|
|
2238
|
-
}
|
|
2239
|
-
catch (error) {
|
|
2240
|
-
console.error('Failed to mark chat as read:', error);
|
|
2241
|
-
}
|
|
2242
|
-
}
|
|
2243
|
-
searchChat(query) {
|
|
2244
|
-
this.searchQuery.set(query);
|
|
2245
|
-
this.isSearching.set(!!query);
|
|
2246
|
-
}
|
|
2247
|
-
// Header methods
|
|
2248
|
-
onSearch(query) {
|
|
2249
|
-
this.searchChat(query);
|
|
2250
|
-
}
|
|
2251
|
-
clearSearch() {
|
|
2252
|
-
this.searchQuery.set('');
|
|
2253
|
-
this.isSearching.set(false);
|
|
2254
|
-
}
|
|
2255
|
-
async openSelector() {
|
|
2256
|
-
try {
|
|
2257
|
-
const entity = await this.entityRegistry.resolve('SecurityManagement', 'User');
|
|
2258
|
-
const result = await this.dataSelectorService.open({
|
|
2259
|
-
entity,
|
|
2260
|
-
title: 'Select Users',
|
|
2261
|
-
allowMultiple: true,
|
|
2262
|
-
columns: ['username', 'displayName', 'roleIds'],
|
|
2263
|
-
filters: {
|
|
2264
|
-
field: 'id',
|
|
2265
|
-
operator: { type: 'equal' },
|
|
2266
|
-
// value: this.sessionService.user?.id,
|
|
2267
|
-
value: '{{ session.currentUser().id }}',
|
|
1486
|
+
goBackToList() {
|
|
1487
|
+
this.mobileView.set('list');
|
|
1488
|
+
}
|
|
1489
|
+
isMobile() {
|
|
1490
|
+
return window.innerWidth < 768;
|
|
1491
|
+
}
|
|
1492
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1493
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: AXMChatComponent, isStandalone: true, selector: "axm-chat", providers: [
|
|
1494
|
+
...provideConversation({
|
|
1495
|
+
userApi: AXIndexedDBUserApi,
|
|
1496
|
+
conversationApi: AXIndexedDBConversationApi,
|
|
1497
|
+
messageApi: AXIndexedDBMessageAIApi,
|
|
1498
|
+
realtimeApi: AXIndexedDBRealtimeApi,
|
|
1499
|
+
config: {},
|
|
1500
|
+
registry: {
|
|
1501
|
+
messageRenderers: [
|
|
1502
|
+
AX_CONVERSATION_TEXT_RENDERER,
|
|
1503
|
+
AX_CONVERSATION_IMAGE_RENDERER,
|
|
1504
|
+
AX_CONVERSATION_VIDEO_RENDERER,
|
|
1505
|
+
AX_CONVERSATION_AUDIO_RENDERER,
|
|
1506
|
+
AX_CONVERSATION_VOICE_RENDERER,
|
|
1507
|
+
AX_CONVERSATION_FILE_RENDERER,
|
|
1508
|
+
AX_CONVERSATION_LOCATION_RENDERER,
|
|
1509
|
+
AX_CONVERSATION_STICKER_RENDERER,
|
|
1510
|
+
AX_CONVERSATION_CONTACT_RENDERER,
|
|
1511
|
+
],
|
|
1512
|
+
messageActions: [
|
|
1513
|
+
AX_CONVERSATION_MESSAGE_REPLY_ACTION,
|
|
1514
|
+
AX_CONVERSATION_MESSAGE_FORWARD_ACTION,
|
|
1515
|
+
AX_CONVERSATION_MESSAGE_EDIT_ACTION,
|
|
1516
|
+
AX_CONVERSATION_MESSAGE_DELETE_ACTION,
|
|
1517
|
+
],
|
|
1518
|
+
composerActions: [
|
|
1519
|
+
AX_CONVERSATION_COMPOSER_EMOJI_ACTION,
|
|
1520
|
+
AX_CONVERSATION_COMPOSER_IMAGE_ACTION,
|
|
1521
|
+
AX_CONVERSATION_COMPOSER_VIDEO_ACTION,
|
|
1522
|
+
AX_CONVERSATION_COMPOSER_FILE_ACTION,
|
|
1523
|
+
AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION,
|
|
1524
|
+
AX_CONVERSATION_COMPOSER_AUDIO_ACTION,
|
|
1525
|
+
AX_CONVERSATION_COMPOSER_CONTACT_ACTION,
|
|
1526
|
+
AX_CONVERSATION_COMPOSER_LOCATION_ACTION,
|
|
1527
|
+
],
|
|
1528
|
+
composerTabs: [AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_STICKER_TAB],
|
|
1529
|
+
conversationTabs: [
|
|
1530
|
+
AX_CONVERSATION_TAB_ALL,
|
|
1531
|
+
AX_CONVERSATION_TAB_PRIVATE,
|
|
1532
|
+
AX_CONVERSATION_TAB_GROUPS,
|
|
1533
|
+
AX_CONVERSATION_TAB_CHANNELS,
|
|
1534
|
+
AX_CONVERSATION_TAB_UNREAD,
|
|
1535
|
+
AX_CONVERSATION_TAB_ARCHIVED,
|
|
1536
|
+
],
|
|
1537
|
+
infoBarActions: [
|
|
1538
|
+
AX_CONVERSATION_INFO_BAR_SEARCH_ACTION,
|
|
1539
|
+
AX_CONVERSATION_INFO_BAR_INFO_ACTION,
|
|
1540
|
+
AX_CONVERSATION_INFO_BAR_MUTE_ACTION,
|
|
1541
|
+
AX_CONVERSATION_INFO_BAR_DIVIDER,
|
|
1542
|
+
AX_CONVERSATION_INFO_BAR_DELETE_ACTION,
|
|
1543
|
+
AX_CONVERSATION_INFO_BAR_BLOCK_ACTION,
|
|
1544
|
+
],
|
|
1545
|
+
conversationItemActions: [
|
|
1546
|
+
AX_CONVERSATION_ITEM_MUTE_ACTION,
|
|
1547
|
+
AX_CONVERSATION_ITEM_PIN_ACTION,
|
|
1548
|
+
AX_CONVERSATION_ITEM_MARK_READ_ACTION,
|
|
1549
|
+
AX_CONVERSATION_ITEM_DIVIDER,
|
|
1550
|
+
AX_CONVERSATION_ITEM_DELETE_ACTION,
|
|
1551
|
+
AX_CONVERSATION_ITEM_BLOCK_ACTION,
|
|
1552
|
+
],
|
|
2268
1553
|
},
|
|
2269
|
-
})
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
.filter((id) => typeof id === 'string' && id.length > 0)
|
|
2274
|
-
: [];
|
|
2275
|
-
}
|
|
2276
|
-
catch {
|
|
2277
|
-
return [];
|
|
2278
|
-
}
|
|
2279
|
-
}
|
|
2280
|
-
// Footer methods
|
|
2281
|
-
async onNewConversation() {
|
|
2282
|
-
const preselectedUserIds = await this.openSelector();
|
|
2283
|
-
if (!preselectedUserIds.length) {
|
|
2284
|
-
return;
|
|
2285
|
-
}
|
|
2286
|
-
let members = preselectedUserIds;
|
|
2287
|
-
let title;
|
|
2288
|
-
let avatar;
|
|
2289
|
-
if (preselectedUserIds.length > 1) {
|
|
2290
|
-
const dialogRef = await this.layoutBuilder
|
|
2291
|
-
.create()
|
|
2292
|
-
.dialog(dialog => {
|
|
2293
|
-
dialog
|
|
2294
|
-
.setTitle('@conversation:new-conversation.header')
|
|
2295
|
-
.setSize('sm')
|
|
2296
|
-
.setContext({ lookup: preselectedUserIds, title: '', avatar: null })
|
|
2297
|
-
.content(layoutBuilder => {
|
|
2298
|
-
layoutBuilder.flex(flex => {
|
|
2299
|
-
flex
|
|
2300
|
-
.setDirection('column')
|
|
2301
|
-
.formField('@conversation:new-conversation.lookup.label', field => {
|
|
2302
|
-
field.path('lookup');
|
|
2303
|
-
field.lookupBox({ entity: 'SecurityManagement.User', multiple: true });
|
|
2304
|
-
})
|
|
2305
|
-
.formField('@conversation:new-conversation.title.label', field => {
|
|
2306
|
-
field.path('title');
|
|
2307
|
-
field.visible(`{{!(context.eval('lookup')?.length > 1) }}`);
|
|
2308
|
-
field.textBox({
|
|
2309
|
-
placeholder: '@conversation:new-conversation.title.placeholder',
|
|
2310
|
-
});
|
|
2311
|
-
})
|
|
2312
|
-
.formField('Avatar', field => {
|
|
2313
|
-
field.path('avatar');
|
|
2314
|
-
field.customWidget('avatar', { refId: 'group', refType: 'group' });
|
|
2315
|
-
});
|
|
2316
|
-
});
|
|
2317
|
-
})
|
|
2318
|
-
.setActions(actions => {
|
|
2319
|
-
actions.cancel('@general:actions.cancel.title').submit('@conversation:new-conversation.actions.accept-send');
|
|
2320
|
-
});
|
|
2321
|
-
})
|
|
2322
|
-
.show();
|
|
2323
|
-
const ctx = dialogRef.context();
|
|
2324
|
-
const action = dialogRef.action();
|
|
2325
|
-
dialogRef.close();
|
|
2326
|
-
const selected = ctx?.lookup ?? [];
|
|
2327
|
-
if (action === 'cancel' || !selected.length) {
|
|
2328
|
-
return;
|
|
2329
|
-
}
|
|
2330
|
-
members = selected;
|
|
2331
|
-
title = ctx?.title;
|
|
2332
|
-
avatar = ctx?.avatar;
|
|
2333
|
-
}
|
|
2334
|
-
try {
|
|
2335
|
-
const res = await this.chatService.createRoom(members, title, avatar || undefined);
|
|
2336
|
-
await this.refreshChat();
|
|
2337
|
-
this.router.navigate([res.id], { relativeTo: this.activatedRoute });
|
|
2338
|
-
}
|
|
2339
|
-
catch (error) {
|
|
2340
|
-
this.toastService.danger('Failed to create room');
|
|
2341
|
-
}
|
|
2342
|
-
}
|
|
2343
|
-
// Sliding item actions (mobile)
|
|
2344
|
-
onSlideAction(room, action) {
|
|
2345
|
-
switch (action) {
|
|
2346
|
-
// case 'mute':
|
|
2347
|
-
// this.toastService.warning('Mute not implemented yet');
|
|
2348
|
-
// break;
|
|
2349
|
-
case 'delete':
|
|
2350
|
-
this.deleteRoom(room.id);
|
|
2351
|
-
break;
|
|
2352
|
-
}
|
|
2353
|
-
}
|
|
2354
|
-
async deleteRoom(roomId) {
|
|
2355
|
-
try {
|
|
2356
|
-
const dialogResult = await this.dialogService.confirm('Delete Room', 'Are you sure you want to delete Room?', 'danger', 'horizontal');
|
|
2357
|
-
if (dialogResult.result) {
|
|
2358
|
-
this.chatService.deleteRoom(roomId);
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
catch (error) {
|
|
2362
|
-
console.error(`Error Deleting Room with Room id: ${roomId}`, error);
|
|
2363
|
-
}
|
|
2364
|
-
}
|
|
2365
|
-
openContextMenu(ev, room) {
|
|
2366
|
-
ev.preventDefault();
|
|
2367
|
-
this.contextRoom = room;
|
|
2368
|
-
this.chatContext()?.showAt({ x: ev.clientX, y: ev.clientY });
|
|
2369
|
-
}
|
|
2370
|
-
openTabContextMenu(ev, tab, index) {
|
|
2371
|
-
ev.preventDefault();
|
|
2372
|
-
this.contextTab = tab;
|
|
2373
|
-
this.contextTabIndex = index;
|
|
2374
|
-
this.tabContext()?.showAt({ x: ev.clientX, y: ev.clientY });
|
|
2375
|
-
}
|
|
2376
|
-
onContextOpening(e) {
|
|
2377
|
-
const items = [];
|
|
2378
|
-
// General Items
|
|
2379
|
-
items.push({ name: 'open', text: this.tOpen(), icon: 'fa-light fa-message-lines' });
|
|
2380
|
-
// Resolve context room once
|
|
2381
|
-
const contextRoom = this.contextRoom;
|
|
2382
|
-
// Mark as seen (only if the room has unread messages)
|
|
2383
|
-
if (contextRoom && (contextRoom.unreadCount || 0) > 0) {
|
|
2384
|
-
items.push({ name: 'mark-seen', text: this.tMarkSeen(), icon: 'fa-light fa-envelope-open' });
|
|
2385
|
-
}
|
|
2386
|
-
// Tab submenu behavior (Telegram-like)
|
|
2387
|
-
const allTabs = this.tabs();
|
|
2388
|
-
const activeTab = this.activeTab();
|
|
2389
|
-
const customTabs = allTabs.filter((t) => t.name !== 'all' && t.name !== 'unread');
|
|
2390
|
-
if (contextRoom && customTabs.length > 0) {
|
|
2391
|
-
if (activeTab?.name === 'all') {
|
|
2392
|
-
const tabMenuItems = customTabs.map((t) => {
|
|
2393
|
-
const isIncluded = (t.includeRooms || []).some((r) => r.id === contextRoom.id);
|
|
2394
|
-
return {
|
|
2395
|
-
name: `tab.toggle:${t.id}`,
|
|
2396
|
-
text: t.title,
|
|
2397
|
-
icon: isIncluded ? 'fa-light fa-check' : undefined,
|
|
2398
|
-
};
|
|
2399
|
-
});
|
|
2400
|
-
items.push({ name: 'tab', text: this.tTab(), icon: 'fa-light fa-folder-tree', items: tabMenuItems });
|
|
2401
|
-
}
|
|
2402
|
-
else if (activeTab?.name === 'unread') {
|
|
2403
|
-
// No tab submenu in unread
|
|
2404
|
-
}
|
|
2405
|
-
else {
|
|
2406
|
-
// Only remove from current custom tab
|
|
2407
|
-
items.push({
|
|
2408
|
-
name: 'tab.remove-current',
|
|
2409
|
-
text: this.tRemoveFromTab(),
|
|
2410
|
-
icon: 'fa-light fa-square-minus',
|
|
2411
|
-
color: 'warning',
|
|
2412
|
-
});
|
|
2413
|
-
}
|
|
2414
|
-
}
|
|
2415
|
-
// Dangerous action at the end
|
|
2416
|
-
if (contextRoom) {
|
|
2417
|
-
const currentUserId = this.sessionService.user?.id;
|
|
2418
|
-
const creatorId = contextRoom.auditInfo?.created?.by?.id;
|
|
2419
|
-
const isCreator = !!currentUserId && !!creatorId && currentUserId === creatorId;
|
|
2420
|
-
const text = isCreator ? this.tDelete() : this.tRemoveChat();
|
|
2421
|
-
const name = isCreator ? 'delete-room' : 'leave-room';
|
|
2422
|
-
items.push({ name, text, icon: 'fa-light fa-trash-can', color: 'danger' });
|
|
2423
|
-
}
|
|
2424
|
-
e.items = items;
|
|
2425
|
-
}
|
|
2426
|
-
// Tab header context menu (synchronous build)
|
|
2427
|
-
onTabContextOpening(e) {
|
|
2428
|
-
const items = [];
|
|
2429
|
-
const tab = this.contextTab;
|
|
2430
|
-
if (!tab) {
|
|
2431
|
-
e.items = items;
|
|
2432
|
-
return;
|
|
2433
|
-
}
|
|
2434
|
-
if (tab.name === 'all' || tab.name === 'unread') {
|
|
2435
|
-
items.push({ name: 'tab.add', text: 'Add tab', icon: 'fa-light fa-square-plus' });
|
|
2436
|
-
}
|
|
2437
|
-
else {
|
|
2438
|
-
items.push({ name: 'tab.remove', text: 'Remove tab', icon: 'fa-light fa-trash-can', color: 'danger' });
|
|
2439
|
-
}
|
|
2440
|
-
e.items = items;
|
|
2441
|
-
}
|
|
2442
|
-
async onTabContextItemClick(e) {
|
|
2443
|
-
if (!this.contextTab)
|
|
2444
|
-
return;
|
|
2445
|
-
switch (e.item.name) {
|
|
2446
|
-
case 'tab.add': {
|
|
2447
|
-
// Build dialog for creating a new custom tab
|
|
2448
|
-
const rooms = this.allRooms();
|
|
2449
|
-
const roomOptions = rooms.map((r) => ({
|
|
2450
|
-
id: r.id,
|
|
2451
|
-
title: (r.members?.length ?? 0) > 1 ? r.title || '' : r.members?.[0]?.fullName || '',
|
|
2452
|
-
}));
|
|
2453
|
-
const dialogRef = await this.layoutBuilder
|
|
2454
|
-
.create()
|
|
2455
|
-
.dialog(dialog => {
|
|
2456
|
-
dialog
|
|
2457
|
-
.setTitle('New Tab')
|
|
2458
|
-
.setSize('sm')
|
|
2459
|
-
.setContext({ title: '', rooms: [] })
|
|
2460
|
-
.content(layoutBuilder => {
|
|
2461
|
-
layoutBuilder.flex(flex => {
|
|
2462
|
-
flex
|
|
2463
|
-
.setDirection('column')
|
|
2464
|
-
.formField('Title', field => {
|
|
2465
|
-
field.path('title');
|
|
2466
|
-
field.textBox({ placeholder: 'Enter tab title' });
|
|
2467
|
-
})
|
|
2468
|
-
.formField('Chats', field => {
|
|
2469
|
-
field.path('rooms');
|
|
2470
|
-
field.selectBox({ valueField: 'id', textField: 'title', dataSource: roomOptions, multiple: true });
|
|
2471
|
-
});
|
|
2472
|
-
});
|
|
2473
|
-
})
|
|
2474
|
-
.setActions(actions => {
|
|
2475
|
-
actions.cancel('Cancel').submit('Create');
|
|
2476
|
-
});
|
|
2477
|
-
})
|
|
2478
|
-
.show();
|
|
2479
|
-
const action = dialogRef.action();
|
|
2480
|
-
const ctx = dialogRef.context();
|
|
2481
|
-
dialogRef.close();
|
|
2482
|
-
if (action === 'cancel' || !ctx?.title)
|
|
2483
|
-
return;
|
|
2484
|
-
try {
|
|
2485
|
-
const name = ctx.title.trim().toLowerCase().replace(/\s+/g, '-').slice(0, 64);
|
|
2486
|
-
const selected = Array.isArray(ctx.rooms) ? ctx.rooms : [];
|
|
2487
|
-
const selectedIds = selected
|
|
2488
|
-
.map((v) => (typeof v === 'string' ? v : v?.id))
|
|
2489
|
-
.filter((v) => typeof v === 'string' && v.length > 0);
|
|
2490
|
-
const includeRooms = rooms.filter((r) => selectedIds.includes(r.id));
|
|
2491
|
-
await this.chatService.createTab({ name, title: ctx.title.trim(), includeRooms, excludeRooms: [] });
|
|
2492
|
-
await this.loadTabs();
|
|
2493
|
-
}
|
|
2494
|
-
catch (err) {
|
|
2495
|
-
console.error('Failed to create tab', err);
|
|
2496
|
-
}
|
|
2497
|
-
break;
|
|
2498
|
-
}
|
|
2499
|
-
case 'tab.remove': {
|
|
2500
|
-
await this.deleteTab(this.contextTab);
|
|
2501
|
-
break;
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
// (this.tab() as any).setIndicatorPosition(this.activeTab());
|
|
2505
|
-
}
|
|
2506
|
-
onContextItemClick(e) {
|
|
2507
|
-
if (!this.contextRoom)
|
|
2508
|
-
return;
|
|
2509
|
-
const roomId = this.contextRoom.id;
|
|
2510
|
-
switch (e.item.name) {
|
|
2511
|
-
case 'open':
|
|
2512
|
-
this.openChat(roomId);
|
|
2513
|
-
break;
|
|
2514
|
-
case 'mark-seen':
|
|
2515
|
-
this.chatService
|
|
2516
|
-
.markRoomSeen(roomId)
|
|
2517
|
-
.catch(async () => this.toastService.danger(await this.translateService.translateAsync('@conversation:messages.mark-seen-failed')));
|
|
2518
|
-
break;
|
|
2519
|
-
// case 'mute':
|
|
2520
|
-
// this.toastService.warning('Mute not implemented yet');
|
|
2521
|
-
// break;
|
|
2522
|
-
default: {
|
|
2523
|
-
// Toggle tab inclusion: names are in the form 'tab.toggle:<tabId>'
|
|
2524
|
-
if (typeof e.item.name === 'string' && e.item.name.startsWith('tab.toggle:')) {
|
|
2525
|
-
const tabId = e.item.name.split(':')[1];
|
|
2526
|
-
const currentTabs = this.tabs();
|
|
2527
|
-
const foundTab = currentTabs.find((t) => t.id === tabId);
|
|
2528
|
-
if (!foundTab) {
|
|
2529
|
-
this.toastService.danger('@conversation:messages.tab-not-found');
|
|
2530
|
-
return;
|
|
2531
|
-
}
|
|
2532
|
-
const isIncluded = (foundTab.includeRooms || []).some((r) => r.id === roomId);
|
|
2533
|
-
const op = isIncluded
|
|
2534
|
-
? this.chatService.removeIncludeRoomFromTab(tabId, roomId)
|
|
2535
|
-
: this.chatService.addIncludeRoomToTab(tabId, roomId);
|
|
2536
|
-
op.then(async (updatedTab) => {
|
|
2537
|
-
this.tabs.update((tabs) => tabs.map((t) => (t.id === updatedTab.id ? updatedTab : t)));
|
|
2538
|
-
this.toastService.success(await this.translateService.translateAsync(isIncluded ? '@conversation:messages.tab-removed' : '@conversation:messages.tab-added'));
|
|
2539
|
-
}).catch(async () => this.toastService.danger(await this.translateService.translateAsync('@conversation:messages.tab-update-failed')));
|
|
2540
|
-
return;
|
|
2541
|
-
}
|
|
2542
|
-
break;
|
|
2543
|
-
}
|
|
2544
|
-
case 'tab.remove-current': {
|
|
2545
|
-
const at = this.activeTab();
|
|
2546
|
-
if (!at || at.name === 'all' || at.name === 'unread') {
|
|
2547
|
-
return;
|
|
2548
|
-
}
|
|
2549
|
-
this.chatService
|
|
2550
|
-
.removeIncludeRoomFromTab(at.id, roomId)
|
|
2551
|
-
.then(async (updatedTab) => {
|
|
2552
|
-
this.tabs.update((tabs) => tabs.map((t) => (t.id === updatedTab.id ? updatedTab : t)));
|
|
2553
|
-
this.toastService.success(await this.translateService.translateAsync('@conversation:messages.tab-removed'));
|
|
2554
|
-
})
|
|
2555
|
-
.catch(async () => this.toastService.danger(await this.translateService.translateAsync('@conversation:messages.tab-remove-failed')));
|
|
2556
|
-
break;
|
|
2557
|
-
}
|
|
2558
|
-
case 'delete-room':
|
|
2559
|
-
this.deleteRoom(roomId);
|
|
2560
|
-
break;
|
|
2561
|
-
case 'leave-room': {
|
|
2562
|
-
const currentUserId = this.sessionService.user?.id;
|
|
2563
|
-
this.chatService
|
|
2564
|
-
.removeParticipant(roomId, currentUserId)
|
|
2565
|
-
.then(() => {
|
|
2566
|
-
if (this.selectedRoom()?.id === roomId) {
|
|
2567
|
-
this.router.navigate(['./'], { relativeTo: this.activatedRoute });
|
|
2568
|
-
}
|
|
2569
|
-
})
|
|
2570
|
-
.catch(async () => this.toastService.danger('Failed to leave'));
|
|
2571
|
-
break;
|
|
2572
|
-
}
|
|
2573
|
-
}
|
|
2574
|
-
}
|
|
2575
|
-
onKeydownHandler(event) {
|
|
2576
|
-
if (this.selectedRoom()) {
|
|
2577
|
-
this.onBackButtonClick();
|
|
2578
|
-
}
|
|
2579
|
-
}
|
|
2580
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMChatComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2581
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMChatComponent, isStandalone: true, selector: "axm-chat", host: { listeners: { "document:keydown.escape": "onKeydownHandler($event)" } }, providers: [
|
|
2582
|
-
{
|
|
2583
|
-
provide: AXPPageLayoutBase,
|
|
2584
|
-
useExisting: AXMChatComponent,
|
|
2585
|
-
},
|
|
2586
|
-
AXUnsubscriber,
|
|
2587
|
-
], viewQueries: [{ propertyName: "tab", first: true, predicate: ["tab"], descendants: true, isSignal: true }, { propertyName: "container", first: true, predicate: ["container"], descendants: true, isSignal: true }, { propertyName: "chatContext", first: true, predicate: ["chatContext"], descendants: true, isSignal: true }, { propertyName: "tabContext", first: true, predicate: ["tabContext"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<axp-page-layout #container>\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header>\n <axp-layout-title>{{ '@conversation:module-name' | translate | async }}</axp-layout-title>\n <axp-layout-toolbar>\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"'@conversation:search.placeholder' | translate | async\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </axp-layout-toolbar>\n </axp-layout-header>\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n @if (!layoutService.isMobileDevice()) {\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-layout-content>\n </axp-layout-start-side>\n\n <axp-page-content\n style=\"height: calc(100vh - 22rem)\"\n [style.padding]=\"layoutService.isMobileDevice() ? '1rem !important' : '0 !important'\"\n >\n @if (selectedRoom()) {\n <router-outlet></router-outlet>\n } @else if (layoutService.isMobileDevice()) {\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"'@conversation:search.placeholder' | translate | async\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full ax-mb-2\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-page-content>\n</axp-page-layout>\n<ng-template #template>\n <!-- Tabs -->\n <div [class]=\"!layoutService.isMobileDevice() ? 'ax-px-4' : ''\">\n <ax-tabs\n #tab\n class=\"ax-text-neutral-400 !ax-overflow-x-hidden\"\n [look]=\"'with-line'\"\n [location]=\"'bottom'\"\n [fitParent]=\"true\"\n (onActiveTabChanged)=\"activeTabIndex.set($event.index)\"\n >\n @for (tab of tabs(); track tab.id; let i = $index) {\n <ax-tab-item\n [text]=\"tab.title\"\n [active]=\"activeTabIndex() === i\"\n (contextmenu)=\"openTabContextMenu($event, tab, i)\"\n >\n @if (getRoomCountForTab(tab) > 0) {\n <ax-suffix>\n <ax-badge\n [text]=\"getRoomCountForTab(tab).toString()\"\n [color]=\"activeTabIndex() === i ? 'primary' : 'secondary'\"\n class=\"ax-min-w-[1.5rem] ax-justify-center\"\n ></ax-badge>\n </ax-suffix>\n }\n </ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n <!-- Chat List Content -->\n <div\n class=\"ax-flex-1 ax-overflow-hidden ax-flex ax-flex-col ax-justify-between ax-min-w-80\"\n [class.ax-border-t]=\"tabs().length > 0\"\n >\n <!-- Loading State -->\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-space-y-4\">\n @for (_ of [1, 2, 3, 4, 5, 6]; track $index) {\n <div class=\"ax-flex ax-items-center ax-space-x-3\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-12 ax-h-12 ax-rounded-full\"></ax-skeleton>\n <div class=\"ax-flex-1 ax-space-y-2\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-3/4 ax-h-4 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"ax-w-1/2 ax-h-3 ax-rounded-md\"></ax-skeleton>\n </div>\n </div>\n }\n </div>\n } @else if (error()) {\n <axp-state-message\n mode=\"error\"\n icon=\"fa-light fa-circle-exclamation\"\n [title]=\"'@conversation:chat-error'\"\n [description]=\"error() || '@conversation:state-message.error.description'\"\n >\n <ax-button\n slot=\"actions\"\n [text]=\"'@conversation:try-again' | translate | async\"\n color=\"primary\"\n (onClick)=\"refreshChat()\"\n ></ax-button>\n </axp-state-message>\n } @else {\n <div class=\"ax-flex-1 ax-overflow-y-auto ax-pt-1\">\n @for (i of filteredRooms(); track i.id) {\n @if (layoutService.isMobileDevice()) {\n <ax-sliding-item class=\"ax-h-20\">\n <ax-content class=\"!ax-p-0\">\n <axm-chat-item\n [data]=\"i\"\n [typing]=\"$any(typingStatus()[i.id])\"\n [lastMessageReaction]=\"i.lastMessage?.reactions?.[0]?.type ?? null\"\n [attr.data-id]=\"i.id\"\n (click)=\"openChat(i.id)\"\n [class.ax-bg-dark]=\"selectedRoom()?.id === i.id\"\n class=\"ax-transition-all ax-duration-100 hover:ax-bg-surface ax-block\"\n [@fadeIn]\n tabindex=\"0\"\n (keydown.enter)=\"openChat(i.id)\"\n role=\"button\"\n (contextmenu)=\"openContextMenu($event, i)\"\n ></axm-chat-item>\n </ax-content>\n\n <!-- <ax-sliding-item-suffix (onClick)=\"onSlideAction(i, 'mute')\" color=\"warning\">\n <ax-icon class=\"fa-light fa-bell-slash fa-lg\"></ax-icon>\n </ax-sliding-item-suffix> -->\n <ax-sliding-item-suffix (onClick)=\"onSlideAction(i, 'delete')\" color=\"danger\">\n <ax-icon class=\"fa-light fa-trash-can fa-lg\"></ax-icon>\n </ax-sliding-item-suffix>\n </ax-sliding-item>\n } @else {\n <axm-chat-item\n [data]=\"i\"\n [typing]=\"$any(typingStatus()[i.id])\"\n [lastMessageReaction]=\"i.lastMessage?.reactions?.[0]?.type ?? null\"\n [attr.data-id]=\"i.id\"\n (click)=\"openChat(i.id)\"\n [class.ax-bg-dark]=\"selectedRoom()?.id === i.id\"\n class=\"ax-transition-all ax-duration-100 hover:ax-bg-surface\"\n [@fadeIn]\n tabindex=\"0\"\n (keydown.enter)=\"openChat(i.id)\"\n role=\"button\"\n (contextmenu)=\"openContextMenu($event, i)\"\n ></axm-chat-item>\n }\n } @empty {\n <axp-state-message\n icon=\"fa-light fa-comments\"\n [title]=\"'@conversation:no-chats-found.title'\"\n [description]=\"'@conversation:no-chats-found.description'\"\n >\n </axp-state-message>\n }\n </div>\n }\n\n <!-- Footer Content -->\n @if (!layoutService.isMobileDevice()) {\n <div class=\"ax-border-t ax-border-divider ax-bg-lightest ax-p-4\">\n <ax-button\n class=\"ax-w-full\"\n color=\"primary\"\n [text]=\"'@conversation:new-conversation.button' | translate | async\"\n (onClick)=\"onNewConversation()\"\n >\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n } @else {\n <ax-button\n class=\"ax-fixed ax-bottom-16 ax-right-8 !ax-rounded-full !ax-w-14 !ax-h-14 ax-shadow-lg\"\n color=\"primary\"\n (onClick)=\"onNewConversation()\"\n >\n <ax-icon class=\"ax-text-2xl\">\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n</ng-template>\n\n<ax-context-menu\n #chatContext\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n [orientation]=\"'vertical'\"\n (onOpening)=\"onContextOpening($event)\"\n (onItemClick)=\"onContextItemClick($event)\"\n></ax-context-menu>\n\n<ax-context-menu\n #tabContext\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n [orientation]=\"'vertical'\"\n (onOpening)=\"onTabContextOpening($event)\"\n (onItemClick)=\"onTabContextItemClick($event)\"\n></ax-context-menu>\n", styles: [""], dependencies: [{ kind: "component", type: AXMChatItemComponent, selector: "axm-chat-item", inputs: ["data", "typing", "lastMessageReaction"], outputs: ["pressChatItem"] }, { kind: "ngmodule", type:
|
|
2588
|
-
// Common Modules
|
|
2589
|
-
CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type:
|
|
2590
|
-
// Acorex Core Modules
|
|
2591
|
-
AXFormatModule }, { kind: "ngmodule", type: AXConversationModule }, { kind: "ngmodule", type: AXCommentModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type:
|
|
2592
|
-
// Acorex Component Modules
|
|
2593
|
-
// AXResizableDirective,
|
|
2594
|
-
AXImageModule }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXSlidingItemModule }, { kind: "component", type: i4$1.AXSlidingItemComponent, selector: "ax-sliding-item" }, { kind: "component", type: i4$1.AXSlidingItemSuffixComponent, selector: "ax-sliding-item-suffix", inputs: ["color", "text"], outputs: ["onClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i5.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i5.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i5.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: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i6.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: "ngmodule", type: AXTabsModule }, { kind: "component", type: i7.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i7.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5$1.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: AXLoadingModule }, { kind: "ngmodule", type: AXWysiwygModule }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i9.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }, { kind: "component", type: AXPThemeLayoutToolbarComponent, selector: "axp-layout-toolbar" }, { kind: "component", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "items", "target"], outputs: ["onItemClick", "onOpening"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "variant"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], animations: [
|
|
2595
|
-
trigger('fadeIn', [
|
|
2596
|
-
transition(':enter', [
|
|
2597
|
-
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
2598
|
-
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
2599
|
-
]),
|
|
2600
|
-
]),
|
|
2601
|
-
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1554
|
+
}),
|
|
1555
|
+
], ngImport: i0, template: "<axp-page-layout #container axConversationContainer>\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header> </axp-layout-header>\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n <div class=\"ax-h-full ax-flex ax-flex-col ax-shrink-0 md:ax-flex\" [class.ax-hidden]=\"mobileView() === 'chat'\">\n <ax-conversation-sidebar></ax-conversation-sidebar>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n <axp-page-header> </axp-page-header>\n\n <axp-page-content class=\"ax-h-full ax-overflow-hidden ax-p-0\">\n <ax-conversation-info-bar>\n <ax-prefix>\n <ax-button look=\"blank\" class=\"md:ax-hidden\" (onClick)=\"goBackToList()\">\n <ax-icon icon=\"fa-solid fa-arrow-left\"></ax-icon>\n </ax-button>\n </ax-prefix>\n </ax-conversation-info-bar>\n <ax-conversation-message-list class=\"ax-flex-1 ax-overflow-hidden\"></ax-conversation-message-list>\n </axp-page-content>\n\n <axp-page-footer class=\"ax-block\">\n <ax-conversation-composer></ax-conversation-composer>\n </axp-page-footer>\n</axp-page-layout>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: AXConversationContainerDirective, selector: "[axConversationContainer]" }, { kind: "component", type: AXSidebarComponent, selector: "ax-conversation-sidebar", outputs: ["conversationSelected"] }, { kind: "component", type: AXInfoBarComponent, selector: "ax-conversation-info-bar", outputs: ["avatarClick", "searchClick", "searchQuery", "menuItemAction"] }, { kind: "component", type: AXMessageListComponent, selector: "ax-conversation-message-list", inputs: ["avatarTemplate"], outputs: ["messageAction"] }, { kind: "component", type: AXComposerComponent, selector: "ax-conversation-composer", outputs: ["messageSent", "emojiClick", "attachClick", "voiceClick"] }, { 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.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: "ngmodule", type: AXTranslationModule }, { kind: "component", type:
|
|
1556
|
+
// AXP Layout
|
|
1557
|
+
AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2602
1558
|
}
|
|
2603
1559
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMChatComponent, decorators: [{
|
|
2604
1560
|
type: Component,
|
|
2605
|
-
args: [{ selector: 'axm-chat', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2606
|
-
{
|
|
2607
|
-
provide: AXPPageLayoutBase,
|
|
2608
|
-
useExisting: AXMChatComponent,
|
|
2609
|
-
},
|
|
2610
|
-
AXUnsubscriber,
|
|
2611
|
-
], imports: [
|
|
2612
|
-
AXMChatItemComponent,
|
|
2613
|
-
// Common Modules
|
|
1561
|
+
args: [{ selector: 'axm-chat', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
2614
1562
|
CommonModule,
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
AXTranslationModule,
|
|
2622
|
-
// Acorex Component Modules
|
|
2623
|
-
// AXResizableDirective,
|
|
2624
|
-
AXImageModule,
|
|
2625
|
-
AXAvatarModule,
|
|
2626
|
-
AXBadgeModule,
|
|
2627
|
-
AXSlidingItemModule,
|
|
1563
|
+
AXConversationContainerDirective,
|
|
1564
|
+
AXSidebarComponent,
|
|
1565
|
+
AXInfoBarComponent,
|
|
1566
|
+
AXMessageListComponent,
|
|
1567
|
+
AXComposerComponent,
|
|
1568
|
+
AXButtonComponent,
|
|
2628
1569
|
AXDecoratorModule,
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
AXTabsModule,
|
|
2632
|
-
AXButtonModule,
|
|
2633
|
-
AXLoadingModule,
|
|
2634
|
-
AXWysiwygModule,
|
|
2635
|
-
AXLabelModule,
|
|
2636
|
-
AXSelectBoxModule,
|
|
2637
|
-
AXFormModule,
|
|
2638
|
-
AXDropdownButtonModule,
|
|
2639
|
-
AXDropdownModule,
|
|
2640
|
-
AXToolBarModule,
|
|
2641
|
-
AXSkeletonModule,
|
|
1570
|
+
AXTranslationModule,
|
|
1571
|
+
// AXP Layout
|
|
2642
1572
|
AXPPageLayoutComponent,
|
|
2643
1573
|
AXPThemeLayoutBlockComponent,
|
|
2644
1574
|
AXPThemeLayoutStartSideComponent,
|
|
2645
|
-
AXPThemeLayoutHeaderComponent
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
1575
|
+
AXPThemeLayoutHeaderComponent
|
|
1576
|
+
], providers: [
|
|
1577
|
+
...provideConversation({
|
|
1578
|
+
userApi: AXIndexedDBUserApi,
|
|
1579
|
+
conversationApi: AXIndexedDBConversationApi,
|
|
1580
|
+
messageApi: AXIndexedDBMessageAIApi,
|
|
1581
|
+
realtimeApi: AXIndexedDBRealtimeApi,
|
|
1582
|
+
config: {},
|
|
1583
|
+
registry: {
|
|
1584
|
+
messageRenderers: [
|
|
1585
|
+
AX_CONVERSATION_TEXT_RENDERER,
|
|
1586
|
+
AX_CONVERSATION_IMAGE_RENDERER,
|
|
1587
|
+
AX_CONVERSATION_VIDEO_RENDERER,
|
|
1588
|
+
AX_CONVERSATION_AUDIO_RENDERER,
|
|
1589
|
+
AX_CONVERSATION_VOICE_RENDERER,
|
|
1590
|
+
AX_CONVERSATION_FILE_RENDERER,
|
|
1591
|
+
AX_CONVERSATION_LOCATION_RENDERER,
|
|
1592
|
+
AX_CONVERSATION_STICKER_RENDERER,
|
|
1593
|
+
AX_CONVERSATION_CONTACT_RENDERER,
|
|
1594
|
+
],
|
|
1595
|
+
messageActions: [
|
|
1596
|
+
AX_CONVERSATION_MESSAGE_REPLY_ACTION,
|
|
1597
|
+
AX_CONVERSATION_MESSAGE_FORWARD_ACTION,
|
|
1598
|
+
AX_CONVERSATION_MESSAGE_EDIT_ACTION,
|
|
1599
|
+
AX_CONVERSATION_MESSAGE_DELETE_ACTION,
|
|
1600
|
+
],
|
|
1601
|
+
composerActions: [
|
|
1602
|
+
AX_CONVERSATION_COMPOSER_EMOJI_ACTION,
|
|
1603
|
+
AX_CONVERSATION_COMPOSER_IMAGE_ACTION,
|
|
1604
|
+
AX_CONVERSATION_COMPOSER_VIDEO_ACTION,
|
|
1605
|
+
AX_CONVERSATION_COMPOSER_FILE_ACTION,
|
|
1606
|
+
AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION,
|
|
1607
|
+
AX_CONVERSATION_COMPOSER_AUDIO_ACTION,
|
|
1608
|
+
AX_CONVERSATION_COMPOSER_CONTACT_ACTION,
|
|
1609
|
+
AX_CONVERSATION_COMPOSER_LOCATION_ACTION,
|
|
1610
|
+
],
|
|
1611
|
+
composerTabs: [AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_STICKER_TAB],
|
|
1612
|
+
conversationTabs: [
|
|
1613
|
+
AX_CONVERSATION_TAB_ALL,
|
|
1614
|
+
AX_CONVERSATION_TAB_PRIVATE,
|
|
1615
|
+
AX_CONVERSATION_TAB_GROUPS,
|
|
1616
|
+
AX_CONVERSATION_TAB_CHANNELS,
|
|
1617
|
+
AX_CONVERSATION_TAB_UNREAD,
|
|
1618
|
+
AX_CONVERSATION_TAB_ARCHIVED,
|
|
1619
|
+
],
|
|
1620
|
+
infoBarActions: [
|
|
1621
|
+
AX_CONVERSATION_INFO_BAR_SEARCH_ACTION,
|
|
1622
|
+
AX_CONVERSATION_INFO_BAR_INFO_ACTION,
|
|
1623
|
+
AX_CONVERSATION_INFO_BAR_MUTE_ACTION,
|
|
1624
|
+
AX_CONVERSATION_INFO_BAR_DIVIDER,
|
|
1625
|
+
AX_CONVERSATION_INFO_BAR_DELETE_ACTION,
|
|
1626
|
+
AX_CONVERSATION_INFO_BAR_BLOCK_ACTION,
|
|
1627
|
+
],
|
|
1628
|
+
conversationItemActions: [
|
|
1629
|
+
AX_CONVERSATION_ITEM_MUTE_ACTION,
|
|
1630
|
+
AX_CONVERSATION_ITEM_PIN_ACTION,
|
|
1631
|
+
AX_CONVERSATION_ITEM_MARK_READ_ACTION,
|
|
1632
|
+
AX_CONVERSATION_ITEM_DIVIDER,
|
|
1633
|
+
AX_CONVERSATION_ITEM_DELETE_ACTION,
|
|
1634
|
+
AX_CONVERSATION_ITEM_BLOCK_ACTION,
|
|
1635
|
+
],
|
|
1636
|
+
},
|
|
1637
|
+
}),
|
|
1638
|
+
], template: "<axp-page-layout #container axConversationContainer>\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header> </axp-layout-header>\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n <div class=\"ax-h-full ax-flex ax-flex-col ax-shrink-0 md:ax-flex\" [class.ax-hidden]=\"mobileView() === 'chat'\">\n <ax-conversation-sidebar></ax-conversation-sidebar>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n <axp-page-header> </axp-page-header>\n\n <axp-page-content class=\"ax-h-full ax-overflow-hidden ax-p-0\">\n <ax-conversation-info-bar>\n <ax-prefix>\n <ax-button look=\"blank\" class=\"md:ax-hidden\" (onClick)=\"goBackToList()\">\n <ax-icon icon=\"fa-solid fa-arrow-left\"></ax-icon>\n </ax-button>\n </ax-prefix>\n </ax-conversation-info-bar>\n <ax-conversation-message-list class=\"ax-flex-1 ax-overflow-hidden\"></ax-conversation-message-list>\n </axp-page-content>\n\n <axp-page-footer class=\"ax-block\">\n <ax-conversation-composer></ax-conversation-composer>\n </axp-page-footer>\n</axp-page-layout>\n" }]
|
|
1639
|
+
}], ctorParameters: () => [] });
|
|
2661
1640
|
|
|
2662
1641
|
var chat_component = /*#__PURE__*/Object.freeze({
|
|
2663
1642
|
__proto__: null,
|
|
2664
1643
|
AXMChatComponent: AXMChatComponent
|
|
2665
1644
|
});
|
|
2666
1645
|
|
|
2667
|
-
/**
|
|
2668
|
-
* Converts chat service response to chat preview format
|
|
2669
|
-
* @param chatResponse - The response from chat service containing items and total
|
|
2670
|
-
* @returns Array of formatted chat preview messages
|
|
2671
|
-
*/
|
|
2672
|
-
function convertToChatPreview(currentUserId, chatResponse, userName) {
|
|
2673
|
-
if (!chatResponse || !chatResponse.items?.length) {
|
|
2674
|
-
return [];
|
|
2675
|
-
}
|
|
2676
|
-
// Map from AXMChatMessage to ChatPreviewMessage
|
|
2677
|
-
return chatResponse.items.map((message) => {
|
|
2678
|
-
// Determine message type based on content type
|
|
2679
|
-
let messageType = 'text';
|
|
2680
|
-
// Map contentType to preview type
|
|
2681
|
-
if (message.message?.contentType) {
|
|
2682
|
-
switch (message.message.contentType) {
|
|
2683
|
-
case 'text':
|
|
2684
|
-
messageType = 'text';
|
|
2685
|
-
break;
|
|
2686
|
-
case 'file':
|
|
2687
|
-
messageType = 'file';
|
|
2688
|
-
break;
|
|
2689
|
-
case 'image':
|
|
2690
|
-
messageType = 'image';
|
|
2691
|
-
break;
|
|
2692
|
-
case 'video':
|
|
2693
|
-
messageType = 'video';
|
|
2694
|
-
break;
|
|
2695
|
-
case 'link':
|
|
2696
|
-
// Determine if link is for audio or other content
|
|
2697
|
-
const content = message.message.content || '';
|
|
2698
|
-
if (content.includes('.mp3') || content.includes('.ogg') || content.includes('audio')) {
|
|
2699
|
-
messageType = 'audio';
|
|
2700
|
-
}
|
|
2701
|
-
else {
|
|
2702
|
-
messageType = 'text';
|
|
2703
|
-
}
|
|
2704
|
-
break;
|
|
2705
|
-
default:
|
|
2706
|
-
messageType = 'text';
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
2709
|
-
// Extract author name if available
|
|
2710
|
-
const name = message.author ? message.author.id : 'Unknown';
|
|
2711
|
-
// Create the chat preview message
|
|
2712
|
-
const previewMessage = {
|
|
2713
|
-
id: message.id,
|
|
2714
|
-
sendTime: new Date(message.auditInfo?.created?.at || new Date()),
|
|
2715
|
-
readTime: new Date(), // Assuming "read" when converted
|
|
2716
|
-
type: messageType,
|
|
2717
|
-
content: message.message?.content || '',
|
|
2718
|
-
name: name,
|
|
2719
|
-
userName,
|
|
2720
|
-
};
|
|
2721
|
-
// Add fromId if the message is not from current user
|
|
2722
|
-
if (currentUserId !== message.author.id) {
|
|
2723
|
-
previewMessage.fromId = message.author?.id;
|
|
2724
|
-
}
|
|
2725
|
-
else {
|
|
2726
|
-
previewMessage.showActionButton = true;
|
|
2727
|
-
}
|
|
2728
|
-
// Note: Reply information would need to be looked up from the actual messages
|
|
2729
|
-
// This would typically be done by the service that has access to all messages
|
|
2730
|
-
return previewMessage;
|
|
2731
|
-
});
|
|
2732
|
-
}
|
|
2733
|
-
/**
|
|
2734
|
-
* Creates a ChatPreviewMessage from reply information
|
|
2735
|
-
* @param message - The original message that is being referenced
|
|
2736
|
-
* @returns A ChatPreviewMessage formatted for use as a replyTo
|
|
2737
|
-
*/
|
|
2738
|
-
function createReplyPreview(currentUserId, message, userName) {
|
|
2739
|
-
if (!message)
|
|
2740
|
-
return undefined;
|
|
2741
|
-
return {
|
|
2742
|
-
id: message.id,
|
|
2743
|
-
sendTime: new Date(message.auditInfo?.created?.at || new Date()),
|
|
2744
|
-
readTime: new Date(),
|
|
2745
|
-
type: message.message?.contentType === 'image'
|
|
2746
|
-
? 'image'
|
|
2747
|
-
: message.message?.contentType === 'video'
|
|
2748
|
-
? 'video'
|
|
2749
|
-
: message.message?.contentType === 'file'
|
|
2750
|
-
? 'file'
|
|
2751
|
-
: 'text',
|
|
2752
|
-
content: message.message?.content || '',
|
|
2753
|
-
name: message.author?.id || 'Unknown',
|
|
2754
|
-
fromId: currentUserId !== message.author.id ? message.author?.id : undefined,
|
|
2755
|
-
showActionButton: true,
|
|
2756
|
-
userName,
|
|
2757
|
-
};
|
|
2758
|
-
}
|
|
2759
|
-
/**
|
|
2760
|
-
* Generate demo chat preview data with a variety of message types
|
|
2761
|
-
* @returns Array of sample chat preview messages
|
|
2762
|
-
*/
|
|
2763
|
-
function generateDemoChatPreview() {
|
|
2764
|
-
return [
|
|
2765
|
-
{
|
|
2766
|
-
id: '0',
|
|
2767
|
-
sendTime: new Date(),
|
|
2768
|
-
type: 'text',
|
|
2769
|
-
readTime: new Date(),
|
|
2770
|
-
content: 'Hello John, How are you?',
|
|
2771
|
-
name: 'test name',
|
|
2772
|
-
},
|
|
2773
|
-
{
|
|
2774
|
-
id: '1',
|
|
2775
|
-
fromId: '10',
|
|
2776
|
-
sendTime: new Date(),
|
|
2777
|
-
readTime: new Date(),
|
|
2778
|
-
type: 'text',
|
|
2779
|
-
content: 'Hello',
|
|
2780
|
-
name: 'test name',
|
|
2781
|
-
replyTo: {
|
|
2782
|
-
id: '0',
|
|
2783
|
-
sendTime: new Date(),
|
|
2784
|
-
type: 'text',
|
|
2785
|
-
readTime: new Date(),
|
|
2786
|
-
content: 'Hello John, How are you?',
|
|
2787
|
-
name: 'test name',
|
|
2788
|
-
},
|
|
2789
|
-
},
|
|
2790
|
-
{
|
|
2791
|
-
id: '2',
|
|
2792
|
-
fromId: '10',
|
|
2793
|
-
sendTime: new Date(),
|
|
2794
|
-
readTime: new Date(),
|
|
2795
|
-
type: 'voice',
|
|
2796
|
-
name: 'test name',
|
|
2797
|
-
content: `data:audio/webm;codecs=opus;base64,GkXfoEF34fJ`,
|
|
2798
|
-
},
|
|
2799
|
-
{
|
|
2800
|
-
id: '3',
|
|
2801
|
-
sendTime: new Date(),
|
|
2802
|
-
readTime: new Date(),
|
|
2803
|
-
type: 'text',
|
|
2804
|
-
content: 'Can i have your address information?',
|
|
2805
|
-
name: 'test name',
|
|
2806
|
-
replyTo: {
|
|
2807
|
-
id: '1',
|
|
2808
|
-
fromId: '10',
|
|
2809
|
-
sendTime: new Date(),
|
|
2810
|
-
readTime: new Date(),
|
|
2811
|
-
type: 'text',
|
|
2812
|
-
content: 'Hello',
|
|
2813
|
-
name: 'test name',
|
|
2814
|
-
},
|
|
2815
|
-
},
|
|
2816
|
-
{
|
|
2817
|
-
id: '4',
|
|
2818
|
-
fromId: '10',
|
|
2819
|
-
sendTime: new Date(),
|
|
2820
|
-
readTime: new Date(),
|
|
2821
|
-
type: 'file',
|
|
2822
|
-
name: 'test name',
|
|
2823
|
-
content: `data:audio/webm;codecs=opus;base64,GkXfoEF34fJ`,
|
|
2824
|
-
},
|
|
2825
|
-
{
|
|
2826
|
-
id: '5',
|
|
2827
|
-
sendTime: new Date(),
|
|
2828
|
-
readTime: new Date(),
|
|
2829
|
-
type: 'image',
|
|
2830
|
-
name: 'test name',
|
|
2831
|
-
content: `https://picsum.photos/300/200`,
|
|
2832
|
-
},
|
|
2833
|
-
{
|
|
2834
|
-
id: '6',
|
|
2835
|
-
sendTime: new Date(),
|
|
2836
|
-
readTime: new Date(),
|
|
2837
|
-
type: 'video',
|
|
2838
|
-
name: 'test name',
|
|
2839
|
-
content: `https://www.pexels.com/download/video/5495322/?fps=29.97&h=540&w=960`,
|
|
2840
|
-
},
|
|
2841
|
-
{
|
|
2842
|
-
id: '7',
|
|
2843
|
-
sendTime: new Date(),
|
|
2844
|
-
type: 'text',
|
|
2845
|
-
readTime: new Date(),
|
|
2846
|
-
content: 'Hello John, How are you?',
|
|
2847
|
-
name: 'test name',
|
|
2848
|
-
},
|
|
2849
|
-
{
|
|
2850
|
-
id: '8',
|
|
2851
|
-
fromId: '10',
|
|
2852
|
-
sendTime: new Date(),
|
|
2853
|
-
readTime: new Date(),
|
|
2854
|
-
type: 'audio',
|
|
2855
|
-
name: 'kids',
|
|
2856
|
-
content: `https://actions.google.com/sounds/v1/ambiences/kids_playing.ogg`,
|
|
2857
|
-
},
|
|
2858
|
-
{
|
|
2859
|
-
id: '9',
|
|
2860
|
-
fromId: '10',
|
|
2861
|
-
sendTime: new Date(),
|
|
2862
|
-
readTime: new Date(),
|
|
2863
|
-
type: 'image',
|
|
2864
|
-
name: 'test name',
|
|
2865
|
-
content: `https://picsum.photos/300/200`,
|
|
2866
|
-
},
|
|
2867
|
-
{
|
|
2868
|
-
id: '10',
|
|
2869
|
-
fromId: '10',
|
|
2870
|
-
sendTime: new Date(),
|
|
2871
|
-
readTime: new Date(),
|
|
2872
|
-
type: 'image',
|
|
2873
|
-
name: 'test name',
|
|
2874
|
-
content: `https://picsum.photos/200/300`,
|
|
2875
|
-
},
|
|
2876
|
-
{
|
|
2877
|
-
id: '11',
|
|
2878
|
-
fromId: '10',
|
|
2879
|
-
sendTime: new Date(),
|
|
2880
|
-
readTime: new Date(),
|
|
2881
|
-
type: 'video',
|
|
2882
|
-
name: 'test name',
|
|
2883
|
-
content: `https://www.pexels.com/download/video/5495322/?fps=29.97&h=540&w=960`,
|
|
2884
|
-
},
|
|
2885
|
-
{
|
|
2886
|
-
id: '12',
|
|
2887
|
-
sendTime: new Date(),
|
|
2888
|
-
readTime: new Date(),
|
|
2889
|
-
type: 'file',
|
|
2890
|
-
name: 'test name',
|
|
2891
|
-
content: `data:audio/webm;codecs=opus;base64,GkXfo59ChoE+u5BxHVL7ZAS1EF34fJ`,
|
|
2892
|
-
},
|
|
2893
|
-
{
|
|
2894
|
-
id: '13',
|
|
2895
|
-
sendTime: new Date(),
|
|
2896
|
-
readTime: new Date(),
|
|
2897
|
-
type: 'audio',
|
|
2898
|
-
name: 'alarm',
|
|
2899
|
-
content: `https://actions.google.com/sounds/v1/alarms/digital_watch_alarm_long.ogg`,
|
|
2900
|
-
},
|
|
2901
|
-
];
|
|
2902
|
-
}
|
|
2903
|
-
/**
|
|
2904
|
-
* Usage Examples:
|
|
2905
|
-
*
|
|
2906
|
-
* Example 1: Converting chat service response to chat preview format
|
|
2907
|
-
* ```typescript
|
|
2908
|
-
* import { AXMChatService } from '../chat.service';
|
|
2909
|
-
* import { convertToChatPreview } from './chat-preview.helper';
|
|
2910
|
-
*
|
|
2911
|
-
* export class ChatPreviewComponent {
|
|
2912
|
-
* constructor(private chatService: AXMChatService) {}
|
|
2913
|
-
*
|
|
2914
|
-
* async loadChatMessages(roomId: string) {
|
|
2915
|
-
* const response = await this.chatService.getChatMessages(roomId);
|
|
2916
|
-
*
|
|
2917
|
-
* // Convert to chat preview format
|
|
2918
|
-
* const previewMessages = convertToChatPreview(response);
|
|
2919
|
-
*
|
|
2920
|
-
* // Use the converted messages
|
|
2921
|
-
* this.conversationService.chats.set(previewMessages);
|
|
2922
|
-
* }
|
|
2923
|
-
* }
|
|
2924
|
-
* ```
|
|
2925
|
-
*
|
|
2926
|
-
* Example 2: Using demo data for development/testing
|
|
2927
|
-
* ```typescript
|
|
2928
|
-
* import { generateDemoChatPreview } from './chat-preview.helper';
|
|
2929
|
-
*
|
|
2930
|
-
* export class ChatPreviewDemoComponent {
|
|
2931
|
-
* ngOnInit() {
|
|
2932
|
-
* // Load demo messages
|
|
2933
|
-
* const demoMessages = generateDemoChatPreview();
|
|
2934
|
-
*
|
|
2935
|
-
* // Use the demo messages
|
|
2936
|
-
* this.conversationService.chats.set(demoMessages);
|
|
2937
|
-
* }
|
|
2938
|
-
* }
|
|
2939
|
-
*/
|
|
2940
|
-
|
|
2941
|
-
class AXMChatPreviewComponent {
|
|
2942
|
-
constructor() {
|
|
2943
|
-
this.activatedRoute = inject(ActivatedRoute);
|
|
2944
|
-
this.fileService = inject(AXFileService);
|
|
2945
|
-
this.chatService = inject(AXMChatManagementService);
|
|
2946
|
-
this.realtimeService = inject(AXMChatRealtimeService);
|
|
2947
|
-
this.sessionService = inject(AXPSessionService);
|
|
2948
|
-
this.toastService = inject(AXToastService);
|
|
2949
|
-
this.unsubscribe = inject(AXUnsubscriber);
|
|
2950
|
-
this.inputRef = viewChild(AXConversationInputComponent, ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
|
|
2951
|
-
this.activeMessage = signal(null, ...(ngDevMode ? [{ debugName: "activeMessage" }] : []));
|
|
2952
|
-
this.typing$ = new Subject();
|
|
2953
|
-
this.chatData = signal([], ...(ngDevMode ? [{ debugName: "chatData" }] : []));
|
|
2954
|
-
this.room = signal(null, ...(ngDevMode ? [{ debugName: "room" }] : []));
|
|
2955
|
-
this.isEditing = signal(false, ...(ngDevMode ? [{ debugName: "isEditing" }] : []));
|
|
2956
|
-
this.editId = signal(null, ...(ngDevMode ? [{ debugName: "editId" }] : []));
|
|
2957
|
-
this.height = signal(0, ...(ngDevMode ? [{ debugName: "height" }] : []));
|
|
2958
|
-
this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
2959
|
-
this.error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
2960
|
-
this.isChannel = computed(() => this.room()?.topic === 'channel', ...(ngDevMode ? [{ debugName: "isChannel" }] : []));
|
|
2961
|
-
this.options = signal({
|
|
2962
|
-
disabled: false,
|
|
2963
|
-
readonly: false,
|
|
2964
|
-
value: '',
|
|
2965
|
-
}, ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
2966
|
-
this.roomId = '';
|
|
2967
|
-
//GO TO LAST MESSAGE EFFECT.
|
|
2968
|
-
this.#af = afterNextRender(() => {
|
|
2969
|
-
setTimeout(() => {
|
|
2970
|
-
const div = document.querySelector('ax-conversation-view > div');
|
|
2971
|
-
if (div) {
|
|
2972
|
-
div.scrollTo({ top: div.scrollHeight, behavior: 'smooth' });
|
|
2973
|
-
}
|
|
2974
|
-
}, 500);
|
|
2975
|
-
});
|
|
2976
|
-
}
|
|
2977
|
-
setHeight(height) {
|
|
2978
|
-
this.height.set(height);
|
|
2979
|
-
}
|
|
2980
|
-
ngOnInit() {
|
|
2981
|
-
this.activatedRoute.params.subscribe((params) => {
|
|
2982
|
-
this.roomId = params['id'];
|
|
2983
|
-
if (this.roomId) {
|
|
2984
|
-
this.loadMessages(this.roomId);
|
|
2985
|
-
this.loadRoomInfo(this.roomId);
|
|
2986
|
-
}
|
|
2987
|
-
});
|
|
2988
|
-
this.realtimeService.message$.pipe(this.unsubscribe.takeUntilDestroy).subscribe(async (event) => {
|
|
2989
|
-
if (event.type === 'add') {
|
|
2990
|
-
const message = event.payload;
|
|
2991
|
-
if (message.author.id !== this.sessionService.user?.id && message.roomId === this.roomId) {
|
|
2992
|
-
await this.chatService.markSeen(message.id);
|
|
2993
|
-
this.chatData.update((values) => {
|
|
2994
|
-
const newMessage = convertToChatPreview(this.sessionService.user?.id || '', {
|
|
2995
|
-
items: [message],
|
|
2996
|
-
total: 1,
|
|
2997
|
-
})[0];
|
|
2998
|
-
return [...values, newMessage];
|
|
2999
|
-
});
|
|
3000
|
-
}
|
|
3001
|
-
}
|
|
3002
|
-
else if (event.type === 'remove') {
|
|
3003
|
-
this.chatData.update((values) => values.filter((item) => item.id !== event.payload));
|
|
3004
|
-
}
|
|
3005
|
-
else if (event.type === 'update') {
|
|
3006
|
-
const message = event.payload;
|
|
3007
|
-
const convertedNewMessage = convertToChatPreview(this.sessionService.user?.id || '', {
|
|
3008
|
-
items: [message],
|
|
3009
|
-
total: 1,
|
|
3010
|
-
})[0];
|
|
3011
|
-
this.chatData.update((values) => values.map((item) => (item.id === message.id ? { ...convertedNewMessage, ...item } : item)));
|
|
3012
|
-
}
|
|
3013
|
-
});
|
|
3014
|
-
this.typingSubscription = this.typing$.pipe(debounceTime(1000)).subscribe(() => {
|
|
3015
|
-
if (this.roomId) {
|
|
3016
|
-
this.chatService.stopTyping(this.roomId);
|
|
3017
|
-
}
|
|
3018
|
-
});
|
|
3019
|
-
}
|
|
3020
|
-
//GO TO LAST MESSAGE EFFECT.
|
|
3021
|
-
#af;
|
|
3022
|
-
ngOnDestroy() {
|
|
3023
|
-
this.typingSubscription?.unsubscribe();
|
|
3024
|
-
}
|
|
3025
|
-
handleTyping(event) {
|
|
3026
|
-
if (this.roomId) {
|
|
3027
|
-
this.chatService.startTyping(this.roomId);
|
|
3028
|
-
this.typing$.next();
|
|
3029
|
-
}
|
|
3030
|
-
}
|
|
3031
|
-
handleFileChange(event) {
|
|
3032
|
-
console.log('File Changed:', event);
|
|
3033
|
-
}
|
|
3034
|
-
handleCancelRecord(event) {
|
|
3035
|
-
console.log('Recording Cancelled:', event);
|
|
3036
|
-
}
|
|
3037
|
-
handleEndRecord(event) {
|
|
3038
|
-
this.fileService.blobToBase64(event.data.value).then((base64Content) => {
|
|
3039
|
-
// Create a properly formatted chat preview message for voice
|
|
3040
|
-
const newVoiceMessage = {
|
|
3041
|
-
id: `${Math.floor(Math.random() * 10000)}`,
|
|
3042
|
-
content: base64Content,
|
|
3043
|
-
sendTime: new Date(),
|
|
3044
|
-
readTime: new Date(),
|
|
3045
|
-
type: 'voice',
|
|
3046
|
-
name: 'test name',
|
|
3047
|
-
};
|
|
3048
|
-
this.chatData.update((values) => [...values, newVoiceMessage]);
|
|
3049
|
-
});
|
|
3050
|
-
}
|
|
3051
|
-
handleOnSend(e) {
|
|
3052
|
-
if (this.isEditing() && this.editId()) {
|
|
3053
|
-
this.chatService
|
|
3054
|
-
.editMessage(this.editId(), e.data.value, e.data.type || 'text')
|
|
3055
|
-
.then((newMessage) => {
|
|
3056
|
-
const convertedNewMessage = convertToChatPreview(this.sessionService.user?.id || '', {
|
|
3057
|
-
items: [newMessage],
|
|
3058
|
-
total: 1,
|
|
3059
|
-
})[0];
|
|
3060
|
-
this.chatData.update((values) => values.map((item) => (item.id === this.editId() ? { ...convertedNewMessage } : item)));
|
|
3061
|
-
this.editId.set(null);
|
|
3062
|
-
this.options.update((prev) => ({ ...prev, value: '' }));
|
|
3063
|
-
this.isEditing.set(false);
|
|
3064
|
-
})
|
|
3065
|
-
.catch((error) => {
|
|
3066
|
-
this.toastService.danger('Failed to edit message');
|
|
3067
|
-
});
|
|
3068
|
-
}
|
|
3069
|
-
else {
|
|
3070
|
-
if (e.data.value && this.roomId) {
|
|
3071
|
-
const replyId = e.data.replyChat?.id;
|
|
3072
|
-
this.chatService
|
|
3073
|
-
.sendMessage(this.roomId, e.data.value, e.data.type || 'text', replyId)
|
|
3074
|
-
.then((newMessage) => {
|
|
3075
|
-
const convertedNewMessage = convertToChatPreview(this.sessionService.user?.id || '', {
|
|
3076
|
-
items: [newMessage],
|
|
3077
|
-
total: 1,
|
|
3078
|
-
})[0];
|
|
3079
|
-
this.chatData.update((values) => [...values, { ...convertedNewMessage, replyTo: replyId }]);
|
|
3080
|
-
this.options.update((prev) => ({ ...prev, value: '' }));
|
|
3081
|
-
this.scrollToEnd();
|
|
3082
|
-
})
|
|
3083
|
-
.catch((error) => {
|
|
3084
|
-
this.toastService.danger('Failed to send message');
|
|
3085
|
-
});
|
|
3086
|
-
}
|
|
3087
|
-
}
|
|
3088
|
-
}
|
|
3089
|
-
handleEnter() {
|
|
3090
|
-
if (this.options().value && this.roomId) {
|
|
3091
|
-
this.handleOnSend({ data: { value: this.options().value } });
|
|
3092
|
-
}
|
|
3093
|
-
}
|
|
3094
|
-
handleOnAction(e) {
|
|
3095
|
-
console.log('Action Triggered:', e);
|
|
3096
|
-
}
|
|
3097
|
-
scrollToEnd() {
|
|
3098
|
-
const conversationView = document.querySelector('ax-conversation-view');
|
|
3099
|
-
if (conversationView) {
|
|
3100
|
-
conversationView.scrollTo({
|
|
3101
|
-
top: conversationView.scrollHeight,
|
|
3102
|
-
behavior: 'smooth',
|
|
3103
|
-
});
|
|
3104
|
-
}
|
|
3105
|
-
}
|
|
3106
|
-
async loadMessages(roomId) {
|
|
3107
|
-
this.isLoading.set(true);
|
|
3108
|
-
this.error.set(null);
|
|
3109
|
-
try {
|
|
3110
|
-
// Get messages from the chat service
|
|
3111
|
-
const messageResponse = await this.chatService.getMessages(roomId);
|
|
3112
|
-
// Convert to chat preview format
|
|
3113
|
-
const chatPreviewMessages = convertToChatPreview(this.sessionService.user?.id || '', messageResponse).sort((a, b) => {
|
|
3114
|
-
return new Date(a.sendTime).getTime() - new Date(b.sendTime).getTime();
|
|
3115
|
-
});
|
|
3116
|
-
// Set the messages in the conversation service
|
|
3117
|
-
this.chatData.set(chatPreviewMessages);
|
|
3118
|
-
}
|
|
3119
|
-
catch (error) {
|
|
3120
|
-
this.error.set('Failed to load messages. Please try again.');
|
|
3121
|
-
console.error('Failed to load messages:', error);
|
|
3122
|
-
}
|
|
3123
|
-
finally {
|
|
3124
|
-
this.isLoading.set(false);
|
|
3125
|
-
}
|
|
3126
|
-
}
|
|
3127
|
-
async loadRoomInfo(roomId) {
|
|
3128
|
-
try {
|
|
3129
|
-
const roomData = await this.chatService.getRoom(roomId);
|
|
3130
|
-
this.room.set(roomData);
|
|
3131
|
-
}
|
|
3132
|
-
catch (error) {
|
|
3133
|
-
console.error('Failed to load room info:', error);
|
|
3134
|
-
}
|
|
3135
|
-
}
|
|
3136
|
-
addItemHandler(e) {
|
|
3137
|
-
this.activeMessage.set(e.data);
|
|
3138
|
-
if (e.data.fromId) {
|
|
3139
|
-
e.canceled = true;
|
|
3140
|
-
return;
|
|
3141
|
-
}
|
|
3142
|
-
const userItem = [];
|
|
3143
|
-
if (e.data.type === 'text') {
|
|
3144
|
-
userItem.push({
|
|
3145
|
-
text: 'Edit',
|
|
3146
|
-
color: 'primary',
|
|
3147
|
-
icon: 'fa-solid fa-pencil',
|
|
3148
|
-
onClick: (id) => {
|
|
3149
|
-
try {
|
|
3150
|
-
this.isEditing.set(true);
|
|
3151
|
-
this.editId.set(e.data.id);
|
|
3152
|
-
this.options.update((prev) => ({ ...prev, value: e.data.content }));
|
|
3153
|
-
this.addInputOverlay('edit', e.data);
|
|
3154
|
-
}
|
|
3155
|
-
catch (error) {
|
|
3156
|
-
this.toastService.danger('Failed to edit message');
|
|
3157
|
-
}
|
|
3158
|
-
},
|
|
3159
|
-
});
|
|
3160
|
-
}
|
|
3161
|
-
if (e.data.type === 'text') {
|
|
3162
|
-
userItem.push({
|
|
3163
|
-
text: 'Delete',
|
|
3164
|
-
color: 'danger',
|
|
3165
|
-
icon: 'fa-solid fa-trash-can',
|
|
3166
|
-
onClick: (id) => {
|
|
3167
|
-
try {
|
|
3168
|
-
this.chatService.deleteMessage(id).then((res) => {
|
|
3169
|
-
this.chatData.update((values) => values.filter((item) => item.id !== id));
|
|
3170
|
-
if (!res) {
|
|
3171
|
-
this.toastService.danger('Failed to delete message');
|
|
3172
|
-
}
|
|
3173
|
-
});
|
|
3174
|
-
}
|
|
3175
|
-
catch (error) {
|
|
3176
|
-
this.toastService.danger('Failed to delete message');
|
|
3177
|
-
}
|
|
3178
|
-
},
|
|
3179
|
-
});
|
|
3180
|
-
}
|
|
3181
|
-
e.items.push(...userItem);
|
|
3182
|
-
}
|
|
3183
|
-
addInputOverlay(type, message) {
|
|
3184
|
-
const input = this.inputRef();
|
|
3185
|
-
const icon = type === 'reply' ? 'fa-solid fa-reply' : 'fa-solid fa-pencil';
|
|
3186
|
-
if (input) {
|
|
3187
|
-
input.setActionBoxContainer(icon, message?.content || this.activeMessage()?.content || '');
|
|
3188
|
-
}
|
|
3189
|
-
}
|
|
3190
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMChatPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3191
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMChatPreviewComponent, isStandalone: true, selector: "axm-chat-preview", viewQueries: [{ propertyName: "inputRef", first: true, predicate: AXConversationInputComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (isLoading()) {\n <div class=\"ax-h-full ax-w-full ax-flex ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n} @else if (error()) {\n <div class=\"ax-h-full ax-w-full ax-flex ax-items-center ax-justify-center\">\n <div class=\"ax-text-center\">\n <p class=\"ax-text-danger\">{{ error() }}</p>\n <button (click)=\"loadMessages(roomId)\" class=\"ax-mt-2 ax-button ax-primary\">Retry</button>\n </div>\n </div>\n} @else {\n <div\n axDomChange\n (axResizeObserver)=\"setHeight($event[0].contentRect.height)\"\n class=\"ax-bg-surface-container ax-h-full\"\n >\n <!-- Messages Container -->\n <ax-conversation-container class=\"ax-overflow-hidden\" [chatData]=\"chatData()\">\n <ax-conversation-view\n (onActionMenuOpening)=\"addItemHandler($event)\"\n (onAction)=\"handleOnAction($event)\"\n (onReplyClick)=\"addInputOverlay('reply', $event.data)\"\n [chatBoxHeight]=\"height() - (isChannel() ? 5 : 68) + 'px'\"\n ></ax-conversation-view>\n @if (!isChannel()) {\n <ax-conversation-input\n class=\"ax-px-2\"\n placeholder=\"Type a message...\"\n [(ngModel)]=\"options().value\"\n (ngModelChange)=\"handleTyping($event)\"\n (onSendClick)=\"handleOnSend($event)\"\n (onFileChange)=\"handleFileChange($event)\"\n (onStopRecording)=\"handleEndRecord($event)\"\n (onCancelRecording)=\"handleCancelRecord($event)\"\n (onEnterPressed)=\"handleEnter()\"\n ></ax-conversation-input>\n }\n </ax-conversation-container>\n </div>\n}\n", styles: [":host{display:block;width:100%;height:100%}\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: "directive", type: AXDomChangeDirective, selector: "[axDomChange]", outputs: ["axMutationObserver", "axResizeObserver"] }, { kind: "ngmodule", type: AXConversationModule }, { kind: "component", type: i2$2.AXConversationViewComponent, selector: "ax-conversation-view", inputs: ["chatBoxHeight", "isReplyArrowShown", "avatar"], outputs: ["onActionMenuOpening", "onAction", "onReplyClick", "onScrollEnd"] }, { kind: "component", type: i2$2.AXConversationInputComponent, selector: "ax-conversation-input", inputs: ["look", "placeholder", "maxLength", "hasAttachment", "hasVoice", "hasEmoji", "isLoading", "acceptFileType"], outputs: ["onActionClose", "onSendClick", "onStartRecording", "onCancelRecording", "onEnterPressed"] }, { kind: "component", type: i2$2.AXConversationContainerComponent, selector: "ax-conversation-container", inputs: ["chatData"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i3$1.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3192
|
-
}
|
|
3193
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMChatPreviewComponent, decorators: [{
|
|
3194
|
-
type: Component,
|
|
3195
|
-
args: [{ selector: 'axm-chat-preview', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, AXDomChangeDirective, AXConversationModule, AXLoadingModule], template: "@if (isLoading()) {\n <div class=\"ax-h-full ax-w-full ax-flex ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n} @else if (error()) {\n <div class=\"ax-h-full ax-w-full ax-flex ax-items-center ax-justify-center\">\n <div class=\"ax-text-center\">\n <p class=\"ax-text-danger\">{{ error() }}</p>\n <button (click)=\"loadMessages(roomId)\" class=\"ax-mt-2 ax-button ax-primary\">Retry</button>\n </div>\n </div>\n} @else {\n <div\n axDomChange\n (axResizeObserver)=\"setHeight($event[0].contentRect.height)\"\n class=\"ax-bg-surface-container ax-h-full\"\n >\n <!-- Messages Container -->\n <ax-conversation-container class=\"ax-overflow-hidden\" [chatData]=\"chatData()\">\n <ax-conversation-view\n (onActionMenuOpening)=\"addItemHandler($event)\"\n (onAction)=\"handleOnAction($event)\"\n (onReplyClick)=\"addInputOverlay('reply', $event.data)\"\n [chatBoxHeight]=\"height() - (isChannel() ? 5 : 68) + 'px'\"\n ></ax-conversation-view>\n @if (!isChannel()) {\n <ax-conversation-input\n class=\"ax-px-2\"\n placeholder=\"Type a message...\"\n [(ngModel)]=\"options().value\"\n (ngModelChange)=\"handleTyping($event)\"\n (onSendClick)=\"handleOnSend($event)\"\n (onFileChange)=\"handleFileChange($event)\"\n (onStopRecording)=\"handleEndRecord($event)\"\n (onCancelRecording)=\"handleCancelRecord($event)\"\n (onEnterPressed)=\"handleEnter()\"\n ></ax-conversation-input>\n }\n </ax-conversation-container>\n </div>\n}\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
|
|
3196
|
-
}], propDecorators: { inputRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXConversationInputComponent), { isSignal: true }] }] } });
|
|
3197
|
-
|
|
3198
|
-
var chatPreview_component = /*#__PURE__*/Object.freeze({
|
|
3199
|
-
__proto__: null,
|
|
3200
|
-
AXMChatPreviewComponent: AXMChatPreviewComponent
|
|
3201
|
-
});
|
|
3202
|
-
|
|
3203
1646
|
class AXMCommentRealtimeService {
|
|
3204
1647
|
}
|
|
3205
1648
|
class AXMCommentRealtimeServiceImpl extends AXMCommentRealtimeService {
|
|
@@ -3951,7 +2394,7 @@ class AXMCommentComponent {
|
|
|
3951
2394
|
}
|
|
3952
2395
|
}
|
|
3953
2396
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMCommentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3954
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMCommentComponent, isStandalone: true, selector: "axm-comment", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "wysiwygEditor", first: true, predicate: ["w"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ax-size-full ax-flex ax-flex-col ax-justify-between ax-p-4 ax-overflow-hidden\">\n <ax-comment-container class=\"ax-overflow-auto\">\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-py-12 ax-bg-lightest ax-px-5\">\n <ax-skeleton class=\"ax-min-w-16 ax-h-16 ax-rounded-full ax-me-4\"></ax-skeleton>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-8/12 ax-h-2 ax-rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (!isLoading() && comments().length > 0) {\n <ax-comment-view class=\"ax-bg-lightest\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar #user [size]=\"48\" [userId]=\"comment.author.id\" ngProjectAs=\"'ax-avatar'\"></axp-user-avatar>\n <ax-title>{{ user.firstName() + ' ' + user.lastName() }}</ax-title>\n <ax-comment-date>{{ comment.auditInfo?.created?.at! | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(comment.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(comment.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(comment)\" [like]=\"isLikedByUser(comment)\">\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n ></ax-comment-reply-text>\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item [id]=\"reply.id\" [class.highlighted]=\"highlightedCommentId() === reply.id\" [@fadeIn]>\n <axp-user-avatar\n #user2\n [size]=\"48\"\n [userId]=\"reply.author.id\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title>{{ user2.firstName() + ' ' + user2.lastName() }}</ax-title>\n <ax-comment-date>{{ reply.auditInfo?.created?.at! | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(reply.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(reply.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(reply)\" [like]=\"isLikedByUser(reply)\">\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n } @else {\n <div>\n <div class=\"ax-flex ax-flex-col ax-gap-4 ax-justify-center ax-items-center ax-p-10\">\n <svg\n class=\"ax-mx-auto\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"154\"\n height=\"161\"\n viewBox=\"0 0 154 161\"\n fill=\"none\"\n >\n <path\n d=\"M0.0616455 84.4268C0.0616455 42.0213 34.435 7.83765 76.6507 7.83765C118.803 7.83765 153.224 42.0055 153.224 84.4268C153.224 102.42 147.026 118.974 136.622 132.034C122.282 150.138 100.367 161 76.6507 161C52.7759 161 30.9882 150.059 16.6633 132.034C6.25961 118.974 0.0616455 102.42 0.0616455 84.4268Z\"\n fill=\"#EEF2FF\"\n />\n <path\n d=\"M96.8189 0.632498L96.8189 0.632384L96.8083 0.630954C96.2034 0.549581 95.5931 0.5 94.9787 0.5H29.338C22.7112 0.5 17.3394 5.84455 17.3394 12.4473V142.715C17.3394 149.318 22.7112 154.662 29.338 154.662H123.948C130.591 154.662 135.946 149.317 135.946 142.715V38.9309C135.946 38.0244 135.847 37.1334 135.648 36.2586L135.648 36.2584C135.117 33.9309 133.874 31.7686 132.066 30.1333C132.066 30.1331 132.065 30.1329 132.065 30.1327L103.068 3.65203C103.068 3.6519 103.067 3.65177 103.067 3.65164C101.311 2.03526 99.1396 0.995552 96.8189 0.632498Z\"\n fill=\"white\"\n stroke=\"#E5E7EB\"\n />\n <ellipse cx=\"80.0618\" cy=\"81\" rx=\"28.0342\" ry=\"28.0342\" fill=\"#EEF2FF\" />\n <path\n d=\"M99.2393 61.3061L99.2391 61.3058C88.498 50.5808 71.1092 50.5804 60.3835 61.3061C49.6423 72.0316 49.6422 89.4361 60.3832 100.162C71.109 110.903 88.4982 110.903 99.2393 100.162C109.965 89.4363 109.965 72.0317 99.2393 61.3061ZM105.863 54.6832C120.249 69.0695 120.249 92.3985 105.863 106.785C91.4605 121.171 68.1468 121.171 53.7446 106.785C39.3582 92.3987 39.3582 69.0693 53.7446 54.683C68.1468 40.2965 91.4605 40.2966 105.863 54.6832Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M110.782 119.267L102.016 110.492C104.888 108.267 107.476 105.651 109.564 102.955L118.329 111.729L110.782 119.267Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M139.122 125.781L139.122 125.78L123.313 109.988C123.313 109.987 123.313 109.987 123.312 109.986C121.996 108.653 119.849 108.657 118.521 109.985L118.871 110.335L118.521 109.985L109.047 119.459C107.731 120.775 107.735 122.918 109.044 124.247L109.047 124.249L124.858 140.06C128.789 143.992 135.191 143.992 139.122 140.06C143.069 136.113 143.069 129.728 139.122 125.781Z\"\n fill=\"#A5B4FC\"\n stroke=\"#818CF8\"\n />\n <path\n d=\"M83.185 87.2285C82.5387 87.2285 82.0027 86.6926 82.0027 86.0305C82.0027 83.3821 77.9987 83.3821 77.9987 86.0305C77.9987 86.6926 77.4627 87.2285 76.8006 87.2285C76.1543 87.2285 75.6183 86.6926 75.6183 86.0305C75.6183 80.2294 84.3831 80.2451 84.3831 86.0305C84.3831 86.6926 83.8471 87.2285 83.185 87.2285Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M93.3528 77.0926H88.403C87.7409 77.0926 87.2049 76.5567 87.2049 75.8946C87.2049 75.2483 87.7409 74.7123 88.403 74.7123H93.3528C94.0149 74.7123 94.5509 75.2483 94.5509 75.8946C94.5509 76.5567 94.0149 77.0926 93.3528 77.0926Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M71.5987 77.0925H66.6488C65.9867 77.0925 65.4507 76.5565 65.4507 75.8945C65.4507 75.2481 65.9867 74.7122 66.6488 74.7122H71.5987C72.245 74.7122 72.781 75.2481 72.781 75.8945C72.781 76.5565 72.245 77.0925 71.5987 77.0925Z\"\n fill=\"#4F46E5\"\n />\n <rect x=\"38.3522\" y=\"21.5128\" width=\"41.0256\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <rect x=\"38.3522\" y=\"133.65\" width=\"54.7009\" height=\"5.47009\" rx=\"2.73504\" fill=\"#A5B4FC\" />\n <rect x=\"38.3522\" y=\"29.7179\" width=\"13.6752\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"56.13\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"61.6001\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"67.0702\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n </svg>\n <div>\n <h2 class=\"ax-text-center ax-text-neutral-600 ax-font-semibold ax-leading-loose ax-pb-2\">\n There is no Comment!\n </h2>\n </div>\n </div>\n </div>\n }\n </ax-comment-container>\n <div>\n @if (isReplyingMode() || isEditingMode()) {\n <div\n class=\"ax-flex ax-justify-between ax-rounded-b-none ax-border ax-border-b-0 ax-rounded-lg ax-px-6 ax-py-3 ax-w-full ax-items-center ax-overflow-hidden ax-text-sm ax-leading-none\"\n >\n <div (click)=\"scrollMain()\" class=\"ax-flex ax-justify-start ax-items-center ax-cursor-pointer\">\n <i\n [class]=\"isReplyingMode() ? 'fa-reply' : 'fa-pen'\"\n class=\"fa-solid ax-text-primary-500 dark:ax-text-primary-300 ax-text-2xl ax-me-4\"\n ></i>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-justify-between ax-align-middle ax-leading-4 ax-overflow-hidden\">\n <p class=\"ax-text-primary-500 dark:ax-text-primary-300\">\n {{ isReplyingMode() ? 'Reply to ' : 'Edit Message' }}\n <span class=\"ax-font-bold\">\n {{ isReplyingMode() ? activeReplyComment()?.userName : '' }}\n </span>\n </p>\n <div\n class=\"ax-truncate\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(activeReplyComment()?.message?.content ?? '')\n : sanitizeHtml(activeEditComment()?.message?.content ?? '')\n \"\n ></div>\n </div>\n </div>\n <div><i (click)=\"resetReplyEditState()\" class=\"fa-solid ax-text-2xl fa-xmark ax-cursor-pointer\"></i></div>\n </div>\n }\n <ax-wysiwyg-container #w [look]=\"wysiwygOptions().look\" [(ngModel)]=\"commentContent\">\n <ax-wysiwyg-view class=\"ax-min-h-28\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar>\n <ax-prefix>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-colors></ax-wysiwyg-colors>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n <ax-wysiwyg-alignment></ax-wysiwyg-alignment>\n </ax-prefix>\n <ax-suffix>\n <ax-dropdown-button\n [disabled]=\"hasCooldown() || !this.commentContent()\"\n type=\"submit\"\n color=\"primary\"\n mode=\"split\"\n text=\"Send\"\n (onClick)=\"submitComment()\"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n <!-- <ax-button-item-list>\n <ax-button-item (click)=\"submitComment()\" text=\"Send Private ...\" name=\"private\" data=\"private\">\n <ax-prefix>\n <ax-icon icon=\"fa-regular fa-user-secret\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list> -->\n </ax-dropdown-button>\n </ax-suffix>\n </ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n </div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}ax-wysiwyg-container .ax-editor-container{border-top-left-radius:0!important;border-top-right-radius:0!important}ax-wysiwyg-container .ax-error-message{padding-left:.5rem}ax-wysiwyg-container .highlighted{background:var(--ax-color-primary-050)!important;border-radius:.25rem;transition:background 1s ease-in-out}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$2.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$2.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i1$2.AXWysiwygAlignmentComponent, selector: "ax-wysiwyg-alignment" }, { kind: "component", type: i1$2.AXWysiwygColorsComponent, selector: "ax-wysiwyg-colors" }, { kind: "component", type: i1$2.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style" }, { kind: "component", type: i1$2.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history" }, { kind: "component", type: i1$2.AXWysiwygListComponent, selector: "ax-wysiwyg-list" }, { kind: "component", type: i1$2.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXConversationModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i9.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i5.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i5.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: "ngmodule", type: AXCommentModule }, { kind: "component", type: i4$2.AXCommentViewComponent, selector: "ax-comment-view" }, { kind: "component", type: i4$2.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4$2.AXCommentItemComponent, selector: "ax-comment-item", inputs: ["replyCount"] }, { kind: "component", type: i4$2.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["like"], outputs: ["likeChange"] }, { kind: "component", type: i4$2.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4$2.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4$2.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5$1.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: i5$1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i5$1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i3$1.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i7$1.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXToolBarModule }, { 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: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: i9$1.AXDropdownButtonComponent, selector: "ax-dropdown-button", inputs: ["disabled", "size", "color", "look", "text", "type", "mode"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "lookChange", "colorChange", "disabledChange"] }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId"] }, { kind: "pipe", type: i10.AXFormatPipe, name: "format" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
|
|
2397
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMCommentComponent, isStandalone: true, selector: "axm-comment", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "wysiwygEditor", first: true, predicate: ["w"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ax-size-full ax-flex ax-flex-col ax-justify-between ax-p-4 ax-overflow-hidden\">\n <ax-comment-container class=\"ax-overflow-auto\">\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-py-12 ax-bg-lightest ax-px-5\">\n <ax-skeleton class=\"ax-min-w-16 ax-h-16 ax-rounded-full ax-me-4\"></ax-skeleton>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-8/12 ax-h-2 ax-rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (!isLoading() && comments().length > 0) {\n <ax-comment-view class=\"ax-bg-lightest\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar #user [size]=\"48\" [userId]=\"comment.author.id\" ngProjectAs=\"'ax-avatar'\"></axp-user-avatar>\n <ax-title>{{ user.firstName() + ' ' + user.lastName() }}</ax-title>\n <ax-comment-date>{{ comment.auditInfo?.created?.at! | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(comment.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(comment.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(comment)\" [like]=\"isLikedByUser(comment)\">\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n ></ax-comment-reply-text>\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item [id]=\"reply.id\" [class.highlighted]=\"highlightedCommentId() === reply.id\" [@fadeIn]>\n <axp-user-avatar\n #user2\n [size]=\"48\"\n [userId]=\"reply.author.id\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title>{{ user2.firstName() + ' ' + user2.lastName() }}</ax-title>\n <ax-comment-date>{{ reply.auditInfo?.created?.at! | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(reply.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(reply.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(reply)\" [like]=\"isLikedByUser(reply)\">\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n } @else {\n <div>\n <div class=\"ax-flex ax-flex-col ax-gap-4 ax-justify-center ax-items-center ax-p-10\">\n <svg\n class=\"ax-mx-auto\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"154\"\n height=\"161\"\n viewBox=\"0 0 154 161\"\n fill=\"none\"\n >\n <path\n d=\"M0.0616455 84.4268C0.0616455 42.0213 34.435 7.83765 76.6507 7.83765C118.803 7.83765 153.224 42.0055 153.224 84.4268C153.224 102.42 147.026 118.974 136.622 132.034C122.282 150.138 100.367 161 76.6507 161C52.7759 161 30.9882 150.059 16.6633 132.034C6.25961 118.974 0.0616455 102.42 0.0616455 84.4268Z\"\n fill=\"#EEF2FF\"\n />\n <path\n d=\"M96.8189 0.632498L96.8189 0.632384L96.8083 0.630954C96.2034 0.549581 95.5931 0.5 94.9787 0.5H29.338C22.7112 0.5 17.3394 5.84455 17.3394 12.4473V142.715C17.3394 149.318 22.7112 154.662 29.338 154.662H123.948C130.591 154.662 135.946 149.317 135.946 142.715V38.9309C135.946 38.0244 135.847 37.1334 135.648 36.2586L135.648 36.2584C135.117 33.9309 133.874 31.7686 132.066 30.1333C132.066 30.1331 132.065 30.1329 132.065 30.1327L103.068 3.65203C103.068 3.6519 103.067 3.65177 103.067 3.65164C101.311 2.03526 99.1396 0.995552 96.8189 0.632498Z\"\n fill=\"white\"\n stroke=\"#E5E7EB\"\n />\n <ellipse cx=\"80.0618\" cy=\"81\" rx=\"28.0342\" ry=\"28.0342\" fill=\"#EEF2FF\" />\n <path\n d=\"M99.2393 61.3061L99.2391 61.3058C88.498 50.5808 71.1092 50.5804 60.3835 61.3061C49.6423 72.0316 49.6422 89.4361 60.3832 100.162C71.109 110.903 88.4982 110.903 99.2393 100.162C109.965 89.4363 109.965 72.0317 99.2393 61.3061ZM105.863 54.6832C120.249 69.0695 120.249 92.3985 105.863 106.785C91.4605 121.171 68.1468 121.171 53.7446 106.785C39.3582 92.3987 39.3582 69.0693 53.7446 54.683C68.1468 40.2965 91.4605 40.2966 105.863 54.6832Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M110.782 119.267L102.016 110.492C104.888 108.267 107.476 105.651 109.564 102.955L118.329 111.729L110.782 119.267Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M139.122 125.781L139.122 125.78L123.313 109.988C123.313 109.987 123.313 109.987 123.312 109.986C121.996 108.653 119.849 108.657 118.521 109.985L118.871 110.335L118.521 109.985L109.047 119.459C107.731 120.775 107.735 122.918 109.044 124.247L109.047 124.249L124.858 140.06C128.789 143.992 135.191 143.992 139.122 140.06C143.069 136.113 143.069 129.728 139.122 125.781Z\"\n fill=\"#A5B4FC\"\n stroke=\"#818CF8\"\n />\n <path\n d=\"M83.185 87.2285C82.5387 87.2285 82.0027 86.6926 82.0027 86.0305C82.0027 83.3821 77.9987 83.3821 77.9987 86.0305C77.9987 86.6926 77.4627 87.2285 76.8006 87.2285C76.1543 87.2285 75.6183 86.6926 75.6183 86.0305C75.6183 80.2294 84.3831 80.2451 84.3831 86.0305C84.3831 86.6926 83.8471 87.2285 83.185 87.2285Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M93.3528 77.0926H88.403C87.7409 77.0926 87.2049 76.5567 87.2049 75.8946C87.2049 75.2483 87.7409 74.7123 88.403 74.7123H93.3528C94.0149 74.7123 94.5509 75.2483 94.5509 75.8946C94.5509 76.5567 94.0149 77.0926 93.3528 77.0926Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M71.5987 77.0925H66.6488C65.9867 77.0925 65.4507 76.5565 65.4507 75.8945C65.4507 75.2481 65.9867 74.7122 66.6488 74.7122H71.5987C72.245 74.7122 72.781 75.2481 72.781 75.8945C72.781 76.5565 72.245 77.0925 71.5987 77.0925Z\"\n fill=\"#4F46E5\"\n />\n <rect x=\"38.3522\" y=\"21.5128\" width=\"41.0256\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <rect x=\"38.3522\" y=\"133.65\" width=\"54.7009\" height=\"5.47009\" rx=\"2.73504\" fill=\"#A5B4FC\" />\n <rect x=\"38.3522\" y=\"29.7179\" width=\"13.6752\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"56.13\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"61.6001\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"67.0702\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n </svg>\n <div>\n <h2 class=\"ax-text-center ax-text-neutral-600 ax-font-semibold ax-leading-loose ax-pb-2\">\n There is no Comment!\n </h2>\n </div>\n </div>\n </div>\n }\n </ax-comment-container>\n <div>\n @if (isReplyingMode() || isEditingMode()) {\n <div\n class=\"ax-flex ax-justify-between ax-rounded-b-none ax-border ax-border-b-0 ax-rounded-lg ax-px-6 ax-py-3 ax-w-full ax-items-center ax-overflow-hidden ax-text-sm ax-leading-none\"\n >\n <div (click)=\"scrollMain()\" class=\"ax-flex ax-justify-start ax-items-center ax-cursor-pointer\">\n <i\n [class]=\"isReplyingMode() ? 'fa-reply' : 'fa-pen'\"\n class=\"fa-solid ax-text-primary-500 dark:ax-text-primary-300 ax-text-2xl ax-me-4\"\n ></i>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-justify-between ax-align-middle ax-leading-4 ax-overflow-hidden\">\n <p class=\"ax-text-primary-500 dark:ax-text-primary-300\">\n {{ isReplyingMode() ? 'Reply to ' : 'Edit Message' }}\n <span class=\"ax-font-bold\">\n {{ isReplyingMode() ? activeReplyComment()?.userName : '' }}\n </span>\n </p>\n <div\n class=\"ax-truncate\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(activeReplyComment()?.message?.content ?? '')\n : sanitizeHtml(activeEditComment()?.message?.content ?? '')\n \"\n ></div>\n </div>\n </div>\n <div><i (click)=\"resetReplyEditState()\" class=\"fa-solid ax-text-2xl fa-xmark ax-cursor-pointer\"></i></div>\n </div>\n }\n <ax-wysiwyg-container #w [look]=\"wysiwygOptions().look\" [(ngModel)]=\"commentContent\">\n <ax-wysiwyg-view class=\"ax-min-h-28\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar>\n <ax-prefix>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-colors></ax-wysiwyg-colors>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n <ax-wysiwyg-alignment></ax-wysiwyg-alignment>\n </ax-prefix>\n <ax-suffix>\n <ax-dropdown-button\n [disabled]=\"hasCooldown() || !this.commentContent()\"\n type=\"submit\"\n color=\"primary\"\n mode=\"split\"\n text=\"Send\"\n (onClick)=\"submitComment()\"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n <!-- <ax-button-item-list>\n <ax-button-item (click)=\"submitComment()\" text=\"Send Private ...\" name=\"private\" data=\"private\">\n <ax-prefix>\n <ax-icon icon=\"fa-regular fa-user-secret\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list> -->\n </ax-dropdown-button>\n </ax-suffix>\n </ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n </div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}ax-wysiwyg-container .ax-editor-container{border-top-left-radius:0!important;border-top-right-radius:0!important}ax-wysiwyg-container .ax-error-message{padding-left:.5rem}ax-wysiwyg-container .highlighted{background:var(--ax-color-primary-050)!important;border-radius:.25rem;transition:background 1s ease-in-out}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$1.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$1.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i1$1.AXWysiwygAlignmentComponent, selector: "ax-wysiwyg-alignment" }, { kind: "component", type: i1$1.AXWysiwygColorsComponent, selector: "ax-wysiwyg-colors" }, { kind: "component", type: i1$1.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style" }, { kind: "component", type: i1$1.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history" }, { kind: "component", type: i1$1.AXWysiwygListComponent, selector: "ax-wysiwyg-list" }, { kind: "component", type: i1$1.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXConversationModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { 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: "ngmodule", type: AXCommentModule }, { kind: "component", type: i4.AXCommentViewComponent, selector: "ax-comment-view" }, { kind: "component", type: i4.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4.AXCommentItemComponent, selector: "ax-comment-item", inputs: ["replyCount"] }, { kind: "component", type: i4.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["like"], outputs: ["likeChange"] }, { kind: "component", type: i4.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5.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: i5.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i5.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i7.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i8.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: i9.AXDropdownButtonComponent, selector: "ax-dropdown-button", inputs: ["disabled", "size", "color", "look", "text", "type", "mode"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "lookChange", "colorChange", "disabledChange"] }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId"] }, { kind: "pipe", type: i10.AXFormatPipe, name: "format" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
|
|
3955
2398
|
trigger('fadeIn', [
|
|
3956
2399
|
transition(':enter', [
|
|
3957
2400
|
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
@@ -4007,9 +2450,9 @@ class AXMCommentPopupComponent extends AXBasePageComponent {
|
|
|
4007
2450
|
// Angular
|
|
4008
2451
|
CommonModule }, { kind: "ngmodule", type:
|
|
4009
2452
|
// ACoreX
|
|
4010
|
-
AXDecoratorModule }, { kind: "component", type:
|
|
2453
|
+
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: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5.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: AXTranslationModule }, { kind: "component", type:
|
|
4011
2454
|
// Comment
|
|
4012
|
-
AXMCommentComponent, selector: "axm-comment", inputs: ["refrenceType", "refrenceId", "subject"] }, { kind: "pipe", type:
|
|
2455
|
+
AXMCommentComponent, selector: "axm-comment", inputs: ["refrenceType", "refrenceId", "subject"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4$1.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
4013
2456
|
}
|
|
4014
2457
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMCommentPopupComponent, decorators: [{
|
|
4015
2458
|
type: Component,
|
|
@@ -4369,7 +2812,7 @@ function routesFactory() {
|
|
|
4369
2812
|
children: [
|
|
4370
2813
|
{
|
|
4371
2814
|
path: ':id',
|
|
4372
|
-
loadComponent: () => Promise.resolve().then(function () { return
|
|
2815
|
+
loadComponent: () => Promise.resolve().then(function () { return chat_component; }).then((c) => c.AXMChatComponent),
|
|
4373
2816
|
},
|
|
4374
2817
|
],
|
|
4375
2818
|
},
|
|
@@ -4415,7 +2858,7 @@ function routesFactory() {
|
|
|
4415
2858
|
}
|
|
4416
2859
|
class AXMConversationModule {
|
|
4417
2860
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMConversationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
4418
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: AXMConversationModule, imports: [i1$
|
|
2861
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: AXMConversationModule, imports: [i1$2.AXPWidgetCoreModule, i2$1.AXPWorkflowModule,
|
|
4419
2862
|
// Entity Modules
|
|
4420
2863
|
AXMConversationTabEntityModule,
|
|
4421
2864
|
AXMRoomEntityModule,
|
|
@@ -4599,5 +3042,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
4599
3042
|
* Generated bundle index. Do not edit.
|
|
4600
3043
|
*/
|
|
4601
3044
|
|
|
4602
|
-
export { AXMChatComponent,
|
|
3045
|
+
export { AXMChatComponent, AXMChatManagementService, AXMChatRealtimeService, AXMChatRealtimeServiceImpl, AXMChatService, AXMChatServiceImpl, AXMCommentComponent, AXMCommentManagementService, AXMCommentPopupComponent, AXMCommentPopupStartAction, AXMCommentPopupWorkflow, AXMCommentRealtimeService, AXMCommentRealtimeServiceImpl, AXMCommentService, AXMCommentServiceImpl, AXMCommentWidgetViewComponent, AXMConversationModule, AXMConversationTabEntityModule, AXMConversationTabService, AXMConversationTabServiceImpl, AXMMessageEntityModule, AXMMessageService, AXMMessageServiceImpl, AXMRoomEntityModule, AXMRoomService, AXMRoomServiceImpl, AXPCommentWidget, RootConfig, messageFactory, roomFactory, tabFactory };
|
|
4603
3046
|
//# sourceMappingURL=acorex-modules-conversation.mjs.map
|