fix: show loading spinner when switching between contact threads

Clear old timeline items immediately on thread switch and display a centered
loader until the new conversation loads, instead of showing stale messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ruslan Bakiev
2026-02-24 21:45:01 +07:00
parent 3ff9120070
commit cb685446a5
2 changed files with 25 additions and 2 deletions

View File

@@ -259,6 +259,7 @@ const {
// ---------------------------------------------------------------------------
const {
clientTimelineItems,
timelineLoading,
timelineContactId,
timelineLimit,
loadClientTimeline,
@@ -1624,6 +1625,12 @@ onBeforeUnmount(() => {
<div v-else-if="selectedCommThread" class="relative flex h-full min-h-0 flex-col">
<div class="comm-thread-surface min-h-0 flex-1 space-y-2 overflow-y-auto px-3 pb-2">
<!-- Loading spinner while timeline is fetching -->
<div v-if="timelineLoading && clientTimelineItems.length === 0" class="flex h-full items-center justify-center">
<span class="loading loading-spinner loading-md text-primary" />
</div>
<template v-else>
<button
class="sticky top-0 z-10 -mx-3 mb-2 flex w-[calc(100%+1.5rem)] items-center gap-2 border-b border-base-300 bg-base-100/80 px-3 py-2 text-left backdrop-blur-sm transition hover:bg-base-100"
@click="commPinnedOnly = !commPinnedOnly"
@@ -1900,6 +1907,7 @@ onBeforeUnmount(() => {
</div>
</div>
</div>
</template>
</div>
<div

View File

@@ -30,9 +30,13 @@ export function useTimeline(opts: { apolloAuthReady: ComputedRef<boolean> }) {
);
const clientTimelineItems = ref<ClientTimelineItem[]>([]);
const timelineLoading = ref(false);
watch(() => timelineResult.value?.getClientTimeline, (v) => {
if (v) clientTimelineItems.value = v as ClientTimelineItem[];
if (v) {
clientTimelineItems.value = v as ClientTimelineItem[];
timelineLoading.value = false;
}
}, { immediate: true });
async function loadClientTimeline(contactId: string, limit = 500) {
@@ -40,18 +44,28 @@ export function useTimeline(opts: { apolloAuthReady: ComputedRef<boolean> }) {
if (!normalizedContactId) {
clientTimelineItems.value = [];
timelineContactId.value = "";
timelineLoading.value = false;
return;
}
// Clear old data immediately and show loader
clientTimelineItems.value = [];
timelineLoading.value = true;
timelineContactId.value = normalizedContactId;
timelineLimit.value = limit;
await refetchTimeline();
try {
await refetchTimeline();
} finally {
timelineLoading.value = false;
}
}
async function refreshSelectedClientTimeline(selectedCommThreadId: string) {
const contactId = String(selectedCommThreadId ?? "").trim();
if (!contactId) {
clientTimelineItems.value = [];
timelineLoading.value = false;
return;
}
await loadClientTimeline(contactId);
@@ -59,6 +73,7 @@ export function useTimeline(opts: { apolloAuthReady: ComputedRef<boolean> }) {
return {
clientTimelineItems,
timelineLoading,
timelineContactId,
timelineLimit,
loadClientTimeline,