diff --git a/components/email/__tests__/thread-list-item.test.tsx b/components/email/__tests__/thread-list-item.test.tsx index f9b312e39..b7208a5b5 100644 --- a/components/email/__tests__/thread-list-item.test.tsx +++ b/components/email/__tests__/thread-list-item.test.tsx @@ -14,6 +14,18 @@ vi.mock('@/stores/auth-store', () => ({ useAuthStore: () => ({ identities: [] }), })); +const ACCOUNT_TEAL = { id: 'acct-teal', avatarColor: '#0d9488', label: 'Teal account' }; +const accountState = { + getAccountById: (id: string) => (id === ACCOUNT_TEAL.id ? ACCOUNT_TEAL : undefined), +}; +vi.mock('@/stores/account-store', () => ({ + useAccountStore: Object.assign( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (selector: any) => (selector ? selector(accountState) : accountState), + { getState: () => accountState }, + ), +})); + const makeEmail = (overrides: Partial = {}): Email => ({ id: 'email-1', threadId: 'thread-1', @@ -288,3 +300,83 @@ describe('ThreadListItem row tint', () => { expect(classes).toContain('bg-accent/40'); }); }); + + +describe('ThreadListItem account row tint', () => { + beforeEach(() => { + useSettingsStore.setState({ + emailKeywords: [...DEFAULT_KEYWORDS], + showPreview: false, + mailLayout: 'split', + tintListRowsByTag: true, + tintListRowsByAccount: false, + }); + useEmailStore.setState({ + selectedEmailIds: new Set(), + selectedMailbox: 'inbox', + isUnifiedView: false, + }); + }); + + const row = (c: HTMLElement) => c.querySelector('[data-subject="Test Subject"]'); + const accountEmail = () => makeEmail({ accountId: ACCOUNT_TEAL.id, accountLabel: ACCOUNT_TEAL.label }); + + it('tints the row with the account colour in the unified view', () => { + useSettingsStore.setState({ tintListRowsByAccount: true }); + useEmailStore.setState({ isUnifiedView: true }); + + const { container } = renderRow(accountEmail()); + expect(row(container)!.className).toContain('bg-teal-100'); + }); + + it('leaves rows untinted outside the unified view', () => { + useSettingsStore.setState({ tintListRowsByAccount: true }); + useEmailStore.setState({ isUnifiedView: false }); + + const { container } = renderRow(accountEmail()); + expect(row(container)!.className).not.toContain('bg-teal-100'); + }); + + it('does not tint by account while the setting is off', () => { + useEmailStore.setState({ isUnifiedView: true }); + + const { container } = renderRow(accountEmail()); + expect(row(container)!.className).not.toContain('bg-teal-100'); + }); + + it('still tints when accountId matches no local account', () => { + // Shared/group entries carry the JMAP owner id, which no AccountEntry + // matches - the row must fall back to a colour from the label, not stay blank. + useSettingsStore.setState({ tintListRowsByAccount: true }); + useEmailStore.setState({ isUnifiedView: true }); + const orphan = makeEmail({ accountId: 'jmap-owner-id-with-no-entry', accountLabel: 'luca@lucazanon.it' }); + + const { container } = renderRow(orphan); + expect(row(container)!.className).toMatch(/bg-[a-z]+-\d+/); + }); + + it('gives different accounts different tints', () => { + useSettingsStore.setState({ tintListRowsByAccount: true }); + useEmailStore.setState({ isUnifiedView: true }); + + const a = renderRow(makeEmail({ accountId: 'x', accountLabel: 'luca@insulaab.it' })); + const clsA = row(a.container)!.className.match(/bg-[a-z]+-\d+/)![0]; + a.unmount(); + const b = renderRow(makeEmail({ accountId: 'y', accountLabel: 'luca@lucazanon.it' })); + const clsB = row(b.container)!.className.match(/bg-[a-z]+-\d+/)![0]; + + expect(clsA).not.toBe(clsB); + }); + + it('outranks the tag tint', () => { + useSettingsStore.setState({ tintListRowsByAccount: true }); + useEmailStore.setState({ isUnifiedView: true }); + const tagged = makeEmail({ + accountId: ACCOUNT_TEAL.id, + keywords: { $seen: true, [`$label:${DEFAULT_KEYWORDS[0].id}`]: true }, + }); + + const { container } = renderRow(tagged); + expect(row(container)!.className).toContain('bg-teal-100'); + }); +}); diff --git a/components/email/thread-list-item.tsx b/components/email/thread-list-item.tsx index 19ac9c4da..812fe29d7 100644 --- a/components/email/thread-list-item.tsx +++ b/components/email/thread-list-item.tsx @@ -9,7 +9,8 @@ import type { Attachment } from "@/lib/jmap/types"; import { SelectableAvatar } from "@/components/email/selectable-avatar"; import { Paperclip, Star, Pin, Circle, ChevronRight, ChevronDown, Loader2, MessageSquare, CheckSquare, Square, Reply, Forward, CalendarClock, Folder, Archive, Trash2, MailOpen, ShieldAlert } from "lucide-react"; import type { LucideIcon } from "lucide-react"; -import { useSettingsStore } from "@/stores/settings-store"; +import { useSettingsStore, KEYWORD_PALETTE } from "@/stores/settings-store"; +import { accountTintKey, generateAvatarColor } from "@/lib/account-utils"; import { useUIStore } from "@/stores/ui-store"; import { useEmailStore } from "@/stores/email-store"; import { useAccountStore, type AccountEntry } from "@/stores/account-store"; @@ -176,6 +177,7 @@ const SingleEmailItem = React.forwardRef( const { sortTagIds, tagColor } = useKeywordFormat(); const { variant: tagVariant, placement: tagPlacement } = useTagDisplay(); const tintListRowsByTag = useSettingsStore((state) => state.tintListRowsByTag); + const tintListRowsByAccount = useSettingsStore((state) => state.tintListRowsByAccount); const density = useSettingsStore((state) => state.density); const mailLayout = useSettingsStore((state) => state.mailLayout); const timeFormat = useSettingsStore((state) => state.timeFormat); @@ -202,7 +204,22 @@ const SingleEmailItem = React.forwardRef( : null; const tagIds = sortTagIds(getEmailTagIds(email.keywords)); - const resolvedRowTint = !tintListRowsByTag ? null : (rowTint ?? (tagIds[0] ? tagColor(tagIds[0]).rowTint : null)); + // The account tint stands in for the per-account dot, so it outranks the + // tag tint - the tag still shows its own colour on its chip. + // + // `accountId` only resolves to a local account for personal entries; shared + // ones carry the JMAP owner id, which no AccountEntry matches. Falling back + // to the reaching client and then to a colour derived from the label means + // every row that knows which account it came from gets tinted, instead of + // silently staying blank. + const accountTintSource = accountColor + ?? (email.sourceClientAccountId ? getAccountById(email.sourceClientAccountId)?.avatarColor : undefined) + ?? (email.accountLabel ? generateAvatarColor(email.accountLabel) : undefined); + const accountRowTint = (tintListRowsByAccount && isUnifiedView && accountTintSource) + ? (KEYWORD_PALETTE[accountTintKey(accountTintSource)]?.rowTint ?? null) + : null; + const resolvedRowTint = accountRowTint + ?? (!tintListRowsByTag ? null : (rowTint ?? (tagIds[0] ? tagColor(tagIds[0]).rowTint : null))); const { dragHandlers, isDragging } = useEmailDrag({ email, @@ -392,7 +409,7 @@ const SingleEmailItem = React.forwardRef( {isFocusedMailLayout ? (
- {isUnifiedView && email.accountId && accountColor && ( + {isUnifiedView && email.accountId && accountColor && !tintListRowsByAccount && ( ( <>
- {isUnifiedView && email.accountId && accountColor && ( + {isUnifiedView && email.accountId && accountColor && !tintListRowsByAccount && ( state.tintListRowsByTag); + const tintListRowsByAccount = useSettingsStore((state) => state.tintListRowsByAccount); // A collapsed row speaks for every message under it, so it carries their tags too. const tagIds = sortTagIds(getThreadTagIds(thread.emails)); - const rowTint = (tintListRowsByTag && tagIds[0]) ? tagColor(tagIds[0]).rowTint : null; + const threadTintSource = threadAccountColor + ?? (latestEmail.sourceClientAccountId ? getAccountById(latestEmail.sourceClientAccountId)?.avatarColor : undefined) + ?? (latestEmail.accountLabel ? generateAvatarColor(latestEmail.accountLabel) : undefined); + const accountRowTint = (tintListRowsByAccount && isUnifiedView && threadTintSource) + ? (KEYWORD_PALETTE[accountTintKey(threadTintSource)]?.rowTint ?? null) + : null; + const rowTint = accountRowTint + ?? ((tintListRowsByTag && tagIds[0]) ? tagColor(tagIds[0]).rowTint : null); const isSelected = selectedEmailId === latestEmail.id || thread.emails.some(e => e.id === selectedEmailId); @@ -885,7 +910,7 @@ export const ThreadListItem = React.forwardRef
- {isUnifiedView && latestEmail.accountId && threadAccountColor && ( + {isUnifiedView && latestEmail.accountId && threadAccountColor && !tintListRowsByAccount && (
- {isUnifiedView && latestEmail.accountId && threadAccountColor && ( + {isUnifiedView && latestEmail.accountId && threadAccountColor && !tintListRowsByAccount && ( s.accounts); const activeAccountId = useAccountStore(s => s.activeAccountId); @@ -231,6 +231,13 @@ export function LayoutSettings() { /> + + updateSetting('tintListRowsByAccount', checked)} + /> + + { expect(result.current.tagColor('archive')).toBe(KEYWORD_PALETTE['red-dark']); }); - it('falls back to grey for a keyword this client has no definition for', () => { - // Set on the message by another client, or its tag was deleted here. + it('gives a keyword it has no definition for a hue of its own', () => { + // Set on the message by another client, applied by a server-side filter, + // or its tag was deleted here. One shared grey made every such tag look + // alike, which is when telling them apart matters most. const { result } = renderHook(() => useKeywordFormat()); - expect(result.current.tagColor('never-heard-of-it')).toBe(KEYWORD_PALETTE.gray); + expect(result.current.tagColor('never-heard-of-it')) + .toBe(KEYWORD_PALETTE[suggestKeywordColor('never-heard-of-it')]); }); - it('falls back to grey for a colour that is not in the palette', () => { + it('matches the colour the settings screen would propose for that tag', () => { + // Adopting a discovered tag must not make its colour jump. + const { result } = renderHook(() => useKeywordFormat()); + + for (const id of ['netflix', 'humb', 'ebay']) { + expect(result.current.tagColor(id)).toBe(KEYWORD_PALETTE[suggestKeywordColor(id)]); + } + }); + + it('keeps an undefined tag on the same hue across renders', () => { + const a = renderHook(() => useKeywordFormat()); + const b = renderHook(() => useKeywordFormat()); + + expect(a.result.current.tagColor('humb')).toBe(b.result.current.tagColor('humb')); + }); + + it('spreads undefined tags over several hues', () => { + const { result } = renderHook(() => useKeywordFormat()); + const ids = ['humb', 'alie', 'ebay', 'zoop', 'fire', 'nexu', 'ubis', 'tlsreports']; + + const dots = new Set(ids.map((id) => result.current.tagColor(id).dot)); + expect(dots.size).toBeGreaterThan(1); + }); + + it('derives a hue for a definition whose colour is not in the palette', () => { useSettingsStore.setState({ emailKeywords: [{ id: 'odd', label: 'Odd', color: 'chartreuse' }] }); const { result } = renderHook(() => useKeywordFormat()); - expect(result.current.tagColor('odd')).toBe(KEYWORD_PALETTE.gray); + expect(result.current.tagColor('odd')).toBe(KEYWORD_PALETTE[suggestKeywordColor('odd')]); }); }); diff --git a/hooks/use-keyword-format.ts b/hooks/use-keyword-format.ts index 91c05bba3..ae82caa65 100644 --- a/hooks/use-keyword-format.ts +++ b/hooks/use-keyword-format.ts @@ -8,6 +8,7 @@ import { type KeywordColor, } from "@/stores/settings-store"; import { formatKeyword, formatKeywordLabels, keywordRenderings } from "@/lib/keyword-format"; +import { suggestKeywordColor } from "@/lib/keyword-discovery"; /** * Names and colours tags for the screen, bound to the user's tag settings. @@ -31,13 +32,22 @@ export function useKeywordFormat() { tagNameCandidates: (id: string) => keywordRenderings(formatKeywordLabels(id, keywords, nested)), /** - * The tag's colour. Falls back to grey for a keyword this client has no - * definition for - one created on another device, or whose tag was - * deleted - so such a tag still shows rather than silently vanishing. + * The tag's colour. + * + * A keyword this client has no definition for - one created on another + * device, applied by a server-side filter, or whose tag was deleted - + * still gets a hue of its own, derived from its id by the same function + * that proposes colours for recovered tags. One shared grey made every + * such tag look alike, which is exactly when telling them apart matters: + * a mailbox filling up with server-assigned tags would show a single + * undifferentiated colour. The hue is a pure function of the id, so it is + * stable across reloads and devices, and it degrades to grey only when + * the proposal names a colour the palette does not hold. */ tagColor: (id: string): KeywordColor => { const color = keywords.find((keyword) => keyword.id === id)?.color; - return (color ? KEYWORD_PALETTE[color] : undefined) ?? KEYWORD_PALETTE[FALLBACK_KEYWORD_COLOR]; + if (color && KEYWORD_PALETTE[color]) return KEYWORD_PALETTE[color]; + return KEYWORD_PALETTE[suggestKeywordColor(id)] ?? KEYWORD_PALETTE[FALLBACK_KEYWORD_COLOR]; }, /** diff --git a/lib/account-utils.ts b/lib/account-utils.ts index 1f08671c0..f1c35592b 100644 --- a/lib/account-utils.ts +++ b/lib/account-utils.ts @@ -42,6 +42,41 @@ export function generateAvatarColor(email: string): string { return colors[Math.abs(hash) % colors.length]; } +/** + * The `KEYWORD_PALETTE` key whose tint matches an account's avatar colour. + * + * Row tints are Tailwind class pairs (light + dark) rather than raw colours, so + * an account's hex cannot be used directly as a background. Mapping onto the + * shared tag palette keeps account tints in the same visual language as tag + * tints and gets dark mode for free. + * + * These pick the palette's `-dark` variants. A tag tint can afford to be faint + * because the tag also shows a coloured chip, but an account tint replaces the + * account dot and has to carry that information on its own - the fainter + * variants are close to invisible against the row background. + * + * The palette has no violet, so the two purple-ish avatar hues would collide. + * Purple keeps `purple-dark` and violet falls back to the plain `purple`, whose + * lighter wash still tells the two apart. + */ +export function accountTintKey(avatarColor: string | undefined): string { + switch ((avatarColor ?? '').toLowerCase()) { + case '#2563eb': return 'blue-dark'; + case '#7c3aed': return 'purple'; + case '#db2777': return 'pink-dark'; + case '#dc2626': return 'red-dark'; + case '#ea580c': return 'orange-dark'; + case '#d97706': return 'amber-dark'; + case '#65a30d': return 'lime-dark'; + case '#16a34a': return 'green-dark'; + case '#0d9488': return 'teal-dark'; + case '#0891b2': return 'cyan-dark'; + case '#6366f1': return 'indigo-dark'; + case '#9333ea': return 'purple-dark'; + default: return 'gray-dark'; + } +} + /** Get initials for an avatar from a display name or email */ export function getInitials(name: string, email?: string): string { if (name) { diff --git a/locales/ar/common.json b/locales/ar/common.json index 53d4bf6d8..075504e55 100644 --- a/locales/ar/common.json +++ b/locales/ar/common.json @@ -1066,6 +1066,10 @@ "label": "تلوين صفوف القائمة بلون الوسم", "description": "تظليل كل صف رسالة بلون أول وسم فيها. عطّل هذا لإبقاء الصفوف عادية؛ ستظل نقاط الوسوم وشاراتها تظهر اللون." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "إظهار إجمالي عدد الرسائل", "description": "إظهار إجمالي عدد الرسائل بجانب المجلدات والوسوم، إلى جانب عدد غير المقروء. عطّل هذا لإظهار عدد غير المقروء فقط." diff --git a/locales/ca/common.json b/locales/ca/common.json index 686039db0..3446c10dc 100644 --- a/locales/ca/common.json +++ b/locales/ca/common.json @@ -1066,6 +1066,10 @@ "label": "Acoloreix les files de la llista segons l'etiqueta", "description": "Ombreja cada fila de missatge amb el color de la primera etiqueta. Desactiveu-ho per mantenir les files planes; els punts i les etiquetes encara mostraran el color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Mostra el nombre total de missatges", "description": "Mostra el nombre total de missatges al costat de les carpetes i etiquetes, juntament amb el nombre de no llegits. Desactiveu-ho per mostrar només els no llegits." diff --git a/locales/cs/common.json b/locales/cs/common.json index 5262ee69d..ae6833a34 100644 --- a/locales/cs/common.json +++ b/locales/cs/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Zobrazit celkový počet zpráv", "description": "Zobrazí celkový počet zpráv vedle složek a štítků spolu s počtem nepřečtených. Vypněte pro zobrazení pouze nepřečtených." diff --git a/locales/da/common.json b/locales/da/common.json index 09552435b..633e3eed7 100644 --- a/locales/da/common.json +++ b/locales/da/common.json @@ -1066,6 +1066,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Vis samlet antal beskeder", "description": "Viser det samlede antal beskeder ud for mapper og tags sammen med antallet af ulæste. Slå fra for kun at vise ulæste." diff --git a/locales/de/common.json b/locales/de/common.json index 2d39bfc03..2fc40ed71 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -1063,6 +1063,10 @@ "label": "Nachrichtenzeilen mit Tag-Farbe einfärben", "description": "Die einzelnen Nachrichtenzeilen mit der Farbe ihres ersten Tags einfärben. Deaktivieren Sie diese Option, um die Zeilen neutral zu halten; Tag-Punkte und -Markierungen zeigen die Farbe weiterhin an." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Gesamtzahl der Nachrichten anzeigen", "description": "Zeigt neben Ordnern und Tags die Gesamtzahl der Nachrichten zusätzlich zur Anzahl ungelesener Nachrichten an. Deaktivieren, um nur ungelesene Nachrichten anzuzeigen." diff --git a/locales/en/common.json b/locales/en/common.json index 78a509e09..487e61539 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -1066,6 +1066,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Show Total Message Count", "description": "Show the total message count next to folders and tags, alongside the unread count. Disable to show only unread counts." diff --git a/locales/es/common.json b/locales/es/common.json index ae2413a7f..4c7fdf899 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Mostrar el número total de mensajes", "description": "Muestra el número total de mensajes junto a las carpetas y etiquetas, además del número de mensajes no leídos. Desactívalo para mostrar solo los no leídos." diff --git a/locales/fa/common.json b/locales/fa/common.json index c454007f8..f678017d3 100644 --- a/locales/fa/common.json +++ b/locales/fa/common.json @@ -1066,6 +1066,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "نمایش تعداد کل پیام‌ها", "description": "تعداد کل پیام‌ها را در کنار پوشه‌ها و برچسب‌ها، همراه با تعداد خوانده‌نشده‌ها نمایش می‌دهد. برای نمایش فقط تعداد خوانده‌نشده‌ها غیرفعال کنید." diff --git a/locales/fr/common.json b/locales/fr/common.json index 738fd0b3f..a4cb1c5f2 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Afficher le nombre total de messages", "description": "Affiche le nombre total de messages à côté des dossiers et des étiquettes, en plus du nombre de messages non lus. Désactivez pour n'afficher que les messages non lus." diff --git a/locales/he/common.json b/locales/he/common.json index a03914d4f..aa46eb335 100644 --- a/locales/he/common.json +++ b/locales/he/common.json @@ -1028,6 +1028,10 @@ "label": "צביעת שורות הרשימה לפי צבע התגית", "description": "צובע כל שורת הודעה בצבע התגית הראשונה שלה. כבו כדי להשאיר את השורות ללא צבע; נקודות ותוויות התגיות עדיין יציגו את הצבע." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "הצגת מספר ההודעות הכולל", "description": "מציג את מספר ההודעות הכולל לצד תיקיות ותגיות, לצד מספר ההודעות שלא נקראו. כבו כדי להציג רק את מספר ההודעות שלא נקראו." diff --git a/locales/hu/common.json b/locales/hu/common.json index d348bccb5..bc77c03ab 100644 --- a/locales/hu/common.json +++ b/locales/hu/common.json @@ -1066,6 +1066,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Összes üzenet számának megjelenítése", "description": "Megjeleníti az üzenetek teljes számát a mappák és címkék mellett, az olvasatlanok számán túl. Kapcsolja ki, ha csak az olvasatlanok számát szeretné látni." diff --git a/locales/it/common.json b/locales/it/common.json index 30c7ab7af..56f606627 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Colora le righe in base all'account", + "description": "Nella vista unificata, colora ogni riga con il colore del suo account invece di mostrare il pallino. Ha la precedenza sulla tinta del tag; i tag mantengono il loro colore sulle etichette." + }, "show_folder_total_count": { "label": "Mostra il numero totale di messaggi", "description": "Mostra il numero totale di messaggi accanto a cartelle ed etichette, insieme al conteggio dei non letti. Disattiva per mostrare solo i non letti." diff --git a/locales/ja/common.json b/locales/ja/common.json index c6555f190..7e0bfcedc 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "メッセージの総数を表示", "description": "フォルダーやタグの横に、未読数に加えてメッセージの総数を表示します。未読数のみを表示するには無効にします。" diff --git a/locales/ko/common.json b/locales/ko/common.json index 93f56bda1..6abadd24d 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "전체 메시지 수 표시", "description": "읽지 않은 수와 함께 폴더 및 태그 옆에 전체 메시지 수를 표시합니다. 읽지 않은 수만 표시하려면 비활성화하세요." diff --git a/locales/lv/common.json b/locales/lv/common.json index b31dd7047..a22b3c750 100644 --- a/locales/lv/common.json +++ b/locales/lv/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Rādīt kopējo ziņojumu skaitu", "description": "Rāda kopējo ziņojumu skaitu blakus mapēm un tagiem, kā arī nelasīto ziņojumu skaitu. Atspējojiet, lai rādītu tikai nelasītos." diff --git a/locales/mn/common.json b/locales/mn/common.json index 0fc2b17f2..f71dba10b 100644 --- a/locales/mn/common.json +++ b/locales/mn/common.json @@ -1066,6 +1066,10 @@ "label": "Тагийн өнгөөр эгнээнүүдийг будах", "description": "Мессежийн мөр бүрийг эхний шошгоны өнгөөр сүүдэрлээрэй. Мөрүүдийг энгийн байлгахын тулд идэвхгүй болгох; шошгоны цэгүүд болон чипүүд нь өнгийг харуулсан хэвээр байна." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Нийт мессежийн тоог харуулах", "description": "Нийт мессежийн тоог хавтас, шошгоны хажууд уншаагүй тооны хажууд харуул. Зөвхөн уншаагүй тоонуудыг харуулахын тулд идэвхгүй болго." diff --git a/locales/nb/common.json b/locales/nb/common.json index 3648dccfc..b06a93ac1 100644 --- a/locales/nb/common.json +++ b/locales/nb/common.json @@ -1066,6 +1066,10 @@ "label": "Fargelegg meldingsrader etter etikett", "description": "Gi hver meldingsrad en svak bakgrunnsfarge basert på den første etiketten. Deaktiver dette for nøytrale rader; etikettmarkørene viser fortsatt fargen." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Vis totalt antall meldinger", "description": "Vis totalt antall meldinger ved siden av mapper og etiketter, sammen med antall uleste. Deaktiver for å vise bare antall uleste." diff --git a/locales/nl/common.json b/locales/nl/common.json index 12e564a77..fcc56ac43 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Totaal aantal berichten tonen", "description": "Toont het totale aantal berichten naast mappen en labels, naast het aantal ongelezen berichten. Schakel uit om alleen ongelezen aantallen te tonen." diff --git a/locales/pl/common.json b/locales/pl/common.json index e903226ee..796a0a66c 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Pokaż łączną liczbę wiadomości", "description": "Pokazuje łączną liczbę wiadomości obok folderów i etykiet, obok liczby nieprzeczytanych. Wyłącz, aby pokazywać tylko nieprzeczytane." diff --git a/locales/pt/common.json b/locales/pt/common.json index bb8f8c8fc..39659b47e 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Mostrar contagem total de mensagens", "description": "Mostra a contagem total de mensagens ao lado de pastas e etiquetas, além da contagem de não lidas. Desative para mostrar apenas as não lidas." diff --git a/locales/ro/common.json b/locales/ro/common.json index 0af8fbf90..b0d2f0d2e 100644 --- a/locales/ro/common.json +++ b/locales/ro/common.json @@ -1066,6 +1066,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Afișează numărul total de mesaje", "description": "Afișează numărul total de mesaje lângă foldere și etichete, pe lângă numărul celor necitite. Dezactivează pentru a afișa doar mesajele necitite." diff --git a/locales/ru/common.json b/locales/ru/common.json index bd08b879c..190f82a78 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Показывать общее количество сообщений", "description": "Показывает общее количество сообщений рядом с папками и метками, наряду с количеством непрочитанных. Отключите, чтобы показывать только непрочитанные." diff --git a/locales/sk/common.json b/locales/sk/common.json index 2e17b787a..d455bb6ce 100644 --- a/locales/sk/common.json +++ b/locales/sk/common.json @@ -1066,6 +1066,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Zobraziť celkový počet správ", "description": "Zobraziť celkový počet správ vedľa priečinkov a štítkov spolu s počtom neprečítaných." diff --git a/locales/tr/common.json b/locales/tr/common.json index f6755de49..7f5def85e 100644 --- a/locales/tr/common.json +++ b/locales/tr/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Toplam mesaj sayısını göster", "description": "Klasörlerin ve etiketlerin yanında, okunmamış sayısının yanı sıra toplam mesaj sayısını gösterir. Yalnızca okunmamışları göstermek için devre dışı bırakın." diff --git a/locales/uk/common.json b/locales/uk/common.json index a896c863c..d4dfa07a4 100644 --- a/locales/uk/common.json +++ b/locales/uk/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "Показувати загальну кількість повідомлень", "description": "Показує загальну кількість повідомлень поруч із теками та мітками, разом із кількістю непрочитаних. Вимкніть, щоб показувати лише непрочитані." diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json index 289ce6d53..715a7bb1b 100644 --- a/locales/zh-TW/common.json +++ b/locales/zh-TW/common.json @@ -1066,6 +1066,10 @@ "label": "依標籤顏色為清單列上色", "description": "以第一個標籤的顏色為每封郵件列加上底色。停用後郵件列保持無底色,但標籤圓點與標籤仍會顯示該顏色。" }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "顯示郵件總數", "description": "在信件匣與標籤旁顯示郵件總數及未讀數量。停用後只顯示未讀數量。" diff --git a/locales/zh/common.json b/locales/zh/common.json index 2cf732396..032b47736 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -1063,6 +1063,10 @@ "label": "Tint List Rows by Tag Color", "description": "Shade each message row with its first tag color. Disable to keep rows plain; tag dots and chips still show the color." }, + "tint_list_rows_by_account": { + "label": "Tint List Rows by Account Color", + "description": "In the unified view, shade each row with its account color instead of showing the account dot. Takes precedence over the tag tint; tags keep their color on their chips." + }, "show_folder_total_count": { "label": "显示邮件总数", "description": "在文件夹和标签旁边显示邮件总数,以及未读数量。停用后仅显示未读数量。" diff --git a/stores/settings-store.ts b/stores/settings-store.ts index 75d8372c6..4e5065fcf 100644 --- a/stores/settings-store.ts +++ b/stores/settings-store.ts @@ -454,6 +454,7 @@ interface SettingsState { // Sidebar colorfulSidebarIcons: boolean; // Tint folder icons by role (inbox blue, junk red, etc.) tintListRowsByTag: boolean; // Tint mail-list rows by the first tag color + tintListRowsByAccount: boolean; // In the unified view, tint rows by account colour instead of showing the account dot showFolderTotalCount: boolean; // Show total message count next to folders/tags (alongside unread) // Folders @@ -668,6 +669,7 @@ const DEFAULT_SETTINGS = { // Sidebar colorfulSidebarIcons: true, tintListRowsByTag: true, + tintListRowsByAccount: false, showFolderTotalCount: true, // Folders @@ -863,6 +865,7 @@ export const useSettingsStore = create()( faviconUnreadBadge: state.faviconUnreadBadge, colorfulSidebarIcons: state.colorfulSidebarIcons, tintListRowsByTag: state.tintListRowsByTag, + tintListRowsByAccount: state.tintListRowsByAccount, showFolderTotalCount: state.showFolderTotalCount, folderIcons: state.folderIcons, emailKeywords: state.emailKeywords,