Fix session replay: fetch newest messages from tail, not oldest from start

This commit is contained in:
Hermes
2026-04-09 21:46:21 -05:00
parent a125e38d07
commit 7405d15200
3 changed files with 13 additions and 10 deletions
+8 -5
View File
@@ -26,7 +26,10 @@ export default function SessionReplayPage({ params }: { params: Promise<{ id: st
const [titleDraft, setTitleDraft] = useState(""); const [titleDraft, setTitleDraft] = useState("");
const { data: sessionData } = useSession(id); const { data: sessionData } = useSession(id);
const [msgLimit, setMsgLimit] = useState(100); const [msgLimit, setMsgLimit] = useState(100);
const { data: messagesData, isLoading } = useMessages(id, msgLimit); // Fetch from the tail: offset = max(0, total - limit)
const msgTotal = sessionData?.session?.message_count || 0;
const msgOffset = Math.max(0, msgTotal - msgLimit);
const { data: messagesData, isLoading } = useMessages(id, msgLimit, msgOffset);
const [input, setInput] = useState(""); const [input, setInput] = useState("");
const [sending, setSending] = useState(false); const [sending, setSending] = useState(false);
const [pendingMsg, setPendingMsg] = useState<string | null>(null); const [pendingMsg, setPendingMsg] = useState<string | null>(null);
@@ -41,7 +44,7 @@ export default function SessionReplayPage({ params }: { params: Promise<{ id: st
useEffect(() => { useEffect(() => {
if (!session || session.ended_at) return; if (!session || session.ended_at) return;
const interval = setInterval(() => { const interval = setInterval(() => {
qc.invalidateQueries({ queryKey: ["messages", id, msgLimit] }); qc.invalidateQueries({ queryKey: ["messages", id] });
qc.invalidateQueries({ queryKey: ["session", id] }); qc.invalidateQueries({ queryKey: ["session", id] });
}, 5000); }, 5000);
return () => clearInterval(interval); return () => clearInterval(interval);
@@ -278,14 +281,14 @@ export default function SessionReplayPage({ params }: { params: Promise<{ id: st
</p> </p>
)} )}
{/* Load more (at bottom = older messages since list is reversed) */} {/* Load older messages */}
{(messagesData?.total || 0) > msgLimit && ( {msgOffset > 0 && (
<button <button
onClick={() => setMsgLimit((l) => l + 100)} onClick={() => setMsgLimit((l) => l + 100)}
className="w-full py-3 mt-2 text-[13px] font-medium rounded-xl transition-colors" className="w-full py-3 mt-2 text-[13px] font-medium rounded-xl transition-colors"
style={{ color: "var(--accent)", background: "var(--accent-dim)" }} style={{ color: "var(--accent)", background: "var(--accent-dim)" }}
> >
Load older messages Load older messages ({msgOffset} more)
</button> </button>
)} )}
</div> </div>
+2 -2
View File
@@ -50,9 +50,9 @@ export const fetchSessions = (limit = 50, offset = 0, source?: string) =>
export const fetchSession = (id: string) => export const fetchSession = (id: string) =>
get<{ session: Session }>(`/api/sessions/${id}`); get<{ session: Session }>(`/api/sessions/${id}`);
export const fetchMessages = (sessionId: string, limit = 200, offset = 0) => export const fetchMessages = (sessionId: string, limit = 200, offset?: number) =>
get<{ items: Message[]; total: number }>( get<{ items: Message[]; total: number }>(
`/api/sessions/${sessionId}/messages?limit=${limit}&offset=${offset}` `/api/sessions/${sessionId}/messages?limit=${limit}${offset != null ? `&offset=${offset}` : ""}`
); );
export const searchSessions = (q: string, limit = 20) => export const searchSessions = (q: string, limit = 20) =>
+3 -3
View File
@@ -19,10 +19,10 @@ export function useSession(id: string) {
}); });
} }
export function useMessages(sessionId: string, limit = 200) { export function useMessages(sessionId: string, limit = 200, offset?: number) {
return useQuery({ return useQuery({
queryKey: ["messages", sessionId, limit], queryKey: ["messages", sessionId, limit, offset],
queryFn: () => api.fetchMessages(sessionId, limit), queryFn: () => api.fetchMessages(sessionId, limit, offset),
enabled: !!sessionId, enabled: !!sessionId,
}); });
} }