use-route-inbox.ts2.7 KBView on GitHub import { useMemo } from 'react';
import { useActiveConnection } from '@/hooks/use-connections';
import { useLabels } from '@/modules/labels/hooks/use-labels';
import { useInboxes, type InboxConfig } from '@/modules/threads/hooks/use-inboxes';
import {
buildInboxCompiledQuery,
type InboxCompiledQuery,
} from '@/modules/threads/lib/inbox-compiled-query';
import { resolveRouteInbox, type RouteInboxResolution } from '@/modules/threads/lib/route-inbox';
export type RouteInbox = RouteInboxResolution & {
/**
* The Gmail query this route means, or `undefined` when the route is not an inbox route.
*
* Built here rather than read off `inbox.compiledQuery`: the system tabs (Inbox / Important
* / Other) are local stubs with no stored query, so reading the record hands back
* `undefined` for exactly the three tabs whose meaning is computed.
*/
compiled: InboxCompiledQuery | undefined;
};
/**
* The one place a `/mail/:folder` route becomes a query — shared by the email list
* (`useThreads`) and the unified feed (`mail.tsx` → `InboxList`).
*
* Two surfaces asking the same route the same way is the whole point: they resolve the inbox
* from the URL through `resolveRouteInbox` and compile it through `buildInboxCompiledQuery`,
* so `All` and `Email` cannot disagree about what tab is open before the server is reached.
* See apps/mail/docs/inbox-triage.md Phase 0.
*/
export function useRouteInbox(opts: { folder: string; inbox?: InboxConfig }): RouteInbox {
const { data: activeConnection } = useActiveConnection();
const { systemLabels } = useLabels();
const { inboxes, importantSignal } = useInboxes();
const hasCategoryPersonal = useMemo(
() => systemLabels.some((label) => label.name.toLowerCase() === 'personal'),
[systemLabels],
);
const resolution = useMemo(
() => resolveRouteInbox({ inboxes, folder: opts.folder, explicitInbox: opts.inbox }),
[inboxes, opts.folder, opts.inbox],
);
const compiled = useMemo<InboxCompiledQuery | undefined>(() => {
if (resolution.systemFolderSplit) {
return {
compiledQuery: resolution.systemFolderSplit.compiledQuery,
queryHash: resolution.systemFolderSplit.queryHash,
inboxName: resolution.systemFolderSplit.inboxName,
};
}
if (!resolution.inbox) return undefined;
return buildInboxCompiledQuery({
inbox: resolution.inbox,
inboxes,
hasCategoryPersonal,
connectionEmail: activeConnection?.email,
sessionName: activeConnection?.name,
importantSignal,
});
}, [
resolution.systemFolderSplit,
resolution.inbox,
inboxes,
hasCategoryPersonal,
activeConnection?.email,
activeConnection?.name,
importantSignal,
]);
return { ...resolution, compiled };
}