fix: use historyId to invalidate mail.get cache (#1063)

This commit is contained in:
Rahul Mishra
2025-05-25 19:06:59 +05:30
committed by GitHub
parent 18980f59da
commit 11ea9fc8cc
7 changed files with 48 additions and 9 deletions

View File

@@ -72,7 +72,11 @@ const Thread = memo(
const [threadId] = useQueryState('threadId');
const [, setBackgroundQueue] = useAtom(backgroundQueueAtom);
const { refetch: refetchStats } = useStats();
const { data: getThreadData, isGroupThread, refetch: refetchThread } = useThread(message.id);
const {
data: getThreadData,
isGroupThread,
refetch: refetchThread,
} = useThread(message.id, message.historyId);
const [isStarred, setIsStarred] = useState(false);
const trpc = useTRPC();
const queryClient = useQueryClient();

View File

@@ -0,0 +1,13 @@
import { useState } from 'react';
export function usePrevious<T>(value: T) {
const [current, setCurrent] = useState(value);
const [previous, setPrevious] = useState<T | null>(null);
if (value !== current) {
setPrevious(current);
setCurrent(value);
}
return previous;
}

View File

@@ -1,12 +1,13 @@
import { backgroundQueueAtom, isThreadInBackgroundQueueAtom } from '@/store/backgroundQueue';
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
import { useInfiniteQuery, useQuery, useQueryClient } from '@tanstack/react-query';
import { useSearchValue } from '@/hooks/use-search-value';
import { useTRPC } from '@/providers/query-provider';
import { useSession } from '@/lib/auth-client';
import { useAtom, useAtomValue } from 'jotai';
import { usePrevious } from './use-previous';
import { useEffect, useMemo } from 'react';
import { useParams } from 'react-router';
import { useQueryState } from 'nuqs';
import { useMemo } from 'react';
export const useThreads = () => {
const { folder } = useParams<{ folder: string }>();
@@ -58,12 +59,20 @@ export const useThreads = () => {
return [threadsQuery, threads, isReachingEnd, loadMore] as const;
};
export const useThread = (threadId: string | null) => {
export const useThread = (threadId: string | null, historyId?: string | null) => {
const { data: session } = useSession();
const [_threadId] = useQueryState('threadId');
const id = threadId ? threadId : _threadId;
const trpc = useTRPC();
const previousHistoryId = usePrevious(historyId ?? null);
const queryClient = useQueryClient();
useEffect(() => {
if (!historyId || !previousHistoryId || historyId === previousHistoryId) return;
queryClient.invalidateQueries({ queryKey: trpc.mail.get.queryKey({ id: id! }) });
}, [historyId, previousHistoryId, id]);
const threadQuery = useQuery(
trpc.mail.get.queryOptions(
{

View File

@@ -106,7 +106,7 @@ export interface MailListProps {
export type MailSelectMode = 'mass' | 'range' | 'single' | 'selectAllBelow';
export type ThreadProps = {
message: { id: string };
message: { id: string; historyId?: string | null };
onClick?: (message: ParsedMessage) => () => void;
isKeyboardFocused?: boolean;
};

View File

@@ -190,11 +190,18 @@ export class GoogleMailManager implements MailManager {
pageToken: pageToken ? pageToken : undefined,
quotaUser: this.config.auth?.email,
});
const threads = res.data.threads ?? [];
return {
threads: (res.data.threads ?? [])
threads: threads
.filter((thread) => typeof thread.id === 'string')
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
.map((thread) => ({ id: thread.id!, $raw: thread })),
.map((thread) => ({
id: thread.id!,
historyId: thread.historyId ?? null,
$raw: thread,
})),
nextPageToken: res.data.nextPageToken ?? null,
};
},
@@ -493,6 +500,7 @@ export class GoogleMailManager implements MailManager {
return {
threads: sortedDrafts.map((draft) => ({
id: draft.id,
historyId: draft.threadId ?? null,
$raw: draft,
})),
nextPageToken: res.data.nextPageToken ?? null,

View File

@@ -305,6 +305,7 @@ export class OutlookMailManager implements MailManager {
return {
threads: messages.map((msg, index) => ({
id: msg.id || msg.internetMessageId || '',
historyId: msg.lastModifiedDateTime ?? null,
$raw: {
...msg,
...fullMessages[index],
@@ -619,6 +620,7 @@ export class OutlookMailManager implements MailManager {
return {
threads: sortedDrafts.map((draft) => ({
id: draft.id,
historyId: null,
$raw: draft,
})),
nextPageToken: nextPageLink || null,

View File

@@ -45,7 +45,7 @@ export interface MailManager {
): Promise<{ id?: string | null; success?: boolean; error?: string }>;
getDraft(id: string): Promise<ParsedDraft>;
listDrafts(params: { q?: string; maxResults?: number; pageToken?: string }): Promise<{
threads: { id: string; $raw: unknown }[];
threads: { id: string; historyId: string | null; $raw: unknown }[];
nextPageToken: string | null;
}>;
delete(id: string): Promise<void>;
@@ -55,7 +55,10 @@ export interface MailManager {
maxResults?: number;
labelIds?: string[];
pageToken?: string | number;
}): Promise<{ threads: { id: string; $raw?: unknown }[]; nextPageToken: string | null }>;
}): Promise<{
threads: { id: string; historyId: string | null; $raw?: unknown }[];
nextPageToken: string | null;
}>;
count(): Promise<{ count?: number; label?: string }[]>;
getTokens(
code: string,