vue-wiguet-chatweb 0.1.15 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-wiguet-chatweb",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -28,7 +28,11 @@
28
28
  required
29
29
  ref="textAreaRef"
30
30
  @input="() => autoAdjustHeight()"
31
- @keydown.enter.prevent
31
+ @keydown.enter="
32
+ (event) => {
33
+ !isMovil && event.preventDefault();
34
+ }
35
+ "
32
36
  @keyup.enter="saltoDeLineaOEnviar"
33
37
  />
34
38
 
@@ -43,7 +47,15 @@
43
47
  </template>
44
48
 
45
49
  <script setup lang="ts">
46
- import { ref, onMounted, nextTick, PropType, watch, onUnmounted } from "vue";
50
+ import {
51
+ ref,
52
+ onMounted,
53
+ nextTick,
54
+ PropType,
55
+ watch,
56
+ onUnmounted,
57
+ computed,
58
+ } from "vue";
47
59
  import { v4 as uuidv4 } from "uuid";
48
60
 
49
61
  import {
@@ -109,8 +121,8 @@ const messageContainerRef = ref<HTMLElement | null>(null);
109
121
  watch(
110
122
  () => props.visible,
111
123
  async (current) => {
112
- if(!current) return
113
-
124
+ if (!current) return;
125
+
114
126
  emit("clear-new-messages");
115
127
  scrollToBottom();
116
128
 
@@ -122,18 +134,23 @@ watch(
122
134
 
123
135
  const resp = await getInformationApi(props.tokenAuth);
124
136
 
125
- if(resp) {
137
+ if (resp) {
126
138
  appChatId.value = resp.appChat.id;
127
139
  }
128
140
  }
129
141
  );
130
142
 
131
143
  function saltoDeLineaOEnviar(event: KeyboardEvent) {
144
+ if(isMovil.value) {
145
+ autoAdjustHeight();
146
+ return;
147
+ }
148
+
132
149
  if (event.key === "Enter" && event.shiftKey) {
133
- const val = (event.target as any)?.value || '';
150
+ const val = (event.target as any)?.value || "";
134
151
  (event.target as any).value = val + "\n";
135
- autoAdjustHeight()
136
- return
152
+ autoAdjustHeight();
153
+ return;
137
154
  }
138
155
 
139
156
  submitMessage(event);
@@ -149,7 +166,7 @@ const submitMessage = async (event: Event) => {
149
166
  });
150
167
  return;
151
168
  }
152
-
169
+
153
170
  if (!message.value.trim()) {
154
171
  emit("show-toast", {
155
172
  severity: "warn",
@@ -176,11 +193,11 @@ const submitMessage = async (event: Event) => {
176
193
  msPersonaId: props.user.msPersonaId,
177
194
  },
178
195
  };
179
-
196
+
180
197
  const idx = messagesData.value.data.push(newMessage) - 1;
181
-
182
- sendApi(message.value, appChatId.value).then((newMsg)=>{
183
- if(!newMsg) {
198
+
199
+ sendApi(message.value, appChatId.value).then((newMsg) => {
200
+ if (!newMsg) {
184
201
  messagesData.value.data[idx].error = {
185
202
  error: true,
186
203
  id: newMessage.id,
@@ -194,13 +211,13 @@ const submitMessage = async (event: Event) => {
194
211
  });
195
212
  } else {
196
213
  messagesData.value.data[idx] = newMsg;
197
-
198
- const message = {...newMsg, chatId:newMessage.chatId }
214
+
215
+ const message = { ...newMsg, chatId: newMessage.chatId };
199
216
  socketService.value?.emit(
200
- 'sendMessage',
217
+ "sendMessage",
201
218
  { roomId: information?.value?.appChat.id, message },
202
219
  (response: any) => {
203
- console.log('🚀 ~ socketService.value.emit ~ response:', response);
220
+ console.log("🚀 ~ socketService.value.emit ~ response:", response);
204
221
  }
205
222
  );
206
223
  }
@@ -208,7 +225,7 @@ const submitMessage = async (event: Event) => {
208
225
 
209
226
  message.value = "";
210
227
  scrollToBottom();
211
- textAreaRef.value && (textAreaRef.value.style.height = "20px")
228
+ textAreaRef.value && (textAreaRef.value.style.height = "20px");
212
229
  };
213
230
 
214
231
  const sendApi = async (message: string, appChatId: string) => {
@@ -221,37 +238,35 @@ const sendApi = async (message: string, appChatId: string) => {
221
238
  };
222
239
 
223
240
  const getMessages = async () => {
224
-
225
241
  const lastMessagesId = messagesData.value.data[0]?.id;
226
242
  const body: ListMessageBody = {
227
243
  lastMessagesId,
228
244
  appChatId: appChatId.value,
229
- limit: 10
245
+ limit: 10,
230
246
  };
231
247
 
232
248
  isLoading.value = true;
233
249
  const resp = await getMessagesApi({ body, token: props.tokenAuth });
234
250
  isLoading.value = false;
235
-
251
+
236
252
  messagesData.value.data.unshift(
237
253
  ...resp.data.sort((a, b) => -b.createdAt.localeCompare(a.createdAt))
238
254
  );
239
-
255
+
240
256
  messagesData.value.canLoadMoreMessages =
241
257
  resp.pagination.total > resp.pagination.size;
242
-
258
+
243
259
  if (lastMessagesId && messageContainerRef.value?.scrollHeight) {
244
260
  mantainElementsOnViewport(messageContainerRef.value?.scrollHeight);
245
261
  }
246
-
262
+
247
263
  if (!lastMessagesId) scrollToBottom();
248
264
  };
249
265
 
250
266
  const retryMessage = async (message: Message) => {
251
267
  emit("show-confirm", async () => {
252
-
253
268
  if (!message.error?.id) return;
254
-
269
+
255
270
  const msg = await sendApi(message.message, appChatId.value);
256
271
 
257
272
  if (!msg) {
@@ -267,13 +282,13 @@ const retryMessage = async (message: Message) => {
267
282
  "id",
268
283
  message.error.id
269
284
  );
270
-
285
+
271
286
  messagesData.value.data[idx] = { ...msg, error: undefined };
272
287
 
273
- socketService.value?.emit(
274
- 'sendMessage',
275
- { roomId: information?.value?.appChat.id, message },
276
- );
288
+ socketService.value?.emit("sendMessage", {
289
+ roomId: information?.value?.appChat.id,
290
+ message,
291
+ });
277
292
  }
278
293
 
279
294
  scrollToBottom();
@@ -305,23 +320,28 @@ const fontSpace = 14;
305
320
  function autoAdjustHeight() {
306
321
  if (!textAreaRef.value) return;
307
322
 
308
- textAreaRef.value.style.height = textAreaRef.value.scrollHeight - fontSpace + 'px'
323
+ textAreaRef.value.style.height =
324
+ textAreaRef.value.scrollHeight - fontSpace + "px";
325
+
326
+ if (textAreaRef.value.scrollHeight === textAreaRef.value.clientHeight)
327
+ return;
309
328
 
310
- if(textAreaRef.value.scrollHeight === textAreaRef.value.clientHeight) return;
311
-
312
- textAreaRef.value.style.height = textAreaRef.value.scrollHeight + "px"
329
+ textAreaRef.value.style.height = textAreaRef.value.scrollHeight + "px";
313
330
  }
314
331
 
315
332
  const socketService = ref<Socket>();
316
333
  const information = ref<ChatInformation>();
317
334
 
318
- function connectMsWebSocket (userChat: ChatInformation ,app: APP_TYPE = APP_TYPE.WEBCHAT) {
319
- if (!userChat) throw new Error('user chat is required')
335
+ function connectMsWebSocket(
336
+ userChat: ChatInformation,
337
+ app: APP_TYPE = APP_TYPE.WEBCHAT
338
+ ) {
339
+ if (!userChat) throw new Error("user chat is required");
320
340
 
321
341
  socketService.value = io(window.VITE_SOCKET_URI, {
322
342
  query: {
323
343
  // TODO: confirmar si se quita o no
324
- usuarioId: `${userChat?.chat?.persona?.funcionarioId}`,
344
+ usuarioId: `${userChat?.chat?.persona?.funcionarioId}`,
325
345
  aplicacion: app,
326
346
  },
327
347
  extraHeaders: { Authorization: props.tokenAuth },
@@ -329,24 +349,24 @@ function connectMsWebSocket (userChat: ChatInformation ,app: APP_TYPE = APP_TYPE
329
349
 
330
350
  socketService.value.removeAllListeners();
331
351
 
332
- socketService.value.on('connect', () => {
333
- console.log('Conectado al servidor de sockets');
352
+ socketService.value.on("connect", () => {
353
+ console.log("Conectado al servidor de sockets");
334
354
 
335
- socketService.value?.emit(
336
- 'joinRoom',
337
- `${userChat?.appChat?.id}`
338
- );
339
- })
355
+ socketService.value?.emit("joinRoom", `${userChat?.appChat?.id}`);
356
+ });
340
357
 
341
- socketService.value.on('disconnect', () => {
342
- console.log('Desconectado del servidor de sockets');
358
+ socketService.value.on("disconnect", () => {
359
+ console.log("Desconectado del servidor de sockets");
343
360
  });
344
361
 
345
- socketService.value.on('receiveMessage', (data: any) => {
346
- console.log('Mensaje recibido:', data.message, userChat);
347
-
348
- if (data.message.sender.msPersonaId === userChat?.chat?.persona?.msPersonaId) return
349
-
362
+ socketService.value.on("receiveMessage", (data: any) => {
363
+ console.log("Mensaje recibido:", data.message, userChat);
364
+
365
+ if (
366
+ data.message.sender.msPersonaId === userChat?.chat?.persona?.msPersonaId
367
+ )
368
+ return;
369
+
350
370
  messagesData.value.data.push(data.message);
351
371
  setVistoToTrueApi(data.message.appChatId, props.tokenAuth);
352
372
  scrollToBottom();
@@ -354,17 +374,56 @@ function connectMsWebSocket (userChat: ChatInformation ,app: APP_TYPE = APP_TYPE
354
374
  });
355
375
  }
356
376
 
377
+ const isMovil = computed(() => {
378
+ return [OS.ANDROID, OS.IOS].includes(getOS() as OS);
379
+ });
380
+
381
+ const enum OS {
382
+ ANDROID = "Android",
383
+ IOS = "iPhone",
384
+ }
385
+
386
+ function getOS() {
387
+ const userAgent = window.navigator.userAgent;
388
+ const platform = (window.navigator as any)?.userAgentData?.platform || window.navigator.platform;
389
+ const macosPlatforms = [
390
+ "macOS",
391
+ "Macintosh",
392
+ "MacIntel",
393
+ "MacPPC",
394
+ "Mac68K",
395
+ ];
396
+ const windowsPlatforms = ["Win32", "Win64", "Windows", "WinCE"];
397
+ const iosPlatforms = ["iPhone", "iPad", "iPod"];
398
+
399
+ let os = null;
400
+
401
+ if (macosPlatforms.indexOf(platform) !== -1) {
402
+ os = "Mac OS";
403
+ } else if (iosPlatforms.indexOf(platform) !== -1) {
404
+ os = OS.IOS;
405
+ } else if (windowsPlatforms.indexOf(platform) !== -1) {
406
+ os = "Windows";
407
+ } else if (/Android/.test(userAgent)) {
408
+ os = OS.ANDROID;
409
+ } else if (/Linux/.test(platform)) {
410
+ os = "Linux";
411
+ }
412
+
413
+ return os;
414
+ }
415
+
357
416
  onMounted(async () => {
358
417
  if (appChatId.value) return;
359
-
418
+
360
419
  const resp = await getInformationApi(props.tokenAuth);
361
-
362
- if(!resp) return;
363
-
420
+
421
+ if (!resp) return;
422
+
364
423
  information.value = resp;
365
424
  appChatId.value = resp.appChat.id;
366
425
  notViewed.value = resp.appChat.totalNoVistosCliente;
367
- connectMsWebSocket(resp)
426
+ connectMsWebSocket(resp);
368
427
  getMessages();
369
428
  emit("not-viewed-total", resp.appChat.totalNoVistosCliente);
370
429
  });
@@ -26,7 +26,7 @@
26
26
  <div class="chat-message">
27
27
  <div class="bubble" :class="message.esCliente ? 'right' : 'left'">
28
28
  <div :class="message.esCliente ? 'content-right' : 'content-left'">
29
- <div class="message-text" style="white-space: pre-line" v-html="convertUrlsToLinks(message.message)"></div>
29
+ <div class="message-text" style="white-space: pre-line" v-html="textToRichFormat(message.message)"></div>
30
30
  <div class="detail-message flex justify-content-between">
31
31
  <span class="mr-5" v-if="message.sender?.nombreCompleto">
32
32
  {{
@@ -98,15 +98,43 @@ watch(
98
98
  }
99
99
  );
100
100
 
101
- function convertUrlsToLinks(content:string) {
102
- // Expresión regular para detectar URLs
103
- const urlRegex = /(https?:\/\/[^\s]+)/g;
101
+ type RichTextType = {
102
+ regex: RegExp;
103
+ tag: string;
104
+ };
104
105
 
105
- // Reemplazar las URLs con etiquetas <a>
106
- return content.replace(urlRegex, (url) => {
107
- return `<a href="${url}" target="_blank">${url}</a>`;
108
- });
106
+ const richText: { [key in string]: RichTextType } = {
107
+ BOLD: { regex: /\*(.+?)\*(?!\*)/g, tag: '<strong--custom-tag>{val}</strong--custom-tag>' },
108
+ ITALIC: { regex: /_(.+?)_/, tag: '<i--custom-tag>{val}</i--custom-tag>' },
109
+ CROSSED_OUT: { regex: /~(.+?)~(?!~)/g, tag: '<del--custom-tag>{val}</del--custom-tag>' },
110
+ URL: {
111
+ regex: /(http?s?:\/\/[^\s]+)/g,
112
+ tag: '<a--custom-tag href="{val}" target="_blank">{val}</a--custom-tag>',
113
+ },
114
+ };
115
+
116
+ function textToRichFormat(text: string) {
117
+ const richTextValues = Object.values(richText);
118
+
119
+ if (!richTextValues || (Array.isArray(richTextValues) && richTextValues.length === 0))
120
+ return text;
121
+
122
+ const newMessage = () => {
123
+
124
+ return richTextValues.reduce((textPrev, rtv) => {
125
+ return textPrev.replace(rtv.regex, (middleValueAssert, middleValue) => {
126
+ const regexVerifyExistTag = /--custom-tag/;
127
+
128
+ if (regexVerifyExistTag.test(middleValueAssert)) return middleValueAssert;
129
+
130
+ return rtv.tag.replace(/{val}/g, middleValue);
131
+ });
132
+ }, text);
133
+ };
134
+
135
+ return newMessage().replace(/--custom-tag/g, '');
109
136
  }
137
+
110
138
  </script>
111
139
 
112
140
  <style scoped>