- Refinement of the chat client to have better visible clues for user vs chatbot messages
- Introduction of interview_phase and normal phase in TRAICIE_SELECTION_SPECIALIST to make interaction with bot more human. - More and random humanised messages to TRAICIE_SELECTION_SPECIALIST
This commit is contained in:
@@ -7,32 +7,35 @@
|
||||
<slot name="loading"></slot>
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
<div v-if="normalMessages.length === 0" class="empty-state">
|
||||
<div class="empty-icon">💬</div>
|
||||
<div class="empty-text">Nog geen berichten</div>
|
||||
<div class="empty-subtext">Start een gesprek door een bericht te typen!</div>
|
||||
</div>
|
||||
|
||||
<!-- Normal message list (excluding temporarily positioned AI messages) -->
|
||||
<template v-if="normalMessages.length > 0">
|
||||
<!-- Messages -->
|
||||
<template v-for="(message, index) in normalMessages" :key="message.id">
|
||||
<!-- The actual message -->
|
||||
<chat-message
|
||||
:message="message"
|
||||
:is-submitting-form="isSubmittingForm"
|
||||
:api-prefix="apiPrefix"
|
||||
:is-latest-ai-message="isLatestAiMessage(message)"
|
||||
@image-loaded="handleImageLoaded"
|
||||
@specialist-complete="$emit('specialist-complete', $event)"
|
||||
@specialist-error="$emit('specialist-error', $event)"
|
||||
></chat-message>
|
||||
<!-- Messages wrapper for bottom alignment -->
|
||||
<div class="messages-wrapper">
|
||||
<!-- Empty state (only show when no messages) -->
|
||||
<div v-if="normalMessages.length === 0" class="empty-state">
|
||||
<div class="empty-icon">💬</div>
|
||||
<div class="empty-text">Nog geen berichten</div>
|
||||
<div class="empty-subtext">Start een gesprek door een bericht te typen!</div>
|
||||
</div>
|
||||
|
||||
<!-- Normal message list (excluding temporarily positioned AI messages) -->
|
||||
<template v-if="normalMessages.length > 0">
|
||||
<!-- Messages -->
|
||||
<template v-for="(message, index) in normalMessages" :key="message.id">
|
||||
<!-- The actual message -->
|
||||
<chat-message
|
||||
:message="message"
|
||||
:is-submitting-form="isSubmittingForm"
|
||||
:api-prefix="apiPrefix"
|
||||
:is-latest-ai-message="isLatestAiMessage(message)"
|
||||
@image-loaded="handleImageLoaded"
|
||||
@specialist-complete="$emit('specialist-complete', $event)"
|
||||
@specialist-error="$emit('specialist-error', $event)"
|
||||
></chat-message>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- Typing indicator -->
|
||||
<typing-indicator v-if="isTyping"></typing-indicator>
|
||||
|
||||
<!-- Typing indicator -->
|
||||
<typing-indicator v-if="isTyping"></typing-indicator>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -96,14 +99,20 @@ export default {
|
||||
watch: {
|
||||
messages: {
|
||||
handler(newMessages, oldMessages) {
|
||||
// Auto-scroll when new messages are added
|
||||
if (this.autoScroll && newMessages.length > (oldMessages?.length || 0)) {
|
||||
const hasNewMessages = newMessages.length > (oldMessages?.length || 0);
|
||||
|
||||
// Always auto-scroll when new messages are added (regardless of current scroll position)
|
||||
if (this.autoScroll && hasNewMessages) {
|
||||
// Double $nextTick for better DOM update synchronization
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom();
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
deep: true,
|
||||
immediate: false
|
||||
},
|
||||
isTyping(newVal) {
|
||||
if (newVal && this.autoScroll) {
|
||||
@@ -188,13 +197,16 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
scrollToBottom() {
|
||||
scrollToBottom(force = false) {
|
||||
const container = this.$refs.messagesContainer;
|
||||
if (container) {
|
||||
container.scrollTop = container.scrollHeight;
|
||||
this.isAtBottom = true;
|
||||
this.showScrollButton = false;
|
||||
this.unreadCount = 0;
|
||||
// Use requestAnimationFrame for better timing
|
||||
requestAnimationFrame(() => {
|
||||
container.scrollTop = container.scrollHeight;
|
||||
this.isAtBottom = true;
|
||||
this.showScrollButton = false;
|
||||
this.unreadCount = 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -209,7 +221,7 @@ export default {
|
||||
const container = this.$refs.messagesContainer;
|
||||
if (!container) return;
|
||||
|
||||
const threshold = 100; // pixels from bottom
|
||||
const threshold = 50; // Reduced threshold for better detection
|
||||
const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < threshold;
|
||||
|
||||
this.isAtBottom = isNearBottom;
|
||||
@@ -221,7 +233,7 @@ export default {
|
||||
},
|
||||
|
||||
handleImageLoaded() {
|
||||
// Auto-scroll when images load to maintain position
|
||||
// Auto-scroll when img load to maintain position
|
||||
if (this.isAtBottom) {
|
||||
this.$nextTick(() => this.scrollToBottom());
|
||||
}
|
||||
@@ -273,8 +285,19 @@ export default {
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
scroll-behavior: smooth;
|
||||
|
||||
/* Bottom-aligned messages implementation */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.messages-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px; /* Space between messages */
|
||||
}
|
||||
|
||||
.load-more-indicator {
|
||||
text-align: center;
|
||||
|
||||
Reference in New Issue
Block a user