valtech-components 4.0.227 → 4.0.228

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 (27) hide show
  1. package/esm2022/lib/components/molecules/chat-input/chat-input.component.mjs +9 -1
  2. package/esm2022/lib/components/molecules/message-bubble/message-bubble.component.mjs +191 -274
  3. package/esm2022/lib/components/molecules/typing-indicator/typing-indicator.component.mjs +12 -11
  4. package/esm2022/lib/components/organisms/chat-window/chat-window.component.mjs +203 -216
  5. package/esm2022/lib/components/organisms/thread-panel/thread-panel.component.mjs +10 -10
  6. package/esm2022/lib/services/chat/conversation.service.mjs +14 -37
  7. package/esm2022/lib/services/chat/types.mjs +1 -1
  8. package/esm2022/lib/services/i18n/default-content.mjs +1 -5
  9. package/esm2022/lib/shared/utils/datetime.mjs +1 -54
  10. package/esm2022/lib/version.mjs +2 -2
  11. package/esm2022/public-api.mjs +2 -4
  12. package/fesm2022/valtech-components.mjs +428 -1080
  13. package/fesm2022/valtech-components.mjs.map +1 -1
  14. package/lib/components/molecules/message-bubble/message-bubble.component.d.ts +32 -34
  15. package/lib/components/molecules/typing-indicator/typing-indicator.component.d.ts +4 -5
  16. package/lib/components/organisms/chat-window/chat-window.component.d.ts +56 -52
  17. package/lib/services/chat/conversation.service.d.ts +5 -12
  18. package/lib/services/chat/types.d.ts +52 -86
  19. package/lib/shared/utils/datetime.d.ts +0 -19
  20. package/lib/version.d.ts +1 -1
  21. package/package.json +1 -1
  22. package/public-api.d.ts +1 -3
  23. package/src/lib/services/firebase/firebase-messaging-sw.js +125 -70
  24. package/esm2022/lib/components/molecules/chat-composer/chat-composer.component.mjs +0 -391
  25. package/esm2022/lib/components/molecules/conversation-list-item/conversation-list-item.component.mjs +0 -108
  26. package/lib/components/molecules/chat-composer/chat-composer.component.d.ts +0 -63
  27. package/lib/components/molecules/conversation-list-item/conversation-list-item.component.d.ts +0 -30
@@ -1,90 +1,145 @@
1
1
  /**
2
- * firebase-messaging-sw.js Service Worker estatico de valtech-components.
2
+ * Firebase Messaging Service Worker
3
3
  *
4
- * NO EDITAR en el consumer. Este archivo se publica con la libreria y se copia a
5
- * la raiz del sitio via el glob de angular.json:
4
+ * Service Worker estático para Firebase Cloud Messaging.
5
+ * Carga la configuración dinámicamente desde /firebase-config.js.
6
6
  *
7
- * { "glob": "firebase-messaging-sw.js",
8
- * "input": "node_modules/valtech-components/src/lib/services/firebase",
9
- * "output": "/" }
7
+ * CONFIGURACIÓN:
8
+ * 1. Crea firebase.config.json con tu configuración de Firebase
9
+ * 2. Ejecuta: npm run generate:firebase-config
10
+ * Esto genera /firebase-config.js con: self.FIREBASE_CONFIG = {...}
11
+ * 3. Agrega este SW y firebase-config.js a los assets de angular.json
10
12
  *
11
- * Lee la config de Firebase desde /firebase-config.js (self.FIREBASE_CONFIG),
12
- * generado en build-time por `npx valtech-firebase-config`. Maneja:
13
- * - mensajes en background (FCM) → muestra la notificacion del sistema.
14
- * - click en la notificacion → enfoca/abre la app y postMessage NOTIFICATION_CLICK
15
- * al cliente (lo consume MessagingService.onNotificationClick()).
13
+ * Ver README.md para documentación completa.
16
14
  */
17
15
 
18
- /* eslint-disable no-undef */
16
+ // Importar Firebase scripts
17
+ importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js');
18
+ importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js');
19
19
 
20
- // SDK compat de Firebase (debe coincidir con la major del peer dep firebase ^10).
21
- importScripts(
22
- 'https://www.gstatic.com/firebasejs/10.14.1/firebase-app-compat.js'
23
- );
24
- importScripts(
25
- 'https://www.gstatic.com/firebasejs/10.14.1/firebase-messaging-compat.js'
26
- );
27
-
28
- // Config inyectada en build-time (self.FIREBASE_CONFIG).
20
+ // Importar configuración desde archivo externo (generado en build)
21
+ // Este archivo define: self.FIREBASE_CONFIG = { ... }
29
22
  try {
30
23
  importScripts('/firebase-config.js');
31
- } catch (err) {
32
- // Sin config no se puede inicializar; los push no funcionaran pero el SW
33
- // no debe romper el registro de la app.
34
- console.error('[firebase-messaging-sw] no se pudo cargar /firebase-config.js', err);
24
+ } catch (e) {
25
+ console.error('[SW] No se pudo cargar firebase-config.js:', e);
35
26
  }
36
27
 
