diff --git a/components/email/__tests__/thread-list-item.test.tsx b/components/email/__tests__/thread-list-item.test.tsx index 26b9a703a..ae627403d 100644 --- a/components/email/__tests__/thread-list-item.test.tsx +++ b/components/email/__tests__/thread-list-item.test.tsx @@ -17,6 +17,18 @@ vi.mock('@/stores/auth-store', () => { }; }); +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', @@ -291,3 +303,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 3aa22733d..fcd44acf4 100644 --- a/components/email/thread-list-item.tsx +++ b/components/email/thread-list-item.tsx @@ -11,7 +11,8 @@ import type { LoadListAttachments } from "@/lib/list-attachments"; 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 "@/components/icons"; import type { AppIcon } from "@/components/icons"; -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"; @@ -195,6 +196,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); @@ -221,7 +223,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, @@ -414,7 +431,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); @@ -904,7 +929,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 f07e856ab..08bb271b1 100644 --- a/locales/ar/common.json +++ b/locales/ar/common.json @@ -1096,6 +1096,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 1ad7d4c0f..9b9c36521 100644 --- a/locales/ca/common.json +++ b/locales/ca/common.json @@ -1096,6 +1096,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 b4e8a633a..075353371 100644 --- a/locales/cs/common.json +++ b/locales/cs/common.json @@ -1093,6 +1093,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 c9b7a83b3..fbec68a1d 100644 --- a/locales/da/common.json +++ b/locales/da/common.json @@ -1096,6 +1096,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 3386f9a12..109e68ebb 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -1093,6 +1093,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 b341d07e2..21d22a428 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -1096,6 +1096,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 a3d431dcf..db38a0ed6 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -1093,6 +1093,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 2602162f8..2626d12b5 100644 --- a/locales/fa/common.json +++ b/locales/fa/common.json @@ -1096,6 +1096,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 3a71d53ba..a98cfe2dc 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -1093,6 +1093,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 97fd062be..1cc530fb6 100644 --- a/locales/he/common.json +++ b/locales/he/common.json @@ -1058,6 +1058,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 a31947216..8011c2853 100644 --- a/locales/hu/common.json +++ b/locales/hu/common.json @@ -1096,6 +1096,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 7a7f90ebb..7bf17bb6e 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -1093,6 +1093,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 425292617..a95f16b4a 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -1093,6 +1093,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 17cbb4626..388f2685f 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -1093,6 +1093,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 5b20f5f05..e7cab43f2 100644 --- a/locales/lv/common.json +++ b/locales/lv/common.json @@ -1093,6 +1093,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 ad131c9d4..cd1eee36b 100644 --- a/locales/mn/common.json +++ b/locales/mn/common.json @@ -1096,6 +1096,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 e98753a24..1794fcf2f 100644 --- a/locales/nb/common.json +++ b/locales/nb/common.json @@ -1096,6 +1096,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 fdc6dd3de..3555bf92f 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -1093,6 +1093,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 98501d3d5..5d1d0505e 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -1093,6 +1093,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 65c3c2b89..b6d3d44a9 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -1093,6 +1093,10 @@ "label": "Colorir as linhas da lista de acordo com a cor da etiqueta", "description": "Aplicar sombreado a cada linha de mensagem com a cor da primeira etiqueta. Desative essa opção para manter as linhas sem sombreado; os pontos e os ícones das etiquetas continuarão exibindo a cor." }, + "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 3734636ba..564de32b4 100644 --- a/locales/ro/common.json +++ b/locales/ro/common.json @@ -1096,6 +1096,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 8b9115b2b..3f1ceadcf 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -1093,6 +1093,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 35e13eb32..0ed10ff34 100644 --- a/locales/sk/common.json +++ b/locales/sk/common.json @@ -1096,6 +1096,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 a378f3255..bea8bd992 100644 --- a/locales/tr/common.json +++ b/locales/tr/common.json @@ -1093,6 +1093,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 1dc84ec59..42b724902 100644 --- a/locales/uk/common.json +++ b/locales/uk/common.json @@ -1093,6 +1093,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 4ab5edeff..15b8030ae 100644 --- a/locales/zh-TW/common.json +++ b/locales/zh-TW/common.json @@ -1096,6 +1096,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 3a2773c5b..36536e060 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -1093,6 +1093,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 04ff908db..971a13e67 100644 --- a/stores/settings-store.ts +++ b/stores/settings-store.ts @@ -457,6 +457,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 @@ -673,6 +674,7 @@ const DEFAULT_SETTINGS = { // Sidebar colorfulSidebarIcons: true, tintListRowsByTag: true, + tintListRowsByAccount: false, showFolderTotalCount: true, // Folders @@ -870,6 +872,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,