1import type { SavedIdentity } from "../shared/types";23export type IdentityFilterMode = "both" | "email" | "username";4export type IdentityKind = "email" | "username";56function compareSavedIdentity(a: SavedIdentity, b: SavedIdentity): number {7 return (8 b.lastUsed - a.lastUsed ||9 b.useCount - a.useCount ||10 a.value.localeCompare(b.value) ||11 a.type.localeCompare(b.type)12 );13}1415function matchesQuery(identity: SavedIdentity, query: string): boolean {16 const q = query.trim().toLowerCase();17 if (!q) return true;18 return [identity.value, identity.exampleDomain ?? "", identity.type]19 .join(" ")20 .toLowerCase()21 .includes(q);22}2324export function sortSavedIdentities(identities: SavedIdentity[]): SavedIdentity[] {25 return [...identities].sort(compareSavedIdentity);26}2728export function filterSavedIdentities(29 identities: SavedIdentity[],30 query: string,31 mode: IdentityFilterMode,32): SavedIdentity[] {33 const typeFiltered = identities.filter((identity) => {34 if (mode === "email") return identity.type === "email";35 if (mode === "username") return identity.type === "username";36 return true;37 });3839 return sortSavedIdentities(typeFiltered).filter((identity) => matchesQuery(identity, query));40}4142export function resolveCustomIdentityKind(43 query: string,44 mode: IdentityFilterMode,45 fallback: IdentityKind,46): IdentityKind {47 if (mode === "email") return "email";48 if (mode === "username") return "username";49 const trimmed = query.trim();50 if (!trimmed) return fallback;51 return trimmed.includes("@") ? "email" : fallback;52}5354export function identityFilterLabel(mode: IdentityFilterMode): string {55 if (mode === "email") return "Emails";56 if (mode === "username") return "Usernames";57 return "Both";58}