vue-wiguet-chatweb 0.1.14 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-wiguet-chatweb",
3
- "version": "0.1.14",
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>
@@ -7,6 +7,7 @@
7
7
  id="chat-circle"
8
8
  class="widget-container"
9
9
  v-if="props.tokenAuth.length > 10"
10
+ v-show="!isChatBoxVisible"
10
11
  >
11
12
  <div class="container-buttons-chat" :class="{'active': toggleButtonsChats}">
12
13
  <a href="javascript:;" class="button whatsapp" @click="go(MeansCommunication.WHATSAPP)">