feat: add option to disable conversation threading #97
This commit is contained in:
@@ -89,10 +89,12 @@ export function EmailList({
|
||||
searchQuery,
|
||||
} = useEmailStore();
|
||||
|
||||
const disableThreading = useSettingsStore((state) => state.disableThreading);
|
||||
|
||||
const threadGroups = useMemo(() => {
|
||||
const groups = groupEmailsByThread(emails);
|
||||
const groups = groupEmailsByThread(emails, disableThreading);
|
||||
return sortThreadGroups(groups);
|
||||
}, [emails]);
|
||||
}, [emails, disableThreading]);
|
||||
|
||||
const { contextMenu, openContextMenu, closeContextMenu, menuRef } = useContextMenu<Email>();
|
||||
const { dialogProps: confirmDialogProps, confirm: confirmDialog } = useConfirmDialog();
|
||||
|
||||
@@ -39,6 +39,7 @@ export function EmailSettings() {
|
||||
deleteAction,
|
||||
permanentlyDeleteJunk,
|
||||
showPreview,
|
||||
disableThreading,
|
||||
emailsPerPage,
|
||||
externalContentPolicy,
|
||||
mailAttachmentAction,
|
||||
@@ -210,6 +211,14 @@ export function EmailSettings() {
|
||||
</SettingItem>
|
||||
)}
|
||||
|
||||
{/* Disable Thread Grouping */}
|
||||
<SettingItem label={t('disable_threading.label')} description={t('disable_threading.description')}>
|
||||
<ToggleSwitch
|
||||
checked={disableThreading}
|
||||
onChange={(checked) => updateSetting('disableThreading', checked)}
|
||||
/>
|
||||
</SettingItem>
|
||||
|
||||
{/* Quick Hover Actions */}
|
||||
{isFeatureEnabled('hoverActionsConfigEnabled') && (
|
||||
<div className="py-3 border-b border-border space-y-3">
|
||||
|
||||
+5
-3
@@ -3,17 +3,19 @@ import type { Email, ThreadGroup } from "./jmap/types";
|
||||
/**
|
||||
* Groups emails by their threadId and creates ThreadGroup objects for UI display.
|
||||
* Single-email threads are still returned as ThreadGroups with emailCount=1.
|
||||
* When disableThreading is true, each email is placed into its own group using
|
||||
* its message ID as the key, so the list shows individual messages.
|
||||
*/
|
||||
export function groupEmailsByThread(emails: Email[]): ThreadGroup[] {
|
||||
export function groupEmailsByThread(emails: Email[], disableThreading = false): ThreadGroup[] {
|
||||
if (!emails || emails.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Group emails by threadId
|
||||
// Group emails by threadId (or by message ID when threading is disabled)
|
||||
const threadMap = new Map<string, Email[]>();
|
||||
|
||||
for (const email of emails) {
|
||||
const threadId = email.threadId;
|
||||
const threadId = disableThreading ? email.id : email.threadId;
|
||||
if (!threadMap.has(threadId)) {
|
||||
threadMap.set(threadId, []);
|
||||
}
|
||||
|
||||
@@ -798,6 +798,10 @@
|
||||
"label": "Vorschautext anzeigen",
|
||||
"description": "E-Mail-Vorschau in der Liste anzeigen"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "Konversationsgruppierung deaktivieren",
|
||||
"description": "E-Mails als einzelne Nachrichten statt nach Konversation gruppiert anzeigen"
|
||||
},
|
||||
"attachment_click_action": {
|
||||
"label": "Aktion beim Klick auf Anhänge",
|
||||
"description": "Festlegen, ob ein Dateianhang beim Anklicken in der Vorschau geöffnet oder sofort heruntergeladen wird",
|
||||
|
||||
@@ -798,6 +798,10 @@
|
||||
"label": "Show Preview Text",
|
||||
"description": "Display email preview in the list"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "Disable Conversation Grouping",
|
||||
"description": "Show emails as individual messages instead of grouped by conversation"
|
||||
},
|
||||
"attachment_click_action": {
|
||||
"label": "Attachment Click Action",
|
||||
"description": "Choose whether clicking a file attachment previews it or downloads it immediately",
|
||||
|
||||
@@ -794,6 +794,10 @@
|
||||
"label": "Eliminar spam permanentemente",
|
||||
"description": "Eliminar permanentemente los correos de la carpeta Spam en lugar de moverlos a la Papelera"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "Desactivar agrupación de conversaciones",
|
||||
"description": "Mostrar correos como mensajes individuales en lugar de agruparlos por conversación"
|
||||
},
|
||||
"show_preview": {
|
||||
"label": "Mostrar Vista Previa",
|
||||
"description": "Mostrar vista previa del correo en la lista"
|
||||
|
||||
@@ -794,6 +794,10 @@
|
||||
"label": "Supprimer définitivement les indésirables",
|
||||
"description": "Supprimer définitivement les e-mails du dossier Indésirables au lieu de les déplacer vers la corbeille"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "Désactiver le regroupement par conversation",
|
||||
"description": "Afficher les e-mails comme messages individuels plutôt que groupés par conversation"
|
||||
},
|
||||
"show_preview": {
|
||||
"label": "Afficher l'aperçu",
|
||||
"description": "Afficher l'aperçu de l'email dans la liste"
|
||||
|
||||
@@ -794,6 +794,10 @@
|
||||
"label": "Elimina spam definitivamente",
|
||||
"description": "Elimina definitivamente i messaggi dalla cartella Spam invece di spostarli nel cestino"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "Disabilita raggruppamento conversazioni",
|
||||
"description": "Mostra le email come messaggi singoli anziché raggruppati per conversazione"
|
||||
},
|
||||
"show_preview": {
|
||||
"label": "Mostra anteprima testo",
|
||||
"description": "Visualizza l'anteprima del messaggio nell'elenco"
|
||||
|
||||
@@ -794,6 +794,10 @@
|
||||
"label": "迷惑メールを完全に削除",
|
||||
"description": "迷惑メールフォルダのメールをゴミ箱に移動せずに完全に削除する"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "会話グループ化を無効にする",
|
||||
"description": "メールを会話ごとにグループ化せず、個別のメッセージとして表示します"
|
||||
},
|
||||
"show_preview": {
|
||||
"label": "プレビューテキストを表示",
|
||||
"description": "リストにメールのプレビューを表示"
|
||||
|
||||
@@ -794,6 +794,10 @@
|
||||
"label": "Spam permanent verwijderen",
|
||||
"description": "E-mails uit de map Spam permanent verwijderen in plaats van naar de prullenbak te verplaatsen"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "Conversatiegroepering uitschakelen",
|
||||
"description": "Toon e-mails als afzonderlijke berichten in plaats van gegroepeerd op gesprek"
|
||||
},
|
||||
"show_preview": {
|
||||
"label": "Voorbeeldtekst tonen",
|
||||
"description": "E-mailvoorbeeld weergeven in de lijst"
|
||||
|
||||
@@ -794,6 +794,10 @@
|
||||
"label": "Excluir spam permanentemente",
|
||||
"description": "Excluir permanentemente e-mails da pasta Spam em vez de movê-los para a Lixeira"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "Desativar agrupamento de conversas",
|
||||
"description": "Mostrar e-mails como mensagens individuais em vez de agrupados por conversa"
|
||||
},
|
||||
"show_preview": {
|
||||
"label": "Mostrar Texto de Visualização",
|
||||
"description": "Exibir visualização do e-mail na lista"
|
||||
|
||||
@@ -794,6 +794,10 @@
|
||||
"label": "Удалять спам навсегда",
|
||||
"description": "Удалять письма из папки «Спам» навсегда вместо перемещения в корзину"
|
||||
},
|
||||
"disable_threading": {
|
||||
"label": "Отключить группировку по беседам",
|
||||
"description": "Отображать письма как отдельные сообщения, а не сгруппированные по беседам"
|
||||
},
|
||||
"show_preview": {
|
||||
"label": "Показывать текст предпросмотра",
|
||||
"description": "Отображать предпросмотр письма в списке"
|
||||
|
||||
@@ -145,6 +145,9 @@ interface SettingsState {
|
||||
toolbarPosition: ToolbarPosition;
|
||||
showToolbarLabels: boolean;
|
||||
|
||||
// Email Display
|
||||
disableThreading: boolean; // Show emails as individual messages instead of grouped by conversation
|
||||
|
||||
// Experimental
|
||||
senderFavicons: boolean;
|
||||
|
||||
@@ -258,6 +261,9 @@ const DEFAULT_SETTINGS = {
|
||||
toolbarPosition: 'top' as ToolbarPosition,
|
||||
showToolbarLabels: true,
|
||||
|
||||
// Email Display
|
||||
disableThreading: false,
|
||||
|
||||
// Experimental
|
||||
senderFavicons: true,
|
||||
|
||||
@@ -325,6 +331,7 @@ export const useSettingsStore = create<SettingsState>()(
|
||||
attachmentPosition: state.attachmentPosition,
|
||||
archiveMode: state.archiveMode,
|
||||
hoverActions: state.hoverActions,
|
||||
disableThreading: state.disableThreading,
|
||||
trustedSenders: state.trustedSenders,
|
||||
autoSaveDraftInterval: state.autoSaveDraftInterval,
|
||||
sendConfirmation: state.sendConfirmation,
|
||||
|
||||
Reference in New Issue
Block a user