valtech-components 4.0.218 → 4.0.220

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.
Files changed (56) hide show
  1. package/esm2022/lib/components/molecules/chat-input/chat-input.component.mjs +157 -0
  2. package/esm2022/lib/components/molecules/chat-input/types.mjs +2 -0
  3. package/esm2022/lib/components/molecules/message-bubble/message-bubble.component.mjs +244 -0
  4. package/esm2022/lib/components/molecules/message-bubble/types.mjs +2 -0
  5. package/esm2022/lib/components/molecules/typing-indicator/typing-indicator.component.mjs +76 -0
  6. package/esm2022/lib/components/organisms/account-view/account-view.component.mjs +2 -2
  7. package/esm2022/lib/components/organisms/chat-window/chat-window.component.mjs +246 -0
  8. package/esm2022/lib/components/organisms/chat-window/types.mjs +2 -0
  9. package/esm2022/lib/components/organisms/thread-panel/thread-panel.component.mjs +211 -0
  10. package/esm2022/lib/services/chat/config.mjs +35 -0
  11. package/esm2022/lib/services/chat/conversation.service.mjs +274 -0
  12. package/esm2022/lib/services/chat/types.mjs +10 -0
  13. package/esm2022/lib/services/entity-feed/entity-feed.service.mjs +103 -0
  14. package/esm2022/lib/services/entity-feed/index.mjs +2 -0
  15. package/esm2022/lib/services/entity-feed/types.mjs +2 -0
  16. package/esm2022/lib/services/i18n/default-content.mjs +65 -1
  17. package/esm2022/public-api.mjs +16 -1
  18. package/fesm2022/valtech-components.mjs +1370 -3
  19. package/fesm2022/valtech-components.mjs.map +1 -1
  20. package/lib/components/atoms/glow/glow.component.d.ts +1 -1
  21. package/lib/components/atoms/rights-footer/rights-footer.component.d.ts +2 -2
  22. package/lib/components/atoms/text/text.component.d.ts +1 -1
  23. package/lib/components/atoms/user-avatar/user-avatar.component.d.ts +2 -2
  24. package/lib/components/molecules/article-card/article-card.component.d.ts +1 -1
  25. package/lib/components/molecules/chat-input/chat-input.component.d.ts +38 -0
  26. package/lib/components/molecules/chat-input/types.d.ts +20 -0
  27. package/lib/components/molecules/content-reaction/content-reaction.component.d.ts +2 -2
  28. package/lib/components/molecules/cta-card/cta-card.component.d.ts +1 -1
  29. package/lib/components/molecules/features-list/features-list.component.d.ts +4 -4
  30. package/lib/components/molecules/load-more/load-more.component.d.ts +1 -1
  31. package/lib/components/molecules/media-object/media-object.component.d.ts +1 -1
  32. package/lib/components/molecules/message-bubble/message-bubble.component.d.ts +40 -0
  33. package/lib/components/molecules/message-bubble/types.d.ts +64 -0
  34. package/lib/components/molecules/metric-card/metric-card.component.d.ts +1 -1
  35. package/lib/components/molecules/typing-indicator/typing-indicator.component.d.ts +19 -0
  36. package/lib/components/organisms/account-view/account-view.component.d.ts +1 -1
  37. package/lib/components/organisms/article/article.component.d.ts +6 -6
  38. package/lib/components/organisms/auth-cta/auth-cta.component.d.ts +1 -1
  39. package/lib/components/organisms/bottom-nav/bottom-nav.component.d.ts +1 -1
  40. package/lib/components/organisms/chat-window/chat-window.component.d.ts +63 -0
  41. package/lib/components/organisms/chat-window/types.d.ts +36 -0
  42. package/lib/components/organisms/landing-steps/landing-steps.component.d.ts +1 -1
  43. package/lib/components/organisms/login/login.component.d.ts +1 -1
  44. package/lib/components/organisms/member-import-modal/member-import-modal.component.d.ts +1 -1
  45. package/lib/components/organisms/notification-preferences-view/notification-preferences-view.component.d.ts +1 -1
  46. package/lib/components/organisms/organization-view/organization-view.component.d.ts +1 -1
  47. package/lib/components/organisms/thread-panel/thread-panel.component.d.ts +55 -0
  48. package/lib/components/templates/page-wrapper/page-wrapper.component.d.ts +2 -2
  49. package/lib/services/chat/config.d.ts +37 -0
  50. package/lib/services/chat/conversation.service.d.ts +147 -0
  51. package/lib/services/chat/types.d.ts +145 -0
  52. package/lib/services/entity-feed/entity-feed.service.d.ts +71 -0
  53. package/lib/services/entity-feed/index.d.ts +2 -0
  54. package/lib/services/entity-feed/types.d.ts +26 -0
  55. package/package.json +1 -1
  56. package/public-api.d.ts +13 -0
