feat: add separate typing indicator

This commit is contained in:
Shivam Mishra
2025-03-17 17:03:37 +05:30
parent 2759954897
commit 9aee8d1a1f
4 changed files with 63 additions and 77 deletions
@@ -0,0 +1,59 @@
<script setup>
import { useFunctionGetter, useMapGetter } from 'dashboard/composables/store';
import { useI18n } from 'vue-i18n';
import { computed } from 'vue';
const { $t } = useI18n();
const getTypingUsersText = (users = []) => {
const count = users.length;
const [firstUser, secondUser] = users;
if (count === 1) {
return $t('TYPING.ONE', { user: firstUser.name });
}
if (count === 2) {
return $t('TYPING.TWO', {
user: firstUser.name,
secondUser: secondUser.name,
});
}
return $t('TYPING.MULTIPLE', { user: firstUser.name, count: count - 1 });
};
const currentChat = useMapGetter('getSelectedChat');
const typingUsersList = useFunctionGetter(
'conversationTypingStatus/getUserList',
currentChat.value.id
);
const isAnyoneTyping = computed(() => {
return true;
// return typingUsersList.value.length !== 0;
});
const typingUserNames = computed(() => {
if (typingUsersList.value.length) {
return getTypingUsersText(typingUsersList.value);
}
return 'Shivam Mishra is typing';
});
</script>
<template>
<div v-show="isAnyoneTyping">
<div
v-if="isAnyoneTyping"
class="flex py-1.5 pr-2 pl-3 rounded-full shadow-sm border border-n-weak bg-n-solid-2 text-xs font-semibold my-2.5 mx-auto"
>
{{ typingUserNames }}
<img
class="w-6 ltr:ml-2 rtl:mr-2"
src="assets/images/typing.gif"
alt="Someone is typing"
/>
</div>
</div>
</template>
@@ -10,6 +10,7 @@ import { useMapGetter } from 'dashboard/composables/store';
import ReplyBox from './ReplyBox.vue';
import Message from './Message.vue';
import NextMessageList from 'next/message/MessageList.vue';
import TypingIndicator from 'next/Conversation/Chips/TypingIndicator.vue';
import ConversationLabelSuggestion from './conversation/LabelSuggestion.vue';
import Banner from 'dashboard/components/ui/Banner.vue';
@@ -21,7 +22,6 @@ import inboxMixin, { INBOX_FEATURES } from 'shared/mixins/inboxMixin';
// utils
import { emitter } from 'shared/helpers/mitt';
import { getTypingUsersText } from '../../../helper/commons';
import { calculateScrollTop } from './helpers/scrollTopCalculationHelper';
import { LocalStorage } from 'shared/helpers/localStorage';
import {
@@ -42,6 +42,7 @@ export default {
Message,
NextMessageList,
ReplyBox,
TypingIndicator,
Banner,
ConversationLabelSuggestion,
},
@@ -142,25 +143,6 @@ export default {
inbox() {
return this.$store.getters['inboxes/getInbox'](this.inboxId);
},
typingUsersList() {
const userList = this.$store.getters[
'conversationTypingStatus/getUserList'
](this.currentChat.id);
return userList;
},
isAnyoneTyping() {
const userList = this.typingUsersList;
return userList.length !== 0;
},
typingUserNames() {
const userList = this.typingUsersList;
if (this.isAnyoneTyping) {
const [i18nKey, params] = getTypingUsersText(userList);
return this.$t(i18nKey, params);
}
return '';
},
getMessages() {
const messages = this.currentChat.messages || [];
if (this.isAWhatsAppChannel) {
@@ -613,19 +595,9 @@ export default {
}"
>
<div
v-if="isAnyoneTyping"
class="absolute flex items-center w-full h-0 -top-7"
class="flex items-center justify-center gap-1 absolute w-full -top-7 h-0"
>
<div
class="flex py-2 pr-4 pl-5 shadow-md rounded-full bg-white dark:bg-slate-700 text-n-slate-11 text-xs font-semibold my-2.5 mx-auto"
>
{{ typingUserNames }}
<img
class="w-6 ltr:ml-2 rtl:mr-2"
src="assets/images/typing.gif"
alt="Someone is typing"
/>
</div>
<TypingIndicator />
</div>
<ReplyBox
v-model:popout-reply-box="isPopOutReplyBox"
@@ -25,24 +25,6 @@ export const isJSONValid = value => {
return true;
};
export const getTypingUsersText = (users = []) => {
const count = users.length;
const [firstUser, secondUser] = users;
if (count === 1) {
return ['TYPING.ONE', { user: firstUser.name }];
}
if (count === 2) {
return [
'TYPING.TWO',
{ user: firstUser.name, secondUser: secondUser.name },
];
}
return ['TYPING.MULTIPLE', { user: firstUser.name, count: count - 1 }];
};
export const createPendingMessage = data => {
const timestamp = Math.floor(new Date().getTime() / 1000);
const tempMessageId = getUuid();
@@ -1,37 +1,10 @@
import {
getTypingUsersText,
createPendingMessage,
convertToAttributeSlug,
convertToCategorySlug,
convertToPortalSlug,
} from '../commons';
describe('#getTypingUsersText', () => {
it('returns the correct text is there is only one typing user', () => {
expect(getTypingUsersText([{ name: 'Pranav' }])).toEqual([
'TYPING.ONE',
{ user: 'Pranav' },
]);
});
it('returns the correct text is there are two typing users', () => {
expect(
getTypingUsersText([{ name: 'Pranav' }, { name: 'Nithin' }])
).toEqual(['TYPING.TWO', { user: 'Pranav', secondUser: 'Nithin' }]);
});
it('returns the correct text is there are more than two users are typing', () => {
expect(
getTypingUsersText([
{ name: 'Pranav' },
{ name: 'Nithin' },
{ name: 'Subin' },
{ name: 'Sojan' },
])
).toEqual(['TYPING.MULTIPLE', { user: 'Pranav', count: 3 }]);
});
});
describe('#createPendingMessage', () => {
const message = {
message: 'hi',