|
|
@@ -48,15 +48,6 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
-
|
|
|
- <!-- Typing Indicator -->
|
|
|
- <div v-if="isOtherPartyTyping" class="flex justify-start mb-2 animate-in fade-in zoom-in duration-300">
|
|
|
- <div class="bg-secondary/60 text-muted-foreground px-4 py-3 rounded-2xl rounded-bl-md flex items-center gap-1.5 shadow-sm">
|
|
|
- <span class="w-1.5 h-1.5 bg-foreground/40 rounded-full animate-bounce" style="animation-delay: 0ms"></span>
|
|
|
- <span class="w-1.5 h-1.5 bg-foreground/40 rounded-full animate-bounce" style="animation-delay: 150ms"></span>
|
|
|
- <span class="w-1.5 h-1.5 bg-foreground/40 rounded-full animate-bounce" style="animation-delay: 300ms"></span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
</div>
|
|
|
|
|
|
<!-- Input area -->
|
|
|
@@ -68,7 +59,7 @@
|
|
|
rows="1"
|
|
|
class="flex-1 resize-none bg-background/80 border border-border/50 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary/40 transition-all placeholder:text-muted-foreground/50 max-h-[80px] overflow-y-auto"
|
|
|
@keydown.enter.exact.prevent="handleSend"
|
|
|
- @input="onTextareaInput($event); autoResize($event)"
|
|
|
+ @input="autoResize($event)"
|
|
|
ref="textareaRef"
|
|
|
/>
|
|
|
<button
|
|
|
@@ -112,8 +103,6 @@ const wsConnected = ref(false);
|
|
|
const messagesContainer = ref<HTMLElement | null>(null);
|
|
|
const textareaRef = ref<HTMLTextAreaElement | null>(null);
|
|
|
const otherPartyOnline = ref(false);
|
|
|
-const isOtherPartyTyping = ref(false);
|
|
|
-let typingTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
|
let cooldownInterval: ReturnType<typeof setInterval> | null = null;
|
|
|
|
|
|
function startCooldown() {
|
|
|
@@ -155,16 +144,6 @@ function connectWebSocket() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (msg.type === "typing" || msg.type === "stop_typing") {
|
|
|
- const myRole = authStore.user?.role === 'admin' ? 'admin' : 'user';
|
|
|
- const isFromOther = (msg.is_admin && myRole === 'user') || (!msg.is_admin && myRole === 'admin');
|
|
|
- if (isFromOther) {
|
|
|
- isOtherPartyTyping.value = (msg.type === "typing");
|
|
|
- scrollToBottom();
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
// If it's a message (type 'message' or has essential fields)
|
|
|
if (msg.type === "message" || (msg.message && msg.id)) {
|
|
|
// Use lenient comparison (==) for ID to avoid string/int mismatches
|
|
|
@@ -270,18 +249,6 @@ function autoResize(e: Event) {
|
|
|
el.style.height = Math.min(el.scrollHeight, 80) + "px";
|
|
|
}
|
|
|
|
|
|
-function onTextareaInput(e: Event) {
|
|
|
- if (wsConnected.value && ws) {
|
|
|
- ws.send("typing");
|
|
|
- if (typingTimeout) clearTimeout(typingTimeout);
|
|
|
- typingTimeout = setTimeout(() => {
|
|
|
- if (ws && ws.readyState === WebSocket.OPEN) {
|
|
|
- ws.send("stop_typing");
|
|
|
- }
|
|
|
- }, 2000);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
function formatTime(dt: string) {
|
|
|
if (!dt) return "";
|
|
|
const d = new Date(dt);
|