@@ -0,0 +1,211 @@
1
+ import { Component, Input, inject, signal, computed } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { IonSpinner } from '@ionic/angular/standalone';
4
+ import { firstValueFrom } from 'rxjs';
5
+ import { I18nService } from '../../../services/i18n';
6
+ import { ConversationService } from '../../../services/chat/conversation.service';
7
+ import { VALTECH_CHAT_CONFIG } from '../../../services/chat/config';
8
+ import { AuthService } from '../../../services/auth/auth.service';
9
+ import { ChatWindowComponent } from '../chat-window/chat-window.component';
10
+ import * as i0 from "@angular/core";
11
+ const THREAD_PANEL_I18N = {
12
+ es: {
13
+ loading: 'Cargando conversacion...',
14
+ thread: 'Hilo',
15
+ },
16
+ en: {
17
+ loading: 'Loading conversation...',
18
+ thread: 'Thread',
19
+ },
20
+ };
21
+ /**
22
+ * val-thread-panel
23
+ *
24
+ * Panel de hilo de conversacion asociado a una entidad (post, request, etc.).
25
+ * Internamente usa ConversationService.getOrCreateForEntity() para inicializar
26
+ * la conversacion y luego watchMessages() para escuchar en tiempo real.
27
+ * Renderiza val-chat-window con los mensajes ya mapeados.
28
+ *
29
+ * Requiere provideValtechChat() y provideValtechFirebase() en main.ts.
30
+ *
31
+ * @example
32
+ * <val-thread-panel
33
+ * entityType="post"
34
+ * entityId="post-abc123"
35
+ * currentUserId="user-xyz"
36
+ * title="Comentarios"
37
+ * />
38
+ */
39
+ export class ThreadPanelComponent {
40
+ constructor() {
41
+ this.i18n = inject(I18nService);
42
+ this.conversationSvc = inject(ConversationService, { optional: true });
43
+ this.chatConfig = inject(VALTECH_CHAT_CONFIG, { optional: true });
44
+ this.auth = inject(AuthService, { optional: true });
45
+ this.entityType = '';
46
+ this.entityId = '';
47
+ this.currentUserId = '';
48
+ this.loading = signal(true);
49
+ this.conv = signal(null);
50
+ this.messages = signal([]);
51
+ this.typingUsers = signal([]);
52
+ this.isConvOpen = computed(() => this.conv()?.status === 'open');
53
+ this.loadingText = computed(() => {
54
+ this.i18n.lang();
55
+ return this.i18n.t('loading', 'ThreadPanel');
56
+ });
57
+ this.bubbleMessages = computed(() => {
58
+ const uid = this.currentUserId || this.auth?.user()?.userId || '';
59
+ return this.messages().map(msg => ({
60
+ msgId: msg.id,
61
+ senderId: msg.senderId,
62
+ senderName: msg.senderName,
63
+ senderAvatar: msg.senderAvatar,
64
+ body: msg.body,
65
+ type: msg.type,
66
+ createdAt: msg.createdAt,
67
+ isMine: msg.senderId === uid,
68
+ isDeleted: msg.isDeleted,
69
+ isEdited: msg.isEdited,
70
+ replyTo: msg.replyTo,
71
+ attachments: msg.attachments,
72
+ reactions: msg.reactions,
73
+ status: msg.status,
74
+ }));
75
+ });
76
+ this.i18n.registerDefaults('ThreadPanel', THREAD_PANEL_I18N);
77
+ }
78
+ async ngOnInit() {
79
+ if (!this.conversationSvc || !this.entityType || !this.entityId) {
80
+ this.loading.set(false);
81
+ return;
82
+ }
83
+ try {
84
+ const conversation = await firstValueFrom(this.conversationSvc.getOrCreateForEntity(this.entityType, this.entityId));
85
+ this.conv.set(conversation);
86
+ const orgId = this.getOrgId();
87
+ const appId = this.chatConfig?.appId ?? '';
88
+ if (orgId && appId) {
89
+ this.msgSub = this.conversationSvc
90
+ .watchMessages(conversation.id, orgId, appId)
91
+ .subscribe(msgs => this.messages.set(msgs));
92
+ this.typingSub = this.conversationSvc
93
+ .watchTyping(conversation.id, orgId, appId)
94
+ .subscribe(users => this.typingUsers.set(users));
95
+ }
96
+ }
97
+ catch (err) {
98
+ console.error('[ThreadPanel] Error al inicializar conversacion:', err);
99
+ }
100
+ finally {
101
+ this.loading.set(false);
102
+ }
103
+ }
104
+ ngOnDestroy() {
105
+ this.msgSub?.unsubscribe();
106
+ this.typingSub?.unsubscribe();
107
+ const conv = this.conv();
108
+ const orgId = this.getOrgId();
109
+ const appId = this.chatConfig?.appId ?? '';
110
+ if (conv && orgId && appId && this.conversationSvc) {
111
+ this.conversationSvc.stopTyping(conv.id, orgId, appId);
112
+ }
113
+ }
114
+ onSend(body) {
115
+ const conv = this.conv();
116
+ if (!conv || !this.conversationSvc)
117
+ return;
118
+ this.conversationSvc.sendMessage(conv.id, body).subscribe();
119
+ }
120
+ onReactionClick(event) {
121
+ // Reacciones se implementan a nivel de app consumer
122
+ console.debug('[ThreadPanel] reactionClick', event);
123
+ }
124
+ onDeleteMessage(msgId) {
125
+ const conv = this.conv();
126
+ if (!conv || !this.conversationSvc)
127
+ return;
128
+ this.conversationSvc.deleteMessage(conv.id, msgId).subscribe();
129
+ }
130
+ onReplyTo(_msgId) {
131
+ // Implementacion futura: seleccionar mensaje de respuesta
132
+ }
133
+ getOrgId() {
134
+ return this.auth?.user()?.activeOrg ?? '';
135
+ }
136
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThreadPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
137
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ThreadPanelComponent, isStandalone: true, selector: "val-thread-panel", inputs: { entityType: "entityType", entityId: "entityId", currentUserId: "currentUserId", title: "title" }, ngImport: i0, template: `
138
+ <div class="thread-panel">
139
+ @if (title) {
140
+ <div class="thread-header">
141
+ <p class="thread-title">{{ title }}</p>
142
+ </div>
143
+ }
144
+
145
+ @if (loading()) {
146
+ <div class="thread-loading">
147
+ <ion-spinner name="dots"></ion-spinner>
148
+ <span>{{ loadingText() }}</span>
149
+ </div>
150
+ } @else {
151
+ <div class="thread-chat">
152
+ <val-chat-window
153
+ [convId]="conv()?.id ?? ''"
154
+ [messages]="bubbleMessages()"
155
+ [currentUserId]="currentUserId"
156
+ [isOpen]="isConvOpen()"
157
+ [typingUsers]="typingUsers()"
158
+ [isLoading]="false"
159
+ (sendMessage)="onSend($event)"
160
+ (reactionClick)="onReactionClick($event)"
161
+ (deleteMessage)="onDeleteMessage($event)"
162
+ (replyTo)="onReplyTo($event)"
163
+ />
164
+ </div>
165
+ }
166
+ </div>
167
+ `, isInline: true, styles: [".thread-panel{display:flex;flex-direction:column;height:100%;background:var(--ion-background-color, #f4f5f8)}.thread-header{padding:12px 16px;border-bottom:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-card-background, var(--ion-background-color, #fff))}.thread-header .thread-title{font-size:1rem;font-weight:600;color:var(--ion-text-color, #000);margin:0}.thread-loading{display:flex;align-items:center;justify-content:center;flex:1;gap:10px;color:var(--ion-color-medium, #92949c);font-size:.875rem}.thread-chat{flex:1;overflow:hidden;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: ChatWindowComponent, selector: "val-chat-window", inputs: ["convId", "messages", "participants", "currentUserId", "isOpen", "typingUsers", "isLoading"], outputs: ["sendMessage", "loadMore", "reactionClick", "deleteMessage", "replyTo"] }] }); }
168
+ }
169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThreadPanelComponent, decorators: [{
170
+ type: Component,
171
+ args: [{ selector: 'val-thread-panel', standalone: true, imports: [CommonModule, IonSpinner, ChatWindowComponent], template: `
172
+ <div class="thread-panel">
173
+ @if (title) {
174
+ <div class="thread-header">
175
+ <p class="thread-title">{{ title }}</p>
176
+ </div>
177
+ }
178
+
179
+ @if (loading()) {
180
+ <div class="thread-loading">
181
+ <ion-spinner name="dots"></ion-spinner>
182
+ <span>{{ loadingText() }}</span>
183
+ </div>
184
+ } @else {
185
+ <div class="thread-chat">
186
+ <val-chat-window
187
+ [convId]="conv()?.id ?? ''"
188
+ [messages]="bubbleMessages()"
189
+ [currentUserId]="currentUserId"
190
+ [isOpen]="isConvOpen()"
191
+ [typingUsers]="typingUsers()"
192
+ [isLoading]="false"
193
+ (sendMessage)="onSend($event)"
194
+ (reactionClick)="onReactionClick($event)"
195
+ (deleteMessage)="onDeleteMessage($event)"
196
+ (replyTo)="onReplyTo($event)"
197
+ />
198
+ </div>
199
+ }
200
+ </div>
201
+ `, styles: [".thread-panel{display:flex;flex-direction:column;height:100%;background:var(--ion-background-color, #f4f5f8)}.thread-header{padding:12px 16px;border-bottom:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-card-background, var(--ion-background-color, #fff))}.thread-header .thread-title{font-size:1rem;font-weight:600;color:var(--ion-text-color, #000);margin:0}.thread-loading{display:flex;align-items:center;justify-content:center;flex:1;gap:10px;color:var(--ion-color-medium, #92949c);font-size:.875rem}.thread-chat{flex:1;overflow:hidden;display:flex;flex-direction:column}\n"] }]
202
+ }], ctorParameters: () => [], propDecorators: { entityType: [{
203
+ type: Input
204
+ }], entityId: [{
205
+ type: Input
206
+ }], currentUserId: [{
207
+ type: Input
208
+ }], title: [{
209
+ type: Input
210
+ }] } });
211
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhyZWFkLXBhbmVsLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9vcmdhbmlzbXMvdGhyZWFkLXBhbmVsL3RocmVhZC1wYW5lbC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQXFCLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdkQsT0FBTyxFQUFnQixjQUFjLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUdsRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQzs7QUFFM0UsTUFBTSxpQkFBaUIsR0FBRztJQUN4QixFQUFFLEVBQUU7UUFDRixPQUFPLEVBQUUsMEJBQTBCO1FBQ25DLE1BQU0sRUFBRSxNQUFNO0tBQ2Y7SUFDRCxFQUFFLEVBQUU7UUFDRixPQUFPLEVBQUUseUJBQXlCO1FBQ2xDLE1BQU0sRUFBRSxRQUFRO0tBQ2pCO0NBQ0YsQ0FBQztBQUVGOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQXNDSCxNQUFNLE9BQU8sb0JBQW9CO0lBbUIvQjtRQWxCVSxTQUFJLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzdCLG9CQUFlLEdBQUcsTUFB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LElBQUksRUFBRSxDQUFDO0lBQzVDLENBQUM7K0dBcEhVLG9CQUFvQjttR0FBcEIsb0JBQW9CLHdMQWpDckI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThCVCxtcUJBL0JTLFlBQVksK0JBQUUsVUFBVSx5R0FBRSxtQkFBbUI7OzRGQWtDNUMsb0JBQW9CO2tCQXJDaEMsU0FBUzsrQkFDRSxrQkFBa0IsY0FDaEIsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLFVBQVUsRUFBRSxtQkFBbUIsQ0FBQyxZQUM5Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEJUO3dEQVNRLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uSW5pdCwgT25EZXN0cm95LCBpbmplY3QsIHNpZ25hbCwgY29tcHV0ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBJb25TcGlubmVyIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXIvc3RhbmRhbG9uZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIGZpcnN0VmFsdWVGcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBJMThuU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2kxOG4nO1xuaW1wb3J0IHsgQ29udmVyc2F0aW9uU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2NoYXQvY29udmVyc2F0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgVkFMVEVDSF9DSEFUX0NPTkZJRyB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2NoYXQvY29uZmlnJztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvYXV0aC9hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ29udmVyc2F0aW9uLCBNZXNzYWdlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvY2hhdC90eXBlcyc7XG5pbXBvcnQgeyBNZXNzYWdlQnViYmxlTWV0YWRhdGEgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvbWVzc2FnZS1idWJibGUvdHlwZXMnO1xuaW1wb3J0IHsgQ2hhdFdpbmRvd0NvbXBvbmVudCB9IGZyb20gJy4uL2NoYXQtd2luZG93L2NoYXQtd2luZG93LmNvbXBvbmVudCc7XG5cbmNvbnN0IFRIUkVBRF9QQU5FTF9JMThOID0ge1xuICBlczoge1xuICAgIGxvYWRpbmc6ICdDYXJnYW5kbyBjb252ZXJzYWNpb24uLi4nLFxuICAgIHRocmVhZDogJ0hpbG8nLFxuICB9LFxuICBlbjoge1xuICAgIGxvYWRpbmc6ICdMb2FkaW5nIGNvbnZlcnNhdGlvbi4uLicsXG4gICAgdGhyZWFkOiAnVGhyZWFkJyxcbiAgfSxcbn07XG5cbi8qKlxuICogdmFsLXRocmVhZC1wYW5lbFxuICpcbiAqIFBhbmVsIGRlIGhpbG8gZGUgY29udmVyc2FjaW9uIGFzb2NpYWRvIGEgdW5hIGVudGlkYWQgKHBvc3QsIHJlcXVlc3QsIGV0Yy4pLlxuICogSW50ZXJuYW1lbnRlIHVzYSBDb252ZXJzYXRpb25TZXJ2aWNlLmdldE9yQ3JlYXRlRm9yRW50aXR5KCkgcGFyYSBpbmljaWFsaXphclxuICogbGEgY29udmVyc2FjaW9uIHkgbHVlZ28gd2F0Y2hNZXNzYWdlcygpIHBhcmEgZXNjdWNoYXIgZW4gdGllbXBvIHJlYWwuXG4gKiBSZW5kZXJpemEgdmFsLWNoYXQtd2luZG93IGNvbiBsb3MgbWVuc2FqZXMgeWEgbWFwZWFkb3MuXG4gKlxuICogUmVxdWllcmUgcHJvdmlkZVZhbHRlY2hDaGF0KCkgeSBwcm92aWRlVmFsdGVjaEZpcmViYXNlKCkgZW4gbWFpbi50cy5cbiAqXG4gKiBAZXhhbXBsZVxuICogPHZhbC10aHJlYWQtcGFuZWxcbiAqICAgZW50aXR5VHlwZT1cInBvc3RcIlxuICogICBlbnRpdHlJZD1cInBvc3QtYWJjMTIzXCJcbiAqICAgY3VycmVudFVzZXJJZD1cInVzZXIteHl6XCJcbiAqICAgdGl0bGU9XCJDb21lbnRhcmlvc1wiXG4gKiAvPlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtdGhyZWFkLXBhbmVsJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgSW9uU3Bpbm5lciwgQ2hhdFdpbmRvd0NvbXBvbmVudF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cInRocmVhZC1wYW5lbFwiPlxuICAgICAgQGlmICh0aXRsZSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwidGhyZWFkLWhlYWRlclwiPlxuICAgICAgICAgIDxwIGNsYXNzPVwidGhyZWFkLXRpdGxlXCI+e3sgdGl0bGUgfX08L3A+XG4gICAgICAgIDwvZGl2PlxuICAgICAgfVxuXG4gICAgICBAaWYgKGxvYWRpbmcoKSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwidGhyZWFkLWxvYWRpbmdcIj5cbiAgICAgICAgICA8aW9uLXNwaW5uZXIgbmFtZT1cImRvdHNcIj48L2lvbi1zcGlubmVyPlxuICAgICAgICAgIDxzcGFuPnt7IGxvYWRpbmdUZXh0KCkgfX08L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0aHJlYWQtY2hhdFwiPlxuICAgICAgICAgIDx2YWwtY2hhdC13aW5kb3dcbiAgICAgICAgICAgIFtjb252SWRdPVwiY29udigpPy5pZCA/PyAnJ1wiXG4gICAgICAgICAgICBbbWVzc2FnZXNdPVwiYnViYmxlTWVzc2FnZXMoKVwiXG4gICAgICAgICAgICBbY3VycmVudFVzZXJJZF09XCJjdXJyZW50VXNlcklkXCJcbiAgICAgICAgICAgIFtpc09wZW5dPVwiaXNDb252T3BlbigpXCJcbiAgICAgICAgICAgIFt0eXBpbmdVc2Vyc109XCJ0eXBpbmdVc2VycygpXCJcbiAgICAgICAgICAgIFtpc0xvYWRpbmddPVwiZmFsc2VcIlxuICAgICAgICAgICAgKHNlbmRNZXNzYWdlKT1cIm9uU2VuZCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChyZWFjdGlvbkNsaWNrKT1cIm9uUmVhY3Rpb25DbGljaygkZXZlbnQpXCJcbiAgICAgICAgICAgIChkZWxldGVNZXNzYWdlKT1cIm9uRGVsZXRlTWVzc2FnZSgkZXZlbnQpXCJcbiAgICAgICAgICAgIChyZXBseVRvKT1cIm9uUmVwbHlUbygkZXZlbnQpXCJcbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbJy4vdGhyZWFkLXBhbmVsLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIFRocmVhZFBhbmVsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBwcm90ZWN0ZWQgaTE4biA9IGluamVjdChJMThuU2VydmljZSk7XG4gIHByaXZhdGUgY29udmVyc2F0aW9uU3ZjID0gaW5qZWN0KENvbnZlcnNhdGlvblNlcnZpY2UsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG4gIHByaXZhdGUgY2hhdENvbmZpZyA9IGluamVjdChWQUxURUNIX0NIQVRfQ09ORklHLCB7IG9wdGlvbmFsOiB0cnVlIH0pO1xuICBwcml2YXRlIGF1dGggPSBpbmplY3QoQXV0aFNlcnZpY2UsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cbiAgQElucHV0KCkgZW50aXR5VHlwZTogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIGVudGl0eUlkOiBzdHJpbmcgPSAnJztcbiAgQElucHV0KCkgY3VycmVudFVzZXJJZDogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIHRpdGxlPzogc3RyaW5nO1xuXG4gIHByb3RlY3RlZCBsb2FkaW5nID0gc2lnbmFsKHRydWUpO1xuICBwcm90ZWN0ZWQgY29udiA9IHNpZ25hbDxDb252ZXJzYXRpb24gfCBudWxsPihudWxsKTtcbiAgcHJvdGVjdGVkIG1lc3NhZ2VzID0gc2lnbmFsPE1lc3NhZ2VbXT4oW10pO1xuICBwcm90ZWN0ZWQgdHlwaW5nVXNlcnMgPSBzaWduYWw8c3RyaW5nW10+KFtdKTtcblxuICBwcml2YXRlIG1zZ1N1Yj86IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSB0eXBpbmdTdWI/OiBTdWJzY3JpcHRpb247XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5pMThuLnJlZ2lzdGVyRGVmYXVsdHMoJ1RocmVhZFBhbmVsJywgVEhSRUFEX1BBTkVMX0kxOE4pO1xuICB9XG5cbiAgYXN5bmMgbmdPbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmNvbnZlcnNhdGlvblN2YyB8fCAhdGhpcy5lbnRpdHlUeXBlIHx8ICF0aGlzLmVudGl0eUlkKSB7XG4gICAgICB0aGlzLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udmVyc2F0aW9uID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20oXG4gICAgICAgIHRoaXMuY29udmVyc2F0aW9uU3ZjLmdldE9yQ3JlYXRlRm9yRW50aXR5KHRoaXMuZW50aXR5VHlwZSwgdGhpcy5lbnRpdHlJZClcbiAgICAgICk7XG4gICAgICB0aGlzLmNvbnYuc2V0KGNvbnZlcnNhdGlvbik7XG5cbiAgICAgIGNvbnN0IG9yZ0lkID0gdGhpcy5nZXRPcmdJZCgpO1xuICAgICAgY29uc3QgYXBwSWQgPSB0aGlzLmNoYXRDb25maWc/LmFwcElkID8/ICcnO1xuXG4gICAgICBpZiAob3JnSWQgJiYgYXBwSWQpIHtcbiAgICAgICAgdGhpcy5tc2dTdWIgPSB0aGlzLmNvbnZlcnNhdGlvblN2Y1xuICAgICAgICAgIC53YXRjaE1lc3NhZ2VzKGNvbnZlcnNhdGlvbi5pZCwgb3JnSWQsIGFwcElkKVxuICAgICAgICAgIC5zdWJzY3JpYmUobXNncyA9PiB0aGlzLm1lc3NhZ2VzLnNldChtc2dzKSk7XG5cbiAgICAgICAgdGhpcy50eXBpbmdTdWIgPSB0aGlzLmNvbnZlcnNhdGlvblN2Y1xuICAgICAgICAgIC53YXRjaFR5cGluZyhjb252ZXJzYXRpb24uaWQsIG9yZ0lkLCBhcHBJZClcbiAgICAgICAgICAuc3Vic2NyaWJlKHVzZXJzID0+IHRoaXMudHlwaW5nVXNlcnMuc2V0KHVzZXJzKSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdbVGhyZWFkUGFuZWxdIEVycm9yIGFsIGluaWNpYWxpemFyIGNvbnZlcnNhY2lvbjonLCBlcnIpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLm1zZ1N1Yj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnR5cGluZ1N1Yj8udW5zdWJzY3JpYmUoKTtcblxuICAgIGNvbnN0IGNvbnYgPSB0aGlzLmNvbnYoKTtcbiAgICBjb25zdCBvcmdJZCA9IHRoaXMuZ2V0T3JnSWQoKTtcbiAgICBjb25zdCBhcHBJZCA9IHRoaXMuY2hhdENvbmZpZz8uYXBwSWQgPz8gJyc7XG4gICAgaWYgKGNvbnYgJiYgb3JnSWQgJiYgYXBwSWQgJiYgdGhpcy5jb252ZXJzYXRpb25TdmMpIHtcbiAgICAgIHRoaXMuY29udmVyc2F0aW9uU3ZjLnN0b3BUeXBpbmcoY29udi5pZCwgb3JnSWQsIGFwcElkKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgaXNDb252T3BlbiA9IGNvbXB1dGVkKCgpID0+IHRoaXMuY29udigpPy5zdGF0dXMgPT09ICdvcGVuJyk7XG5cbiAgcHJvdGVjdGVkIGxvYWRpbmdUZXh0ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIHRoaXMuaTE4bi5sYW5nKCk7XG4gICAgcmV0dXJuIHRoaXMuaTE4bi50KCdsb2FkaW5nJywgJ1RocmVhZFBhbmVsJyk7XG4gIH0pO1xuXG4gIHByb3RlY3RlZCBidWJibGVNZXNzYWdlcyA9IGNvbXB1dGVkKCgpOiBNZXNzYWdlQnViYmxlTWV0YWRhdGFbXSA9PiB7XG4gICAgY29uc3QgdWlkID0gdGhpcy5jdXJyZW50VXNlcklkIHx8IHRoaXMuYXV0aD8udXNlcigpPy51c2VySWQgfHwgJyc7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMoKS5tYXAobXNnID0+ICh7XG4gICAgICBtc2dJZDogbXNnLmlkLFxuICAgICAgc2VuZGVySWQ6IG1zZy5zZW5kZXJJZCxcbiAgICAgIHNlbmRlck5hbWU6IG1zZy5zZW5kZXJOYW1lLFxuICAgICAgc2VuZGVyQXZhdGFyOiBtc2cuc2VuZGVyQXZhdGFyLFxuICAgICAgYm9keTogbXNnLmJvZHksXG4gICAgICB0eXBlOiBtc2cudHlwZSxcbiAgICAgIGNyZWF0ZWRBdDogbXNnLmNyZWF0ZWRBdCxcbiAgICAgIGlzTWluZTogbXNnLnNlbmRlcklkID09PSB1aWQsXG4gICAgICBpc0RlbGV0ZWQ6IG1zZy5pc0RlbGV0ZWQsXG4gICAgICBpc0VkaXRlZDogbXNnLmlzRWRpdGVkLFxuICAgICAgcmVwbHlUbzogbXNnLnJlcGx5VG8sXG4gICAgICBhdHRhY2htZW50czogbXNnLmF0dGFjaG1lbnRzLFxuICAgICAgcmVhY3Rpb25zOiBtc2cucmVhY3Rpb25zLFxuICAgICAgc3RhdHVzOiBtc2cuc3RhdHVzLFxuICAgIH0pKTtcbiAgfSk7XG5cbiAgcHJvdGVjdGVkIG9uU2VuZChib2R5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjb252ID0gdGhpcy5jb252KCk7XG4gICAgaWYgKCFjb252IHx8ICF0aGlzLmNvbnZlcnNhdGlvblN2YykgcmV0dXJuO1xuICAgIHRoaXMuY29udmVyc2F0aW9uU3ZjLnNlbmRNZXNzYWdlKGNvbnYuaWQsIGJvZHkpLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uUmVhY3Rpb25DbGljayhldmVudDogeyBtc2dJZDogc3RyaW5nOyB0b2tlbjogc3RyaW5nIH0pOiB2b2lkIHtcbiAgICAvLyBSZWFjY2lvbmVzIHNlIGltcGxlbWVudGFuIGEgbml2ZWwgZGUgYXBwIGNvbnN1bWVyXG4gICAgY29uc29sZS5kZWJ1ZygnW1RocmVhZFBhbmVsXSByZWFjdGlvbkNsaWNrJywgZXZlbnQpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uRGVsZXRlTWVzc2FnZShtc2dJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY29udiA9IHRoaXMuY29udigpO1xuICAgIGlmICghY29udiB8fCAhdGhpcy5jb252ZXJzYXRpb25TdmMpIHJldHVybjtcbiAgICB0aGlzLmNvbnZlcnNhdGlvblN2Yy5kZWxldGVNZXNzYWdlKGNvbnYuaWQsIG1zZ0lkKS5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblJlcGx5VG8oX21zZ0lkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBJbXBsZW1lbnRhY2lvbiBmdXR1cmE6IHNlbGVjY2lvbmFyIG1lbnNhamUgZGUgcmVzcHVlc3RhXG4gIH1cblxuICBwcml2YXRlIGdldE9yZ0lkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aD8udXNlcigpPy5hY3RpdmVPcmcgPz8gJyc7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,35 @@
1
+ import { InjectionToken, makeEnvironmentProviders } from '@angular/core';
2
+ /**
3
+ * Token de inyeccion para la configuracion del Chat.
4
+ */
5
+ export const VALTECH_CHAT_CONFIG = new InjectionToken('ValtechChatConfig');
6
+ /**
7
+ * Configuracion por defecto del Chat.
8
+ */
9
+ export const DEFAULT_CHAT_CONFIG = {
10
+ chatPrefix: '/v2/chat',
11
+ };
12
+ /**
13
+ * Provee el servicio de Chat a la aplicacion Angular.
14
+ *
15
+ * @example
16
+ * // main.ts
17
+ * import { provideValtechChat } from 'valtech-components';
18
+ *
19
+ * bootstrapApplication(AppComponent, {
20
+ * providers: [
21
+ * provideValtechChat({
22
+ * apiUrl: environment.apiUrl,
23
+ * appId: 'showcase',
24
+ * }),
25
+ * ],
26
+ * });
27
+ */
28
+ export function provideValtechChat(config) {
29
+ const mergedConfig = {
30
+ ...DEFAULT_CHAT_CONFIG,
31
+ ...config,
32
+ };
33
+ return makeEnvironmentProviders([{ provide: VALTECH_CHAT_CONFIG, useValue: mergedConfig }]);
34
+ }
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9jaGF0L2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQXdCLGNBQWMsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQWMvRjs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLElBQUksY0FBYyxDQUFvQixtQkFBbUIsQ0FBQyxDQUFDO0FBRTlGOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQStCO0lBQzdELFVBQVUsRUFBRSxVQUFVO0NBQ3ZCLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsTUFBeUI7SUFDMUQsTUFBTSxZQUFZLEdBQXNCO1FBQ3RDLEdBQUcsbUJBQW1CO1FBQ3RCLEdBQUcsTUFBTTtLQUNWLENBQUM7SUFFRixPQUFPLHdCQUF3QixDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRW52aXJvbm1lbnRQcm92aWRlcnMsIEluamVjdGlvblRva2VuLCBtYWtlRW52aXJvbm1lbnRQcm92aWRlcnMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuLyoqXG4gKiBDb25maWd1cmFjaW9uIGRlbCBzZXJ2aWNpbyBkZSBDaGF0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFZhbHRlY2hDaGF0Q29uZmlnIHtcbiAgLyoqIFVSTCBiYXNlIGRlIGxhIEFQSSBkZWwgYmFja2VuZCAoZWo6ICdodHRwczovL2FwaS5teXZhbHRlY2guY29tJykuICovXG4gIGFwaVVybDogc3RyaW5nO1xuICAvKiogSUQgZGUgbGEgYXBsaWNhY2lvbiAoZWo6ICdzaG93Y2FzZScpLiAqL1xuICBhcHBJZDogc3RyaW5nO1xuICAvKiogUHJlZmlqbyBkZWwgZW5kcG9pbnQgZGUgY2hhdCAoZGVmYXVsdDogJy92Mi9jaGF0JykuICovXG4gIGNoYXRQcmVmaXg/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVG9rZW4gZGUgaW55ZWNjaW9uIHBhcmEgbGEgY29uZmlndXJhY2lvbiBkZWwgQ2hhdC5cbiAqL1xuZXhwb3J0IGNvbnN0IFZBTFRFQ0hfQ0hBVF9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48VmFsdGVjaENoYXRDb25maWc+KCdWYWx0ZWNoQ2hhdENvbmZpZycpO1xuXG4vKipcbiAqIENvbmZpZ3VyYWNpb24gcG9yIGRlZmVjdG8gZGVsIENoYXQuXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0NIQVRfQ09ORklHOiBQYXJ0aWFsPFZhbHRlY2hDaGF0Q29uZmlnPiA9IHtcbiAgY2hhdFByZWZpeDogJy92Mi9jaGF0Jyxcbn07XG5cbi8qKlxuICogUHJvdmVlIGVsIHNlcnZpY2lvIGRlIENoYXQgYSBsYSBhcGxpY2FjaW9uIEFuZ3VsYXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIG1haW4udHNcbiAqIGltcG9ydCB7IHByb3ZpZGVWYWx0ZWNoQ2hhdCB9IGZyb20gJ3ZhbHRlY2gtY29tcG9uZW50cyc7XG4gKlxuICogYm9vdHN0cmFwQXBwbGljYXRpb24oQXBwQ29tcG9uZW50LCB7XG4gKiAgIHByb3ZpZGVyczogW1xuICogICAgIHByb3ZpZGVWYWx0ZWNoQ2hhdCh7XG4gKiAgICAgICBhcGlVcmw6IGVudmlyb25tZW50LmFwaVVybCxcbiAqICAgICAgIGFwcElkOiAnc2hvd2Nhc2UnLFxuICogICAgIH0pLFxuICogICBdLFxuICogfSk7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlVmFsdGVjaENoYXQoY29uZmlnOiBWYWx0ZWNoQ2hhdENvbmZpZyk6IEVudmlyb25tZW50UHJvdmlkZXJzIHtcbiAgY29uc3QgbWVyZ2VkQ29uZmlnOiBWYWx0ZWNoQ2hhdENvbmZpZyA9IHtcbiAgICAuLi5ERUZBVUxUX0NIQVRfQ09ORklHLFxuICAgIC4uLmNvbmZpZyxcbiAgfTtcblxuICByZXR1cm4gbWFrZUVudmlyb25tZW50UHJvdmlkZXJzKFt7IHByb3ZpZGU6IFZBTFRFQ0hfQ0hBVF9DT05GSUcsIHVzZVZhbHVlOiBtZXJnZWRDb25maWcgfV0pO1xufVxuIl19
@@ -0,0 +1,274 @@
1
+ import { Injectable, inject, isDevMode } from '@angular/core';
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { map } from 'rxjs';
4
+ import { serverTimestamp, deleteDoc, doc, setDoc, updateDoc } from '@angular/fire/firestore';
5
+ import { Firestore } from '@angular/fire/firestore';
6
+ import { VALTECH_CHAT_CONFIG } from './config';
7
+ import { FirestoreService } from '../firebase/firestore.service';
8
+ import * as i0 from "@angular/core";
9
+ /**
10
+ * ConversationService
11
+ *
12
+ * Gestiona conversaciones y mensajes del chat.
13
+ *
14
+ * Dos capas:
15
+ * - HTTP (via backend /v2/chat/*): operaciones de escritura y consulta.
16
+ * - Firestore real-time (directa): escucha mensajes y estado de escritura.
17
+ *
18
+ * Paths Firestore:
19
+ * /apps/{appId}/orgs/{orgId}/conversations/{convId}/messages/{msgId}
20
+ * /apps/{appId}/orgs/{orgId}/conversations/{convId}/typing/{userId}
21
+ *
22
+ * @example
23
+ * // Enviar y escuchar mensajes
24
+ * const svc = inject(ConversationService);
25
+ *
26
+ * // Enviar (HTTP)
27
+ * svc.sendMessage(convId, 'Hola!').subscribe();
28
+ *
29
+ * // Escuchar en tiempo real (Firestore)
30
+ * svc.watchMessages(convId, orgId, appId).subscribe(msgs => this.messages.set(msgs));
31
+ */
32
+ export class ConversationService {
33
+ constructor() {
34
+ this.config = inject(VALTECH_CHAT_CONFIG, { optional: true });
35
+ this.http = inject(HttpClient);
36
+ this.firestoreService = inject(FirestoreService, { optional: true });
37
+ this.firestore = inject(Firestore, { optional: true });
38
+ if (!this.config && isDevMode()) {
39
+ console.warn('[valtech-components] ConversationService: provideValtechChat() no esta en main.ts. ' +
40
+ 'El chat no funcionara.');
41
+ }
42
+ }
43
+ // ===========================================================================
44
+ // HTTP — operaciones de escritura y consulta al backend
45
+ // ===========================================================================
46
+ get baseUrl() {
47
+ return `${this.config?.apiUrl}${this.config?.chatPrefix ?? '/v2/chat'}`;
48
+ }
49
+ /**
50
+ * Crea una nueva conversacion.
51
+ */
52
+ createConversation(req) {
53
+ return this.http.post(`${this.baseUrl}/conversations`, req);
54
+ }
55
+ /**
56
+ * Obtiene o crea una conversacion asociada a una entidad (post, request, etc.).
57
+ * Usa el patron upsert del backend: si ya existe una conversacion para esa entidad,
58
+ * la devuelve; si no, la crea.
59
+ */
60
+ getOrCreateForEntity(entityType, entityId, type = 'entity') {
61
+ return this.http.post(`${this.baseUrl}/conversations/entity`, {
62
+ entityType,
63
+ entityId,
64
+ type,
65
+ });
66
+ }
67
+ /**
68
+ * Lista las conversaciones del usuario autenticado.
69
+ */
70
+ listConversations(cursor) {
71
+ const params = {};
72
+ if (cursor)
73
+ params['cursor'] = cursor;
74
+ return this.http.get(`${this.baseUrl}/conversations`, { params });
75
+ }
76
+ /**
77
+ * Obtiene una conversacion por ID.
78
+ */
79
+ getConversation(convId) {
80
+ return this.http.get(`${this.baseUrl}/conversations/${convId}`);
81
+ }
82
+ /**
83
+ * Actualiza el titulo o estado de una conversacion.
84
+ */
85
+ updateConversation(convId, req) {
86
+ return this.http.patch(`${this.baseUrl}/conversations/${convId}`, req);
87
+ }
88
+ /**
89
+ * Abre una conversacion cerrada.
90
+ */
91
+ openConversation(convId) {
92
+ return this.http.post(`${this.baseUrl}/conversations/${convId}/open`, {});
93
+ }
94
+ /**
95
+ * Cierra una conversacion.
96
+ */
97
+ closeConversation(convId) {
98
+ return this.http.post(`${this.baseUrl}/conversations/${convId}/close`, {});
99
+ }
100
+ /**
101
+ * Agrega un participante a la conversacion.
102
+ */
103
+ addParticipant(convId, userId) {
104
+ return this.http.post(`${this.baseUrl}/conversations/${convId}/participants`, { userId });
105
+ }
106
+ /**
107
+ * Elimina un participante de la conversacion.
108
+ */
109
+ removeParticipant(convId, userId) {
110
+ return this.http.delete(`${this.baseUrl}/conversations/${convId}/participants/${userId}`);
111
+ }
112
+ /**
113
+ * Envia un mensaje a una conversacion.
114
+ */
115
+ sendMessage(convId, body) {
116
+ return this.http.post(`${this.baseUrl}/conversations/${convId}/messages`, { body });
117
+ }
118
+ /**
119
+ * Elimina (marca como eliminado) un mensaje.
120
+ */
121
+ deleteMessage(convId, msgId) {
122
+ return this.http.delete(`${this.baseUrl}/conversations/${convId}/messages/${msgId}`);
123
+ }
124
+ // ===========================================================================
125
+ // Firestore — escucha en tiempo real (sin pasar por el backend)
126
+ // ===========================================================================
127
+ /**
128
+ * Construye el path base para los datos de una conversacion.
129
+ * Nota: usamos el path completo con skipPrefix porque el path ya incluye
130
+ * apps/{appId}/orgs/{orgId} que el FirestoreService prefijaria de nuevo.
131
+ * En cambio armamos el path como sub-coleccion directamente.
132
+ */
133
+ convMessagesPath(convId, orgId, appId) {
134
+ return `apps/${appId}/orgs/${orgId}/conversations/${convId}/messages`;
135
+ }
136
+ convTypingPath(convId, orgId, appId) {
137
+ return `apps/${appId}/orgs/${orgId}/conversations/${convId}/typing`;
138
+ }
139
+ /**
140
+ * Escucha los mensajes de una conversacion en tiempo real.
141
+ *
142
+ * @param convId - ID de la conversacion
143
+ * @param orgId - ID de la organizacion
144
+ * @param appId - ID de la aplicacion
145
+ * @param limit - Cantidad maxima de mensajes a cargar (default 50)
146
+ */
147
+ watchMessages(convId, orgId, appId, limit = 50) {
148
+ if (!this.firestoreService) {
149
+ throw new Error('[ConversationService] FirestoreService no disponible. Asegurate de provideValtechFirebase().');
150
+ }
151
+ // Usamos ABS_PATH_SENTINEL para evitar que FirestoreService anteponga el prefijo
152
+ // porque el path ya contiene la ruta completa con appId/orgId.
153
+ const { ABS_PATH_SENTINEL } = this.getAbsPathSentinel();
154
+ const collectionPath = `${ABS_PATH_SENTINEL}${this.convMessagesPath(convId, orgId, appId)}`;
155
+ return this.firestoreService.collectionChanges(collectionPath, {
156
+ orderBy: [{ field: 'createdAt', direction: 'asc' }],
157
+ limit,
158
+ });
159
+ }
160
+ /**
161
+ * Escucha los usuarios que estan escribiendo en una conversacion.
162
+ * Devuelve un array de displayNames.
163
+ *
164
+ * @param convId - ID de la conversacion
165
+ * @param orgId - ID de la organizacion
166
+ * @param appId - ID de la aplicacion
167
+ */
168
+ watchTyping(convId, orgId, appId) {
169
+ if (!this.firestoreService) {
170
+ throw new Error('[ConversationService] FirestoreService no disponible. Asegurate de provideValtechFirebase().');
171
+ }
172
+ const { ABS_PATH_SENTINEL } = this.getAbsPathSentinel();
173
+ const collectionPath = `${ABS_PATH_SENTINEL}${this.convTypingPath(convId, orgId, appId)}`;
174
+ return this.firestoreService
175
+ .collectionChanges(collectionPath)
176
+ .pipe(map(docs => docs.map(d => d.displayName)));
177
+ }
178
+ /**
179
+ * Registra que el usuario actual esta escribiendo.
180
+ * El documento se sobreescribe para actualizar el timestamp.
181
+ * Debe llamarse con un TTL/cleanup (ver stopTyping).
182
+ *
183
+ * @param convId - ID de la conversacion
184
+ * @param orgId - ID de la organizacion
185
+ * @param appId - ID de la aplicacion
186
+ * @param displayName - Nombre visible del usuario
187
+ */
188
+ startTyping(convId, orgId, appId, displayName) {
189
+ if (!this.firestore)
190
+ return;
191
+ const userId = this.getCurrentUserId();
192
+ if (!userId)
193
+ return;
194
+ const path = `${this.convTypingPath(convId, orgId, appId)}/${userId}`;
195
+ const docRef = doc(this.firestore, path);
196
+ void setDoc(docRef, {
197
+ displayName,
198
+ updatedAt: serverTimestamp(),
199
+ });
200
+ }
201
+ /**
202
+ * Elimina el documento de "escribiendo" del usuario actual.
203
+ *
204
+ * @param convId - ID de la conversacion
205
+ * @param orgId - ID de la organizacion
206
+ * @param appId - ID de la aplicacion
207
+ */
208
+ stopTyping(convId, orgId, appId) {
209
+ if (!this.firestore)
210
+ return;
211
+ const userId = this.getCurrentUserId();
212
+ if (!userId)
213
+ return;
214
+ const path = `${this.convTypingPath(convId, orgId, appId)}/${userId}`;
215
+ const docRef = doc(this.firestore, path);
216
+ void deleteDoc(docRef);
217
+ }
218
+ /**
219
+ * Marca un mensaje como leido por el usuario actual.
220
+ * Escribe directamente en Firestore sin pasar por el backend.
221
+ *
222
+ * @param convId - ID de la conversacion
223
+ * @param msgId - ID del ultimo mensaje leido
224
+ * @param orgId - ID de la organizacion
225
+ * @param appId - ID de la aplicacion
226
+ */
227
+ markRead(convId, msgId, orgId, appId) {
228
+ if (!this.firestore)
229
+ return;
230
+ const userId = this.getCurrentUserId();
231
+ if (!userId)
232
+ return;
233
+ const convPath = `apps/${appId}/orgs/${orgId}/conversations/${convId}`;
234
+ const convRef = doc(this.firestore, convPath);
235
+ // Usa dot-notation de Firestore para actualizar solo el campo del usuario
236
+ const updateData = {
237
+ [`participants_readMap.${userId}`]: msgId,
238
+ updatedAt: serverTimestamp(),
239
+ };
240
+ void updateDoc(convRef, updateData);
241
+ }
242
+ // ===========================================================================
243
+ // Helpers privados
244
+ // ===========================================================================
245
+ /**
246
+ * Importa ABS_PATH_SENTINEL de forma lazy para evitar dependencias circulares.
247
+ */
248
+ getAbsPathSentinel() {
249
+ // La sentinel se define en firestore.service.ts — replicamos el valor aqui
250
+ // para no crear una dependencia circular en el import estatico.
251
+ return { ABS_PATH_SENTINEL: '__abs__:' };
252
+ }
253
+ /**
254
+ * Obtiene el userId del usuario actual desde sessionStorage / localStorage
255
+ * como fallback no-DI para el contexto de escritura de Firestore.
256
+ * En prod, el AuthService actualiza el userId en el contexto de la app.
257
+ */
258
+ getCurrentUserId() {
259
+ // Intentar obtenerlo desde sessionStorage (el AuthService lo guarda ahi)
260
+ if (typeof sessionStorage !== 'undefined') {
261
+ const uid = sessionStorage.getItem('uid') ?? sessionStorage.getItem('userId');
262
+ if (uid)
263
+ return uid;
264
+ }
265
+ return null;
266
+ }
267
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConversationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
268
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConversationService, providedIn: 'root' }); }
269
+ }
270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConversationService, decorators: [{
271
+ type: Injectable,
272
+ args: [{ providedIn: 'root' }]
273
+ }], ctorParameters: () => [] });
274
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udmVyc2F0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2NoYXQvY29udmVyc2F0aW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzlELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRCxPQUFPLEVBQWMsR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDN0YsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRXBELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQVUvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7QUFFakU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQkc7QUFFSCxNQUFNLE9BQU8sbUJBQW1CO0lBTTlCO1FBTFEsV0FBTSxHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3pELFNBQUksR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDMUIscUJBQWdCLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDaEUsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUd4RCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxTQUFTLEVBQUUsRUFBRSxDQUFDO1lB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QWUsRUFBRTtTQUM3QixDQUFDO1FBRUYsS0FBSyxTQUFTLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRCw4RUFBOEU7SUFDOUUsbUJBQW1CO0lBQ25CLDhFQUE4RTtJQUU5RTs7T0FFRztJQUNLLGtCQUFrQjtRQUN4QiwyRUFBMkU7UUFDM0UsZ0VBQWdFO1FBQ2hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxVQUFVLEVBQUUsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGdCQUFnQjtRQUN0Qix5RUFBeUU7UUFDekUsSUFBSSxPQUFPLGNBQWMsS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUMxQyxNQUFNLEdBQUcsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLGNBQWMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDOUUsSUFBSSxHQUFHO2dCQUFFLE9BQU8sR0FBRyxDQUFDO1FBQ3RCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7K0dBeFJVLG1CQUFtQjttSEFBbkIsbUJBQW1CLGNBRE4sTUFBTTs7NEZBQ25CLG1CQUFtQjtrQkFEL0IsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QsIGlzRGV2TW9kZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IE9ic2VydmFibGUsIG1hcCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgc2VydmVyVGltZXN0YW1wLCBkZWxldGVEb2MsIGRvYywgc2V0RG9jLCB1cGRhdGVEb2MgfSBmcm9tICdAYW5ndWxhci9maXJlL2ZpcmVzdG9yZSc7XG5pbXBvcnQgeyBGaXJlc3RvcmUgfSBmcm9tICdAYW5ndWxhci9maXJlL2ZpcmVzdG9yZSc7XG5cbmltcG9ydCB7IFZBTFRFQ0hfQ0hBVF9DT05GSUcgfSBmcm9tICcuL2NvbmZpZyc7XG5pbXBvcnQge1xuICBDb252ZXJzYXRpb24sXG4gIENvbnZlcnNhdGlvblR5cGUsXG4gIENyZWF0ZUNvbnZlcnNhdGlvblJlcXVlc3QsXG4gIExpc3RDb252ZXJzYXRpb25zUmVzcG9uc2UsXG4gIE1lc3NhZ2UsXG4gIFVwZGF0ZUNvbnZlcnNhdGlvblJlcXVlc3QsXG4gIFR5cGluZ0RvY3VtZW50LFxufSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IEZpcmVzdG9yZVNlcnZpY2UgfSBmcm9tICcuLi9maXJlYmFzZS9maXJlc3RvcmUuc2VydmljZSc7XG5cbi8qKlxuICogQ29udmVyc2F0aW9uU2VydmljZVxuICpcbiAqIEdlc3Rpb25hIGNvbnZlcnNhY2lvbmVzIHkgbWVuc2FqZXMgZGVsIGNoYXQuXG4gKlxuICogRG9zIGNhcGFzOlxuICogICAtIEhUVFAgKHZpYSBiYWNrZW5kIC92Mi9jaGF0LyopOiBvcGVyYWNpb25lcyBkZSBlc2NyaXR1cmEgeSBjb25zdWx0YS5cbiAqICAgLSBGaXJlc3RvcmUgcmVhbC10aW1lIChkaXJlY3RhKTogZXNjdWNoYSBtZW5zYWplcyB5IGVzdGFkbyBkZSBlc2NyaXR1cmEuXG4gKlxuICogUGF0aHMgRmlyZXN0b3JlOlxuICogICAvYXBwcy97YXBwSWR9L29yZ3Mve29yZ0lkfS9jb252ZXJzYXRpb25zL3tjb252SWR9L21lc3NhZ2VzL3ttc2dJZH1cbiAqICAgL2FwcHMve2FwcElkfS9vcmdzL3tvcmdJZH0vY29udmVyc2F0aW9ucy97Y29udklkfS90eXBpbmcve3VzZXJJZH1cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gRW52aWFyIHkgZXNjdWNoYXIgbWVuc2FqZXNcbiAqIGNvbnN0IHN2YyA9IGluamVjdChDb252ZXJzYXRpb25TZXJ2aWNlKTtcbiAqXG4gKiAvLyBFbnZpYXIgKEhUVFApXG4gKiBzdmMuc2VuZE1lc3NhZ2UoY29udklkLCAnSG9sYSEnKS5zdWJzY3JpYmUoKTtcbiAqXG4gKiAvLyBFc2N1Y2hhciBlbiB0aWVtcG8gcmVhbCAoRmlyZXN0b3JlKVxuICogc3ZjLndhdGNoTWVzc2FnZXMoY29udklkLCBvcmdJZCwgYXBwSWQpLnN1YnNjcmliZShtc2dzID0+IHRoaXMubWVzc2FnZXMuc2V0KG1zZ3MpKTtcbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBDb252ZXJzYXRpb25TZXJ2aWNlIHtcbiAgcHJpdmF0ZSBjb25maWcgPSBpbmplY3QoVkFMVEVDSF9DSEFUX0NPTkZJRywgeyBvcHRpb25hbDogdHJ1ZSB9KTtcbiAgcHJpdmF0ZSBodHRwID0gaW5qZWN0KEh0dHBDbGllbnQpO1xuICBwcml2YXRlIGZpcmVzdG9yZVNlcnZpY2UgPSBpbmplY3QoRmlyZXN0b3JlU2VydmljZSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcbiAgcHJpdmF0ZSBmaXJlc3RvcmUgPSBpbmplY3QoRmlyZXN0b3JlLCB7IG9wdGlvbmFsOiB0cnVlIH0pO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGlmICghdGhpcy5jb25maWcgJiYgaXNEZXZNb2RlKCkpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ1t2YWx0ZWNoLWNvbXBvbmVudHNdIENvbnZlcnNhdGlvblNlcnZpY2U6IHByb3ZpZGVWYWx0ZWNoQ2hhdCgpIG5vIGVzdGEgZW4gbWFpbi50cy4gJyArXG4gICAgICAgICAgJ0VsIGNoYXQgbm8gZnVuY2lvbmFyYS4nXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBIVFRQIOKAlCBvcGVyYWNpb25lcyBkZSBlc2NyaXR1cmEgeSBjb25zdWx0YSBhbCBiYWNrZW5kXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHByaXZhdGUgZ2V0IGJhc2VVcmwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7dGhpcy5jb25maWc/LmFwaVVybH0ke3RoaXMuY29uZmlnPy5jaGF0UHJlZml4ID8/ICcvdjIvY2hhdCd9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhIHVuYSBudWV2YSBjb252ZXJzYWNpb24uXG4gICAqL1xuICBjcmVhdGVDb252ZXJzYXRpb24ocmVxOiBDcmVhdGVDb252ZXJzYXRpb25SZXF1ZXN0KTogT2JzZXJ2YWJsZTxDb252ZXJzYXRpb24+IHtcbiAgICByZXR1cm4gdGhpcy5odHRwLnBvc3Q8Q29udmVyc2F0aW9uPihgJHt0aGlzLmJhc2VVcmx9L2NvbnZlcnNhdGlvbnNgLCByZXEpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgbyBjcmVhIHVuYSBjb252ZXJzYWNpb24gYXNvY2lhZGEgYSB1bmEgZW50aWRhZCAocG9zdCwgcmVxdWVzdCwgZXRjLikuXG4gICAqIFVzYSBlbCBwYXRyb24gdXBzZXJ0IGRlbCBiYWNrZW5kOiBzaSB5YSBleGlzdGUgdW5hIGNvbnZlcnNhY2lvbiBwYXJhIGVzYSBlbnRpZGFkLFxuICAgKiBsYSBkZXZ1ZWx2ZTsgc2kgbm8sIGxhIGNyZWEuXG4gICAqL1xuICBnZXRPckNyZWF0ZUZvckVudGl0eShcbiAgICBlbnRpdHlUeXBlOiBzdHJpbmcsXG4gICAgZW50aXR5SWQ6IHN0cmluZyxcbiAgICB0eXBlOiBDb252ZXJzYXRpb25UeXBlID0gJ2VudGl0eSdcbiAgKTogT2JzZXJ2YWJsZTxDb252ZXJzYXRpb24+IHtcbiAgICByZXR1cm4gdGhpcy5odHRwLnBvc3Q8Q29udmVyc2F0aW9uPihgJHt0aGlzLmJhc2VVcmx9L2NvbnZlcnNhdGlvbnMvZW50aXR5YCwge1xuICAgICAgZW50aXR5VHlwZSxcbiAgICAgIGVudGl0eUlkLFxuICAgICAgdHlwZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0YSBsYXMgY29udmVyc2FjaW9uZXMgZGVsIHVzdWFyaW8gYXV0ZW50aWNhZG8uXG4gICAqL1xuICBsaXN0Q29udmVyc2F0aW9ucyhjdXJzb3I/OiBzdHJpbmcpOiBPYnNlcnZhYmxlPExpc3RDb252ZXJzYXRpb25zUmVzcG9uc2U+IHtcbiAgICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBpZiAoY3Vyc29yKSBwYXJhbXNbJ2N1cnNvciddID0gY3Vyc29yO1xuICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PExpc3RDb252ZXJzYXRpb25zUmVzcG9uc2U+KGAke3RoaXMuYmFzZVVybH0vY29udmVyc2F0aW9uc2AsIHsgcGFyYW1zIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgdW5hIGNvbnZlcnNhY2lvbiBwb3IgSUQuXG4gICAqL1xuICBnZXRDb252ZXJzYXRpb24oY29udklkOiBzdHJpbmcpOiBPYnNlcnZhYmxlPENvbnZlcnNhdGlvbj4ge1xuICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PENvbnZlcnNhdGlvbj4oYCR7dGhpcy5iYXNlVXJsfS9jb252ZXJzYXRpb25zLyR7Y29udklkfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFjdHVhbGl6YSBlbCB0aXR1bG8gbyBlc3RhZG8gZGUgdW5hIGNvbnZlcnNhY2lvbi5cbiAgICovXG4gIHVwZGF0ZUNvbnZlcnNhdGlvbihjb252SWQ6IHN0cmluZywgcmVxOiBVcGRhdGVDb252ZXJzYXRpb25SZXF1ZXN0KTogT2JzZXJ2YWJsZTxDb252ZXJzYXRpb24+IHtcbiAgICByZXR1cm4gdGhpcy5odHRwLnBhdGNoPENvbnZlcnNhdGlvbj4oYCR7dGhpcy5iYXNlVXJsfS9jb252ZXJzYXRpb25zLyR7Y29udklkfWAsIHJlcSk7XG4gIH1cblxuICAvKipcbiAgICogQWJyZSB1bmEgY29udmVyc2FjaW9uIGNlcnJhZGEuXG4gICAqL1xuICBvcGVuQ29udmVyc2F0aW9uKGNvbnZJZDogc3RyaW5nKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0PHZvaWQ+KGAke3RoaXMuYmFzZVVybH0vY29udmVyc2F0aW9ucy8ke2NvbnZJZH0vb3BlbmAsIHt9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaWVycmEgdW5hIGNvbnZlcnNhY2lvbi5cbiAgICovXG4gIGNsb3NlQ29udmVyc2F0aW9uKGNvbnZJZDogc3RyaW5nKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0PHZvaWQ+KGAke3RoaXMuYmFzZVVybH0vY29udmVyc2F0aW9ucy8ke2NvbnZJZH0vY2xvc2VgLCB7fSk7XG4gIH1cblxuICAvKipcbiAgICogQWdyZWdhIHVuIHBhcnRpY2lwYW50ZSBhIGxhIGNvbnZlcnNhY2lvbi5cbiAgICovXG4gIGFkZFBhcnRpY2lwYW50KGNvbnZJZDogc3RyaW5nLCB1c2VySWQ6IHN0cmluZyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmh0dHAucG9zdDx2b2lkPihgJHt0aGlzLmJhc2VVcmx9L2NvbnZlcnNhdGlvbnMvJHtjb252SWR9L3BhcnRpY2lwYW50c2AsIHsgdXNlcklkIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEVsaW1pbmEgdW4gcGFydGljaXBhbnRlIGRlIGxhIGNvbnZlcnNhY2lvbi5cbiAgICovXG4gIHJlbW92ZVBhcnRpY2lwYW50KGNvbnZJZDogc3RyaW5nLCB1c2VySWQ6IHN0cmluZyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmh0dHAuZGVsZXRlPHZvaWQ+KGAke3RoaXMuYmFzZVVybH0vY29udmVyc2F0aW9ucy8ke2NvbnZJZH0vcGFydGljaXBhbnRzLyR7dXNlcklkfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEVudmlhIHVuIG1lbnNhamUgYSB1bmEgY29udmVyc2FjaW9uLlxuICAgKi9cbiAgc2VuZE1lc3NhZ2UoY29udklkOiBzdHJpbmcsIGJvZHk6IHN0cmluZyk6IE9ic2VydmFibGU8TWVzc2FnZT4ge1xuICAgIHJldHVybiB0aGlzLmh0dHAucG9zdDxNZXNzYWdlPihgJHt0aGlzLmJhc2VVcmx9L2NvbnZlcnNhdGlvbnMvJHtjb252SWR9L21lc3NhZ2VzYCwgeyBib2R5IH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEVsaW1pbmEgKG1hcmNhIGNvbW8gZWxpbWluYWRvKSB1biBtZW5zYWplLlxuICAgKi9cbiAgZGVsZXRlTWVzc2FnZShjb252SWQ6IHN0cmluZywgbXNnSWQ6IHN0cmluZyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmh0dHAuZGVsZXRlPHZvaWQ+KGAke3RoaXMuYmFzZVVybH0vY29udmVyc2F0aW9ucy8ke2NvbnZJZH0vbWVzc2FnZXMvJHttc2dJZH1gKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBGaXJlc3RvcmUg4oCUIGVzY3VjaGEgZW4gdGllbXBvIHJlYWwgKHNpbiBwYXNhciBwb3IgZWwgYmFja2VuZClcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIENvbnN0cnV5ZSBlbCBwYXRoIGJhc2UgcGFyYSBsb3MgZGF0b3MgZGUgdW5hIGNvbnZlcnNhY2lvbi5cbiAgICogTm90YTogdXNhbW9zIGVsIHBhdGggY29tcGxldG8gY29uIHNraXBQcmVmaXggcG9ycXVlIGVsIHBhdGggeWEgaW5jbHV5ZVxuICAgKiBhcHBzL3thcHBJZH0vb3Jncy97b3JnSWR9IHF1ZSBlbCBGaXJlc3RvcmVTZXJ2aWNlIHByZWZpamFyaWEgZGUgbnVldm8uXG4gICAqIEVuIGNhbWJpbyBhcm1hbW9zIGVsIHBhdGggY29tbyBzdWItY29sZWNjaW9uIGRpcmVjdGFtZW50ZS5cbiAgICovXG4gIHByaXZhdGUgY29udk1lc3NhZ2VzUGF0aChjb252SWQ6IHN0cmluZywgb3JnSWQ6IHN0cmluZywgYXBwSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGBhcHBzLyR7YXBwSWR9L29yZ3MvJHtvcmdJZH0vY29udmVyc2F0aW9ucy8ke2NvbnZJZH0vbWVzc2FnZXNgO1xuICB9XG5cbiAgcHJpdmF0ZSBjb252VHlwaW5nUGF0aChjb252SWQ6IHN0cmluZywgb3JnSWQ6IHN0cmluZywgYXBwSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGBhcHBzLyR7YXBwSWR9L29yZ3MvJHtvcmdJZH0vY29udmVyc2F0aW9ucy8ke2NvbnZJZH0vdHlwaW5nYDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFc2N1Y2hhIGxvcyBtZW5zYWplcyBkZSB1bmEgY29udmVyc2FjaW9uIGVuIHRpZW1wbyByZWFsLlxuICAgKlxuICAgKiBAcGFyYW0gY29udklkIC0gSUQgZGUgbGEgY29udmVyc2FjaW9uXG4gICAqIEBwYXJhbSBvcmdJZCAtIElEIGRlIGxhIG9yZ2FuaXphY2lvblxuICAgKiBAcGFyYW0gYXBwSWQgLSBJRCBkZSBsYSBhcGxpY2FjaW9uXG4gICAqIEBwYXJhbSBsaW1pdCAtIENhbnRpZGFkIG1heGltYSBkZSBtZW5zYWplcyBhIGNhcmdhciAoZGVmYXVsdCA1MClcbiAgICovXG4gIHdhdGNoTWVzc2FnZXMoXG4gICAgY29udklkOiBzdHJpbmcsXG4gICAgb3JnSWQ6IHN0cmluZyxcbiAgICBhcHBJZDogc3RyaW5nLFxuICAgIGxpbWl0OiBudW1iZXIgPSA1MFxuICApOiBPYnNlcnZhYmxlPE1lc3NhZ2VbXT4ge1xuICAgIGlmICghdGhpcy5maXJlc3RvcmVTZXJ2aWNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdbQ29udmVyc2F0aW9uU2VydmljZV0gRmlyZXN0b3JlU2VydmljZSBubyBkaXNwb25pYmxlLiBBc2VndXJhdGUgZGUgcHJvdmlkZVZhbHRlY2hGaXJlYmFzZSgpLidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gVXNhbW9zIEFCU19QQVRIX1NFTlRJTkVMIHBhcmEgZXZpdGFyIHF1ZSBGaXJlc3RvcmVTZXJ2aWNlIGFudGVwb25nYSBlbCBwcmVmaWpvXG4gICAgLy8gcG9ycXVlIGVsIHBhdGggeWEgY29udGllbmUgbGEgcnV0YSBjb21wbGV0YSBjb24gYXBwSWQvb3JnSWQuXG4gICAgY29uc3QgeyBBQlNfUEFUSF9TRU5USU5FTCB9ID0gdGhpcy5nZXRBYnNQYXRoU2VudGluZWwoKTtcbiAgICBjb25zdCBjb2xsZWN0aW9uUGF0aCA9IGAke0FCU19QQVRIX1NFTlRJTkVMfSR7dGhpcy5jb252TWVzc2FnZXNQYXRoKGNvbnZJZCwgb3JnSWQsIGFwcElkKX1gO1xuXG4gICAgcmV0dXJuIHRoaXMuZmlyZXN0b3JlU2VydmljZS5jb2xsZWN0aW9uQ2hhbmdlczxNZXNzYWdlPihjb2xsZWN0aW9uUGF0aCwge1xuICAgICAgb3JkZXJCeTogW3sgZmllbGQ6ICdjcmVhdGVkQXQnLCBkaXJlY3Rpb246ICdhc2MnIH1dLFxuICAgICAgbGltaXQsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRXNjdWNoYSBsb3MgdXN1YXJpb3MgcXVlIGVzdGFuIGVzY3JpYmllbmRvIGVuIHVuYSBjb252ZXJzYWNpb24uXG4gICAqIERldnVlbHZlIHVuIGFycmF5IGRlIGRpc3BsYXlOYW1lcy5cbiAgICpcbiAgICogQHBhcmFtIGNvbnZJZCAtIElEIGRlIGxhIGNvbnZlcnNhY2lvblxuICAgKiBAcGFyYW0gb3JnSWQgLSBJRCBkZSBsYSBvcmdhbml6YWNpb25cbiAgICogQHBhcmFtIGFwcElkIC0gSUQgZGUgbGEgYXBsaWNhY2lvblxuICAgKi9cbiAgd2F0Y2hUeXBpbmcoY29udklkOiBzdHJpbmcsIG9yZ0lkOiBzdHJpbmcsIGFwcElkOiBzdHJpbmcpOiBPYnNlcnZhYmxlPHN0cmluZ1tdPiB7XG4gICAgaWYgKCF0aGlzLmZpcmVzdG9yZVNlcnZpY2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ1tDb252ZXJzYXRpb25TZXJ2aWNlXSBGaXJlc3RvcmVTZXJ2aWNlIG5vIGRpc3BvbmlibGUuIEFzZWd1cmF0ZSBkZSBwcm92aWRlVmFsdGVjaEZpcmViYXNlKCkuJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IEFCU19QQVRIX1NFTlRJTkVMIH0gPSB0aGlzLmdldEFic1BhdGhTZW50aW5lbCgpO1xuICAgIGNvbnN0IGNvbGxlY3Rpb25QYXRoID0gYCR7QUJTX1BBVEhfU0VOVElORUx9JHt0aGlzLmNvbnZUeXBpbmdQYXRoKGNvbnZJZCwgb3JnSWQsIGFwcElkKX1gO1xuXG4gICAgcmV0dXJuIHRoaXMuZmlyZXN0b3JlU2VydmljZVxuICAgICAgLmNvbGxlY3Rpb25DaGFuZ2VzPFR5cGluZ0RvY3VtZW50Pihjb2xsZWN0aW9uUGF0aClcbiAgICAgIC5waXBlKG1hcChkb2NzID0+IGRvY3MubWFwKGQgPT4gZC5kaXNwbGF5TmFtZSkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RyYSBxdWUgZWwgdXN1YXJpbyBhY3R1YWwgZXN0YSBlc2NyaWJpZW5kby5cbiAgICogRWwgZG9jdW1lbnRvIHNlIHNvYnJlZXNjcmliZSBwYXJhIGFjdHVhbGl6YXIgZWwgdGltZXN0YW1wLlxuICAgKiBEZWJlIGxsYW1hcnNlIGNvbiB1biBUVEwvY2xlYW51cCAodmVyIHN0b3BUeXBpbmcpLlxuICAgKlxuICAgKiBAcGFyYW0gY29udklkIC0gSUQgZGUgbGEgY29udmVyc2FjaW9uXG4gICAqIEBwYXJhbSBvcmdJZCAtIElEIGRlIGxhIG9yZ2FuaXphY2lvblxuICAgKiBAcGFyYW0gYXBwSWQgLSBJRCBkZSBsYSBhcGxpY2FjaW9uXG4gICAqIEBwYXJhbSBkaXNwbGF5TmFtZSAtIE5vbWJyZSB2aXNpYmxlIGRlbCB1c3VhcmlvXG4gICAqL1xuICBzdGFydFR5cGluZyhjb252SWQ6IHN0cmluZywgb3JnSWQ6IHN0cmluZywgYXBwSWQ6IHN0cmluZywgZGlzcGxheU5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghdGhpcy5maXJlc3RvcmUpIHJldHVybjtcblxuICAgIGNvbnN0IHVzZXJJZCA9IHRoaXMuZ2V0Q3VycmVudFVzZXJJZCgpO1xuICAgIGlmICghdXNlcklkKSByZXR1cm47XG5cbiAgICBjb25zdCBwYXRoID0gYCR7dGhpcy5jb252VHlwaW5nUGF0aChjb252SWQsIG9yZ0lkLCBhcHBJZCl9LyR7dXNlcklkfWA7XG4gICAgY29uc3QgZG9jUmVmID0gZG9jKHRoaXMuZmlyZXN0b3JlLCBwYXRoKTtcblxuICAgIHZvaWQgc2V0RG9jKGRvY1JlZiwge1xuICAgICAgZGlzcGxheU5hbWUsXG4gICAgICB1cGRhdGVkQXQ6IHNlcnZlclRpbWVzdGFtcCgpLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEVsaW1pbmEgZWwgZG9jdW1lbnRvIGRlIFwiZXNjcmliaWVuZG9cIiBkZWwgdXN1YXJpbyBhY3R1YWwuXG4gICAqXG4gICAqIEBwYXJhbSBjb252SWQgLSBJRCBkZSBsYSBjb252ZXJzYWNpb25cbiAgICogQHBhcmFtIG9yZ0lkIC0gSUQgZGUgbGEgb3JnYW5pemFjaW9uXG4gICAqIEBwYXJhbSBhcHBJZCAtIElEIGRlIGxhIGFwbGljYWNpb25cbiAgICovXG4gIHN0b3BUeXBpbmcoY29udklkOiBzdHJpbmcsIG9yZ0lkOiBzdHJpbmcsIGFwcElkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZmlyZXN0b3JlKSByZXR1cm47XG5cbiAgICBjb25zdCB1c2VySWQgPSB0aGlzLmdldEN1cnJlbnRVc2VySWQoKTtcbiAgICBpZiAoIXVzZXJJZCkgcmV0dXJuO1xuXG4gICAgY29uc3QgcGF0aCA9IGAke3RoaXMuY29udlR5cGluZ1BhdGgoY29udklkLCBvcmdJZCwgYXBwSWQpfS8ke3VzZXJJZH1gO1xuICAgIGNvbnN0IGRvY1JlZiA9IGRvYyh0aGlzLmZpcmVzdG9yZSwgcGF0aCk7XG5cbiAgICB2b2lkIGRlbGV0ZURvYyhkb2NSZWYpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hcmNhIHVuIG1lbnNhamUgY29tbyBsZWlkbyBwb3IgZWwgdXN1YXJpbyBhY3R1YWwuXG4gICAqIEVzY3JpYmUgZGlyZWN0YW1lbnRlIGVuIEZpcmVzdG9yZSBzaW4gcGFzYXIgcG9yIGVsIGJhY2tlbmQuXG4gICAqXG4gICAqIEBwYXJhbSBjb252SWQgLSBJRCBkZSBsYSBjb252ZXJzYWNpb25cbiAgICogQHBhcmFtIG1zZ0lkIC0gSUQgZGVsIHVsdGltbyBtZW5zYWplIGxlaWRvXG4gICAqIEBwYXJhbSBvcmdJZCAtIElEIGRlIGxhIG9yZ2FuaXphY2lvblxuICAgKiBAcGFyYW0gYXBwSWQgLSBJRCBkZSBsYSBhcGxpY2FjaW9uXG4gICAqL1xuICBtYXJrUmVhZChjb252SWQ6IHN0cmluZywgbXNnSWQ6IHN0cmluZywgb3JnSWQ6IHN0cmluZywgYXBwSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghdGhpcy5maXJlc3RvcmUpIHJldHVybjtcblxuICAgIGNvbnN0IHVzZXJJZCA9IHRoaXMuZ2V0Q3VycmVudFVzZXJJZCgpO1xuICAgIGlmICghdXNlcklkKSByZXR1cm47XG5cbiAgICBjb25zdCBjb252UGF0aCA9IGBhcHBzLyR7YXBwSWR9L29yZ3MvJHtvcmdJZH0vY29udmVyc2F0aW9ucy8ke2NvbnZJZH1gO1xuICAgIGNvbnN0IGNvbnZSZWYgPSBkb2ModGhpcy5maXJlc3RvcmUsIGNvbnZQYXRoKTtcblxuICAgIC8vIFVzYSBkb3Qtbm90YXRpb24gZGUgRmlyZXN0b3JlIHBhcmEgYWN0dWFsaXphciBzb2xvIGVsIGNhbXBvIGRlbCB1c3VhcmlvXG4gICAgY29uc3QgdXBkYXRlRGF0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7XG4gICAgICBbYHBhcnRpY2lwYW50c19yZWFkTWFwLiR7dXNlcklkfWBdOiBtc2dJZCxcbiAgICAgIHVwZGF0ZWRBdDogc2VydmVyVGltZXN0YW1wKCksXG4gICAgfTtcblxuICAgIHZvaWQgdXBkYXRlRG9jKGNvbnZSZWYsIHVwZGF0ZURhdGEpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIEhlbHBlcnMgcHJpdmFkb3NcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEltcG9ydGEgQUJTX1BBVEhfU0VOVElORUwgZGUgZm9ybWEgbGF6eSBwYXJhIGV2aXRhciBkZXBlbmRlbmNpYXMgY2lyY3VsYXJlcy5cbiAgICovXG4gIHByaXZhdGUgZ2V0QWJzUGF0aFNlbnRpbmVsKCk6IHsgQUJTX1BBVEhfU0VOVElORUw6IHN0cmluZyB9IHtcbiAgICAvLyBMYSBzZW50aW5lbCBzZSBkZWZpbmUgZW4gZmlyZXN0b3JlLnNlcnZpY2UudHMg4oCUIHJlcGxpY2Ftb3MgZWwgdmFsb3IgYXF1aVxuICAgIC8vIHBhcmEgbm8gY3JlYXIgdW5hIGRlcGVuZGVuY2lhIGNpcmN1bGFyIGVuIGVsIGltcG9ydCBlc3RhdGljby5cbiAgICByZXR1cm4geyBBQlNfUEFUSF9TRU5USU5FTDogJ19fYWJzX186JyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgZWwgdXNlcklkIGRlbCB1c3VhcmlvIGFjdHVhbCBkZXNkZSBzZXNzaW9uU3RvcmFnZSAvIGxvY2FsU3RvcmFnZVxuICAgKiBjb21vIGZhbGxiYWNrIG5vLURJIHBhcmEgZWwgY29udGV4dG8gZGUgZXNjcml0dXJhIGRlIEZpcmVzdG9yZS5cbiAgICogRW4gcHJvZCwgZWwgQXV0aFNlcnZpY2UgYWN0dWFsaXphIGVsIHVzZXJJZCBlbiBlbCBjb250ZXh0byBkZSBsYSBhcHAuXG4gICAqL1xuICBwcml2YXRlIGdldEN1cnJlbnRVc2VySWQoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgLy8gSW50ZW50YXIgb2J0ZW5lcmxvIGRlc2RlIHNlc3Npb25TdG9yYWdlIChlbCBBdXRoU2VydmljZSBsbyBndWFyZGEgYWhpKVxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvblN0b3JhZ2UgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBjb25zdCB1aWQgPSBzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKCd1aWQnKSA/PyBzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKCd1c2VySWQnKTtcbiAgICAgIGlmICh1aWQpIHJldHVybiB1aWQ7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Chat Service Types
3
+ *
4
+ * Tipos compartidos para el sistema de chat en tiempo real.
5
+ * Firestore paths:
6
+ * /apps/{appId}/orgs/{orgId}/conversations/{convId}/messages/{msgId}
7
+ * /apps/{appId}/orgs/{orgId}/conversations/{convId}/typing/{userId}
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2NoYXQvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ2hhdCBTZXJ2aWNlIFR5cGVzXG4gKlxuICogVGlwb3MgY29tcGFydGlkb3MgcGFyYSBlbCBzaXN0ZW1hIGRlIGNoYXQgZW4gdGllbXBvIHJlYWwuXG4gKiBGaXJlc3RvcmUgcGF0aHM6XG4gKiAgIC9hcHBzL3thcHBJZH0vb3Jncy97b3JnSWR9L2NvbnZlcnNhdGlvbnMve2NvbnZJZH0vbWVzc2FnZXMve21zZ0lkfVxuICogICAvYXBwcy97YXBwSWR9L29yZ3Mve29yZ0lkfS9jb252ZXJzYXRpb25zL3tjb252SWR9L3R5cGluZy97dXNlcklkfVxuICovXG5cbmltcG9ydCB7IEZpcmVzdG9yZURvY3VtZW50IH0gZnJvbSAnLi4vZmlyZWJhc2UvdHlwZXMnO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENvbnZlcnNhdGlvblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKiBUaXBvIGRlIGNvbnZlcnNhY2lvbi4gKi9cbmV4cG9ydCB0eXBlIENvbnZlcnNhdGlvblR5cGUgPSAnZGlyZWN0JyB8ICdncm91cCcgfCAnZW50aXR5JztcblxuLyoqIEVzdGFkbyBkZSB1bmEgY29udmVyc2FjaW9uLiAqL1xuZXhwb3J0IHR5cGUgQ29udmVyc2F0aW9uU3RhdHVzID0gJ29wZW4nIHwgJ2Nsb3NlZCc7XG5cbi8qKiBQYXJ0aWNpcGFudGUgZGUgdW5hIGNvbnZlcnNhY2lvbi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29udmVyc2F0aW9uUGFydGljaXBhbnQge1xuICAvKiogSUQgZGVsIHVzdWFyaW8uICovXG4gIHVzZXJJZDogc3RyaW5nO1xuICAvKiogTm9tYnJlIHZpc2libGUgZGVsIHVzdWFyaW8uICovXG4gIGRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gIC8qKiBVUkwgZGVsIGF2YXRhciBkZWwgdXN1YXJpbyAob3BjaW9uYWwpLiAqL1xuICBhdmF0YXJVcmw/OiBzdHJpbmc7XG4gIC8qKiBGZWNoYSBlbiBxdWUgc2UgdW5pbyBhIGxhIGNvbnZlcnNhY2lvbi4gKi9cbiAgam9pbmVkQXQ6IERhdGU7XG4gIC8qKiBVbHRpbW8gbWVuc2FqZSBsZWlkbyBwb3IgZXN0ZSBwYXJ0aWNpcGFudGUuICovXG4gIGxhc3RSZWFkTXNnSWQ/OiBzdHJpbmc7XG59XG5cbi8qKiBEb2N1bWVudG8gZGUgY29udmVyc2FjaW9uIGVuIEZpcmVzdG9yZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29udmVyc2F0aW9uIGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQge1xuICAvKiogVGlwbyBkZSBjb252ZXJzYWNpb24uICovXG4gIHR5cGU6IENvbnZlcnNhdGlvblR5cGU7XG4gIC8qKiBFc3RhZG8gZGUgbGEgY29udmVyc2FjaW9uLiAqL1xuICBzdGF0dXM6IENvbnZlcnNhdGlvblN0YXR1cztcbiAgLyoqIFBhcnRpY2lwYW50ZXMuICovXG4gIHBhcnRpY2lwYW50czogQ29udmVyc2F0aW9uUGFydGljaXBhbnRbXTtcbiAgLyoqIFRpcG8gZGUgZW50aWRhZCBhc29jaWFkYSAocGFyYSB0aXBvIGVudGl0eSkuICovXG4gIGVudGl0eVR5cGU/OiBzdHJpbmc7XG4gIC8qKiBJRCBkZSBsYSBlbnRpZGFkIGFzb2NpYWRhLiAqL1xuICBlbnRpdHlJZD86IHN0cmluZztcbiAgLyoqIFRpdHVsbyBkZSBsYSBjb252ZXJzYWNpb24gKHBhcmEgZ3J1cG9zKS4gKi9cbiAgdGl0bGU/OiBzdHJpbmc7XG4gIC8qKiBJRCBkZWwgdWx0aW1vIG1lbnNhamUuICovXG4gIGxhc3RNc2dJZD86IHN0cmluZztcbiAgLyoqIFRleHRvIGRlbCB1bHRpbW8gbWVuc2FqZSAocHJldmlldykuICovXG4gIGxhc3RNc2dCb2R5Pzogc3RyaW5nO1xuICAvKiogRmVjaGEgZGVsIHVsdGltbyBtZW5zYWplLiAqL1xuICBsYXN0TXNnQXQ/OiBEYXRlO1xuICAvKiogQ29udGVvIGRlIG1lbnNhamVzIG5vIGxlaWRvcyBwb3IgdXNlcklkLiAqL1xuICB1bnJlYWRDb3VudD86IFJlY29yZDxzdHJpbmcsIG51bWJlcj47XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gTWVzc2FnZVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKiBUaXBvIGRlIG1lbnNhamUuICovXG5leHBvcnQgdHlwZSBNZXNzYWdlVHlwZSA9ICd0ZXh0JyB8ICdpbWFnZScgfCAnZmlsZScgfCAnc3lzdGVtJztcblxuLyoqIEVzdGFkbyBkZSBlbnZpbyBkZWwgbWVuc2FqZS4gKi9cbmV4cG9ydCB0eXBlIE1lc3NhZ2VTdGF0dXMgPSAnc2VuZGluZycgfCAnc2VudCcgfCAnZmFpbGVkJztcblxuLyoqIEFyY2hpdm8gYWRqdW50byBlbiB1biBtZW5zYWplLiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZXNzYWdlQXR0YWNobWVudCB7XG4gIC8qKiBOb21icmUgZGVsIGFyY2hpdm8uICovXG4gIG5hbWU6IHN0cmluZztcbiAgLyoqIFVSTCBkZSBkZXNjYXJnYS4gKi9cbiAgdXJsOiBzdHJpbmc7XG4gIC8qKiBUaXBvIE1JTUUuICovXG4gIG1pbWVUeXBlOiBzdHJpbmc7XG4gIC8qKiBUYW1hbm8gZW4gYnl0ZXMuICovXG4gIHNpemU/OiBudW1iZXI7XG59XG5cbi8qKiBSZWFjY2lvbiBhIHVuIG1lbnNhamUuICovXG5leHBvcnQgaW50ZXJmYWNlIE1lc3NhZ2VSZWFjdGlvbiB7XG4gIC8qKiBUb2tlbiBkZWwgZW1vamkgKGVqOiAnbGlrZScsICdoZWFydCcpLiAqL1xuICB0b2tlbjogc3RyaW5nO1xuICAvKiogQ2FudGlkYWQgZGUgdXN1YXJpb3MgcXVlIHJlYWNjaW9uYXJvbiBjb24gZXN0ZSBlbW9qaS4gKi9cbiAgY291bnQ6IG51bWJlcjtcbiAgLyoqIFNpIGVsIHVzdWFyaW8gYWN0dWFsIHRpZW5lIGFjdGl2YSBlc3RhIHJlYWNjaW9uLiAqL1xuICBhY3RpdmU6IGJvb2xlYW47XG59XG5cbi8qKiBSZWZlcmVuY2lhIGFsIG1lbnNhamUgYWwgcXVlIHNlIHJlc3BvbmRlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZXNzYWdlUmVwbHlUbyB7XG4gIC8qKiBJRCBkZWwgbWVuc2FqZSBvcmlnaW5hbC4gKi9cbiAgbXNnSWQ6IHN0cmluZztcbiAgLyoqIE5vbWJyZSBkZWwgZW1pc29yIGRlbCBtZW5zYWplIG9yaWdpbmFsLiAqL1xuICBzZW5kZXJOYW1lOiBzdHJpbmc7XG4gIC8qKiBUZXh0byBkZWwgbWVuc2FqZSBvcmlnaW5hbCAocHJldmlldykuICovXG4gIGJvZHk6IHN0cmluZztcbn1cblxuLyoqIERvY3VtZW50byBkZSBtZW5zYWplIGVuIEZpcmVzdG9yZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWVzc2FnZSBleHRlbmRzIEZpcmVzdG9yZURvY3VtZW50IHtcbiAgLyoqIElEIGRlbCBlbWlzb3IuICovXG4gIHNlbmRlcklkOiBzdHJpbmc7XG4gIC8qKiBOb21icmUgdmlzaWJsZSBkZWwgZW1pc29yLiAqL1xuICBzZW5kZXJOYW1lOiBzdHJpbmc7XG4gIC8qKiBVUkwgZGVsIGF2YXRhciBkZWwgZW1pc29yIChvcGNpb25hbCkuICovXG4gIHNlbmRlckF2YXRhcj86IHN0cmluZztcbiAgLyoqIEN1ZXJwbyBkZWwgbWVuc2FqZS4gKi9cbiAgYm9keTogc3RyaW5nO1xuICAvKiogVGlwbyBkZSBtZW5zYWplLiAqL1xuICB0eXBlOiBNZXNzYWdlVHlwZTtcbiAgLyoqIEZlY2hhIGRlIGNyZWFjaW9uIGRlbCBtZW5zYWplLiAqL1xuICBjcmVhdGVkQXQ6IERhdGU7XG4gIC8qKiBTaSBlbCBtZW5zYWplIGZ1ZSBlbGltaW5hZG8uICovXG4gIGlzRGVsZXRlZD86IGJvb2xlYW47XG4gIC8qKiBTaSBlbCBtZW5zYWplIGZ1ZSBlZGl0YWRvLiAqL1xuICBpc0VkaXRlZD86IGJvb2xlYW47XG4gIC8qKiBNZW5zYWplIGFsIHF1ZSBzZSByZXNwb25kZS4gKi9cbiAgcmVwbHlUbz86IE1lc3NhZ2VSZXBseVRvO1xuICAvKiogQXJjaGl2b3MgYWRqdW50b3MuICovXG4gIGF0dGFjaG1lbnRzPzogTWVzc2FnZUF0dGFjaG1lbnRbXTtcbiAgLyoqIFJlYWNjaW9uZXMgZGVsIG1lbnNhamUuICovXG4gIHJlYWN0aW9ucz86IE1lc3NhZ2VSZWFjdGlvbltdO1xuICAvKiogRXN0YWRvIGRlIGVudmlvIChwYXJhIG1lbnNhamVzIG9wdGltaXN0YXMgZGVsIGxhZG8gZGVsIGNsaWVudGUpLiAqL1xuICBzdGF0dXM/OiBNZXNzYWdlU3RhdHVzO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFR5cGluZyBpbmRpY2F0b3Jcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogRG9jdW1lbnRvIGRlIFwiZXNjcmliaWVuZG9cIiBlbiBGaXJlc3RvcmUuICovXG5leHBvcnQgaW50ZXJmYWNlIFR5cGluZ0RvY3VtZW50IGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQge1xuICAvKiogTm9tYnJlIHZpc2libGUgZGVsIHVzdWFyaW8gcXVlIGVzdGEgZXNjcmliaWVuZG8uICovXG4gIGRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gIC8qKiBUaW1lc3RhbXAgZGUgbGEgdWx0aW1hIGFjdHVhbGl6YWNpb24uICovXG4gIHVwZGF0ZWRBdDogRGF0ZTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBIVFRQIFJlcXVlc3QgLyBSZXNwb25zZSB0eXBlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKiBSZXF1ZXN0IHBhcmEgY3JlYXIgdW5hIGNvbnZlcnNhY2lvbi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlQ29udmVyc2F0aW9uUmVxdWVzdCB7XG4gIC8qKiBUaXBvIGRlIGNvbnZlcnNhY2lvbi4gKi9cbiAgdHlwZTogQ29udmVyc2F0aW9uVHlwZTtcbiAgLyoqIElEcyBkZSBsb3MgcGFydGljaXBhbnRlcyBpbmljaWFsZXMuICovXG4gIHBhcnRpY2lwYW50SWRzPzogc3RyaW5nW107XG4gIC8qKiBQYXJhIHRpcG8gZW50aXR5OiB0aXBvIGRlIGxhIGVudGlkYWQuICovXG4gIGVudGl0eVR5cGU/OiBzdHJpbmc7XG4gIC8qKiBQYXJhIHRpcG8gZW50aXR5OiBJRCBkZSBsYSBlbnRpZGFkLiAqL1xuICBlbnRpdHlJZD86IHN0cmluZztcbiAgLyoqIFRpdHVsbyAocGFyYSBncnVwb3MpLiAqL1xuICB0aXRsZT86IHN0cmluZztcbn1cblxuLyoqIFJlcXVlc3QgcGFyYSBhY3R1YWxpemFyIHVuYSBjb252ZXJzYWNpb24uICovXG5leHBvcnQgaW50ZXJmYWNlIFVwZGF0ZUNvbnZlcnNhdGlvblJlcXVlc3Qge1xuICAvKiogTnVldm8gdGl0dWxvIChvcGNpb25hbCkuICovXG4gIHRpdGxlPzogc3RyaW5nO1xuICAvKiogTnVldm8gZXN0YWRvIChvcGNpb25hbCkuICovXG4gIHN0YXR1cz86IENvbnZlcnNhdGlvblN0YXR1cztcbn1cblxuLyoqIFJlc3BvbnNlIGRlIGxpc3RhZG8gZGUgY29udmVyc2FjaW9uZXMuICovXG5leHBvcnQgaW50ZXJmYWNlIExpc3RDb252ZXJzYXRpb25zUmVzcG9uc2Uge1xuICAvKiogTGlzdGEgZGUgY29udmVyc2FjaW9uZXMuICovXG4gIGNvbnZlcnNhdGlvbnM6IENvbnZlcnNhdGlvbltdO1xuICAvKiogQ3Vyc29yIHBhcmEgcGFnaW5hY2lvbi4gKi9cbiAgbmV4dEN1cnNvcj86IHN0cmluZztcbiAgLyoqIFNpIGhheSBtYXMgcGFnaW5hcy4gKi9cbiAgaGFzTW9yZTogYm9vbGVhbjtcbn1cbiJdfQ==