@webitel/ui-chats 0.1.26 → 0.1.28
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 +1 -1
- package/src/ui/messaging/components/chat-observer.vue +7 -4
- package/src/ui/messaging/components/the-messages-container.vue +7 -1
- package/src/ui/messaging/composables/useChatScroll.ts +47 -1
- package/src/ui/messaging/modules/message/components/chat-message.vue +3 -1
- package/types/ui/messaging/components/chat-observer.vue.d.ts +2 -2
- package/types/ui/messaging/composables/useChatScroll.d.ts +2 -1
package/package.json
CHANGED
|
@@ -2,23 +2,24 @@
|
|
|
2
2
|
<div class="chat-observer">
|
|
3
3
|
<wt-intersection-observer
|
|
4
4
|
:can-load-more="props.next"
|
|
5
|
-
:loading="props.
|
|
5
|
+
:loading="props.loading"
|
|
6
6
|
@next="emit(ChatAction.LoadNextMessages)"
|
|
7
7
|
/>
|
|
8
8
|
</div>
|
|
9
9
|
</template>
|
|
10
10
|
|
|
11
11
|
<script setup lang="ts">
|
|
12
|
+
import { WtIntersectionObserver } from '@webitel/ui-sdk/components';
|
|
12
13
|
import { ChatAction } from '../../chat-footer/modules/user-input/enums/ChatAction.enum';
|
|
13
14
|
|
|
14
15
|
const props = withDefaults(
|
|
15
16
|
defineProps<{
|
|
16
17
|
next?: boolean;
|
|
17
|
-
|
|
18
|
+
loading?: boolean;
|
|
18
19
|
}>(),
|
|
19
20
|
{
|
|
20
21
|
next: false,
|
|
21
|
-
|
|
22
|
+
loading: false,
|
|
22
23
|
},
|
|
23
24
|
);
|
|
24
25
|
|
|
@@ -34,6 +35,8 @@ const emit = defineEmits<(e: typeof ChatAction.LoadNextMessages) => void>();
|
|
|
34
35
|
/* @author ye.pohranichna */
|
|
35
36
|
/* to place observer at the bottom of observer wrapper (closer to messages) */
|
|
36
37
|
display: flex;
|
|
37
|
-
|
|
38
|
+
flex-direction: column;
|
|
39
|
+
align-items: center;
|
|
40
|
+
justify-content: flex-end;
|
|
38
41
|
}
|
|
39
42
|
</style>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
v-if="props.next"
|
|
14
14
|
:next="props.next"
|
|
15
15
|
:loading="props.isLoading"
|
|
16
|
-
@[ChatAction.LoadNextMessages]="
|
|
16
|
+
@[ChatAction.LoadNextMessages]="handleLoadNextMessages"
|
|
17
17
|
/>
|
|
18
18
|
<chat-message
|
|
19
19
|
v-for="(message, index) of props.messages"
|
|
@@ -94,13 +94,19 @@ const {
|
|
|
94
94
|
showScrollToBottomBtn,
|
|
95
95
|
newUnseenMessagesCount,
|
|
96
96
|
scrollToBottom,
|
|
97
|
+
loadNextMessages,
|
|
97
98
|
handleChatScroll,
|
|
98
99
|
handleChatResize,
|
|
99
100
|
} = useChatScroll(
|
|
100
101
|
messagesContainer,
|
|
101
102
|
computed(() => props.messages), // props values reactivity https://stackoverflow.com/questions/72408463/use-props-in-composables-vue3 @author ye.pohranichna
|
|
103
|
+
computed(() => props.isLoading),
|
|
102
104
|
);
|
|
103
105
|
|
|
106
|
+
function handleLoadNextMessages() {
|
|
107
|
+
loadNextMessages(props.next, () => emit(ChatAction.LoadNextMessages));
|
|
108
|
+
}
|
|
109
|
+
|
|
104
110
|
function focusOnInput() {
|
|
105
111
|
uiChatsEmitter?.on('focusOnTextField', focus);
|
|
106
112
|
}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { useScroll } from '@vueuse/core';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type ComputedRef,
|
|
4
|
+
computed,
|
|
5
|
+
nextTick,
|
|
6
|
+
type Ref,
|
|
7
|
+
ref,
|
|
8
|
+
watch,
|
|
9
|
+
} from 'vue';
|
|
3
10
|
|
|
4
11
|
import type { ChatMessageType } from '../types/ChatMessage.types';
|
|
5
12
|
|
|
6
13
|
export const useChatScroll = (
|
|
7
14
|
element: Ref<HTMLElement | null> = null,
|
|
8
15
|
messages: Ref<ChatMessageType[]> | ComputedRef<ChatMessageType[]>,
|
|
16
|
+
isLoading?: Ref<boolean> | ComputedRef<boolean>,
|
|
9
17
|
) => {
|
|
10
18
|
/* @author ye.pohranichna
|
|
11
19
|
why 136px? because: https://webitel.atlassian.net/browse/WTEL-7136 */
|
|
@@ -17,6 +25,8 @@ export const useChatScroll = (
|
|
|
17
25
|
/* @author ye.pohranichna
|
|
18
26
|
the distance where the scrollToBottomBtn must be shown/hide. */
|
|
19
27
|
const threshold = ref<number>(defaultThreshold);
|
|
28
|
+
const isLoadingNextMessages = ref<boolean>(false);
|
|
29
|
+
const lastVisibleMessageEl = ref<HTMLElement | null>(null);
|
|
20
30
|
|
|
21
31
|
const isLastMessageIsMy = computed<boolean>(
|
|
22
32
|
() => lastMessage.value?.member?.self,
|
|
@@ -80,6 +90,25 @@ export const useChatScroll = (
|
|
|
80
90
|
showScrollToBottomBtn.value = false;
|
|
81
91
|
};
|
|
82
92
|
|
|
93
|
+
const getTopMessageEl = () => {
|
|
94
|
+
// help to fix chat viewing position when new messages was loaded
|
|
95
|
+
if (!element.value?.children) return;
|
|
96
|
+
lastVisibleMessageEl.value =
|
|
97
|
+
element.value?.getElementsByClassName('chat-message')[0] ?? null;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const loadNextMessages = (
|
|
101
|
+
canLoadMore: boolean | undefined,
|
|
102
|
+
onLoadNextMessages: () => void,
|
|
103
|
+
) => {
|
|
104
|
+
if (isLoadingNextMessages.value || isLoading?.value || !canLoadMore) return;
|
|
105
|
+
|
|
106
|
+
isLoadingNextMessages.value = true;
|
|
107
|
+
getTopMessageEl();
|
|
108
|
+
|
|
109
|
+
onLoadNextMessages();
|
|
110
|
+
};
|
|
111
|
+
|
|
83
112
|
watch(
|
|
84
113
|
() => messages.value?.length,
|
|
85
114
|
(newValue, oldValue) => {
|
|
@@ -91,10 +120,27 @@ export const useChatScroll = (
|
|
|
91
120
|
},
|
|
92
121
|
);
|
|
93
122
|
|
|
123
|
+
watch(
|
|
124
|
+
() => isLoading?.value,
|
|
125
|
+
async (loading) => {
|
|
126
|
+
if (loading || !isLoadingNextMessages.value) return;
|
|
127
|
+
|
|
128
|
+
await nextTick();
|
|
129
|
+
|
|
130
|
+
element.value?.scrollTo({
|
|
131
|
+
top: lastVisibleMessageEl.value?.offsetTop,
|
|
132
|
+
behavior: 'auto',
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
isLoadingNextMessages.value = false;
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
|
|
94
139
|
return {
|
|
95
140
|
showScrollToBottomBtn,
|
|
96
141
|
newUnseenMessagesCount,
|
|
97
142
|
scrollToBottom,
|
|
143
|
+
loadNextMessages,
|
|
98
144
|
handleChatScroll,
|
|
99
145
|
handleChatResize,
|
|
100
146
|
};
|
|
@@ -108,7 +108,9 @@ const isSelfSide = computed<boolean>(
|
|
|
108
108
|
const isBot = computed<boolean>(() => props.message.member?.type === 'bot');
|
|
109
109
|
|
|
110
110
|
const getClientUsername = computed<string>(() => {
|
|
111
|
-
|
|
111
|
+
if (isSelfSide.value) return isSelfSide?.value;
|
|
112
|
+
|
|
113
|
+
return props.username || props.message.member?.name;
|
|
112
114
|
});
|
|
113
115
|
|
|
114
116
|
function handlePlayerInitialize(player) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
next?: boolean;
|
|
3
|
-
|
|
3
|
+
loading?: boolean;
|
|
4
4
|
};
|
|
5
5
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
6
6
|
loadNextMessages: () => any;
|
|
@@ -8,7 +8,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
8
8
|
onLoadNextMessages?: () => any;
|
|
9
9
|
}>, {
|
|
10
10
|
next: boolean;
|
|
11
|
-
|
|
11
|
+
loading: boolean;
|
|
12
12
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
13
13
|
declare const _default: typeof __VLS_export;
|
|
14
14
|
export default _default;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type ComputedRef, type Ref } from 'vue';
|
|
2
2
|
import type { ChatMessageType } from '../types/ChatMessage.types';
|
|
3
|
-
export declare const useChatScroll: (element: Ref<HTMLElement | null>, messages: Ref<ChatMessageType[]> | ComputedRef<ChatMessageType[]>) => {
|
|
3
|
+
export declare const useChatScroll: (element: Ref<HTMLElement | null>, messages: Ref<ChatMessageType[]> | ComputedRef<ChatMessageType[]>, isLoading?: Ref<boolean> | ComputedRef<boolean>) => {
|
|
4
4
|
showScrollToBottomBtn: Ref<boolean, boolean>;
|
|
5
5
|
newUnseenMessagesCount: Ref<number, number>;
|
|
6
6
|
scrollToBottom: (behavior?: ScrollBehavior) => void;
|
|
7
|
+
loadNextMessages: (canLoadMore: boolean | undefined, onLoadNextMessages: () => void) => void;
|
|
7
8
|
handleChatScroll: () => void;
|
|
8
9
|
handleChatResize: () => void;
|
|
9
10
|
};
|