37
- if (self.FIREBASE_CONFIG) {
28
+ // Verificar que la configuración existe
29
+ if (!self.FIREBASE_CONFIG) {
30
+ console.error('[SW] FIREBASE_CONFIG no está definido.');
31
+ console.error('[SW] Ejecuta: npm run generate:firebase-config');
32
+ } else {
33
+ // Inicializar Firebase
38
34
  firebase.initializeApp(self.FIREBASE_CONFIG);
35
+
36
+ // Obtener instancia de messaging
39
37
  const messaging = firebase.messaging();
40
38
 
41
- // Mensaje recibido con la app en background o cerrada.
39
+ /**
40
+ * Handler para mensajes en background.
41
+ */
42
42
  messaging.onBackgroundMessage((payload) => {
43
- const notification = payload.notification || {};
43
+ console.log('[SW] Mensaje recibido en background:', payload);
44
+
45
+ // Web push usa mensajes data-only (sin bloque `notification`) para que el
46
+ // navegador NO auto-muestre una notificación duplicada — el SW es el único
47
+ // que la pinta. Title/body/icon llegan dentro de `data`. Se mantiene el
48
+ // fallback a `payload.notification` por compatibilidad con mensajes
49
+ // legacy o nativos que sí traen el bloque.
44
50
  const data = payload.data || {};
45
- const title = notification.title || data.title || 'Notificacion';
46
- const options = {
47
- body: notification.body || data.body || '',
48
- icon: notification.icon || data.icon || '/assets/icons/icon-192.png',
49
- badge: '/assets/icons/icon-96.png',
50
- data,
51
+ const notificationTitle =
52
+ payload.notification?.title || data.title || 'Nueva notificación';
53
+ const notificationBody = payload.notification?.body || data.body || '';
54
+ const notificationIcon =
55
+ payload.notification?.icon || data.icon || '/assets/icon/favicon.ico';
56
+
57
+ const notificationOptions = {
58
+ body: notificationBody,
59
+ icon: notificationIcon,
60
+ image: payload.notification?.image,
61
+ badge: '/assets/icon/badge.png',
62
+ tag: payload.messageId || data.messageId || 'default',
63
+ data: {
64
+ ...data,
65
+ messageId: payload.messageId || data.messageId,
66
+ title: notificationTitle,
67
+ body: notificationBody,
68
+ },
69
+ vibrate: [200, 100, 200],
70
+ requireInteraction: data.require_interaction === 'true',
51
71
  };
52
- self.registration.showNotification(title, options);
72
+
73
+ return self.registration.showNotification(notificationTitle, notificationOptions);
53
74
  });
54
- }
55
75
 
56
- // Click en la notificacion: enfocar un cliente existente (o abrir uno nuevo) y
57
- // avisarle para que navegue. El cliente resuelve la ruta desde data.route.
58
- self.addEventListener('notificationclick', (event) => {
59
- event.notification.close();
60
-
61
- const data = event.notification.data || {};
62
- const route = data.route || data.actionRoute || '/';
63
-
64
- event.waitUntil(
65
- self.clients
66
- .matchAll({ type: 'window', includeUncontrolled: true })
67
- .then((clientList) => {
68
- const message = {
69
- type: 'NOTIFICATION_CLICK',
70
- notification: {
71
- title: event.notification.title,
72
- body: event.notification.body,
73
- data,
74
- },
75
- };
76
-
77
- for (const client of clientList) {
78
- if ('focus' in client) {
79
- client.postMessage(message);
80
- return client.focus();
76
+ /**
77
+ * Handler para clicks en notificaciones.
78
+ */
79
+ self.addEventListener('notificationclick', (event) => {
80
+ console.log('[SW] Click en notificación:', event);
81
+ event.notification.close();
82
+
83
+ const data = event.notification.data || {};
84
+ let targetUrl = '/';
85
+
86
+ if (data.route) {
87
+ targetUrl = data.route;
88
+ } else if (data.url) {
89
+ targetUrl = data.url;
90
+ }
91
+
92
+ if (data.query_params) {
93
+ const separator = targetUrl.includes('?') ? '&' : '?';
94
+ targetUrl += separator + data.query_params;
95
+ }
96
+
97
+ const notificationPayload = {
98
+ type: 'NOTIFICATION_CLICK',
99
+ notification: {
100
+ title: data.title,
101
+ body: data.body,
102
+ data: data,
103
+ messageId: data.messageId,
104
+ },
105
+ };
106
+
107
+ event.waitUntil(
108
+ clients
109
+ .matchAll({ type: 'window', includeUncontrolled: true })
110
+ .then((clientList) => {
111
+ // Siempre enviar postMessage para que la app pueda reaccionar
112
+ for (const client of clientList) {
113
+ client.postMessage(notificationPayload);
114
+ }
115
+
116
+ // Navegar si hay route o url
117
+ if (targetUrl !== '/') {
118
+ for (const client of clientList) {
119
+ if ('navigate' in client) {
120
+ return client.navigate(targetUrl).then((c) => c?.focus());
121
+ }
122
+ }
123
+ // Si no hay cliente abierto, abrir nueva ventana
124
+ if (clients.openWindow) {
125
+ return clients.openWindow(targetUrl);
126
+ }
127
+ }
128
+
129
+ // Solo hacer focus si no hay navegación
130
+ for (const client of clientList) {
131
+ if ('focus' in client) {
132
+ return client.focus();
133
+ }
81
134
  }
82
- }
83
-
84
- if (self.clients.openWindow) {
85
- return self.clients.openWindow(route);
86
- }
87
- return undefined;
88
- })
89
- );
90
- });
135
+ if (clients.openWindow) {
136
+ return clients.openWindow('/');
137
+ }
138
+ })
139
+ );
140
+ });
141
+
142
+ self.addEventListener('notificationclose', (event) => {
143
+ console.log('[SW] Notificación cerrada:', event.notification.tag);
144
+ });
145
+ }