50 lines
1.4 KiB
TypeScript
50 lines
1.4 KiB
TypeScript
"use client"
|
|
|
|
import { useCallback } from "react"
|
|
import type { Email } from "@/lib/email-data"
|
|
import { useMailStore } from "@/lib/stores/mail-store"
|
|
|
|
export type ListMailIndex = {
|
|
emailById: Map<string, Email>
|
|
scheduledIds: Set<string>
|
|
}
|
|
|
|
/** O(n) index for list row logic — avoids repeated `allEmails.some` / `find` per row. */
|
|
export function buildListMailIndex(emails: Email[]): ListMailIndex {
|
|
const emailById = new Map<string, Email>()
|
|
const scheduledIds = new Set<string>()
|
|
for (const e of emails) {
|
|
emailById.set(e.id, e)
|
|
if (e.labels?.includes("scheduled")) scheduledIds.add(e.id)
|
|
}
|
|
return { emailById, scheduledIds }
|
|
}
|
|
|
|
export type MailRowFlags = {
|
|
isRead: boolean
|
|
isStarred: boolean
|
|
isImportant: boolean
|
|
}
|
|
|
|
/**
|
|
* Per-row mail UI flags from the persisted mail store.
|
|
* Use inside a keyed `memo` row component (not a plain `.map` callback).
|
|
*/
|
|
export function useMailRowFlags(email: Email): MailRowFlags {
|
|
const id = email.id
|
|
const readOverride = useMailStore(
|
|
useCallback((s) => s.readOverrides[id], [id])
|
|
)
|
|
const starred = useMailStore(
|
|
useCallback((s) => s.starredIds.includes(id), [id])
|
|
)
|
|
const important = useMailStore(
|
|
useCallback((s) => s.importantIds.includes(id), [id])
|
|
)
|
|
return {
|
|
isRead: readOverride !== undefined ? readOverride : email.read,
|
|
isStarred: starred || email.starred,
|
|
isImportant: important || email.important,
|
|
}
|
|
}
|