diff --git a/components/email/email-hover-actions.tsx b/components/email/email-hover-actions.tsx index 76c0cc52..3d8a9441 100644 --- a/components/email/email-hover-actions.tsx +++ b/components/email/email-hover-actions.tsx @@ -54,6 +54,13 @@ const ACTION_CONFIG: Record state.hoverActions); + const hoverActionsMode = useSettingsStore((state) => state.hoverActionsMode); + const hoverActionsCorner = useSettingsStore((state) => state.hoverActionsCorner); const t = useTranslations("settings.email_behavior.hover_actions"); const isUnread = !email.keywords?.$seen; @@ -96,42 +105,59 @@ export function EmailHoverActions({ } }; + const actionButtons = hoverActions.map((actionId) => { + const config = ACTION_CONFIG[actionId]; + if (!config) return null; + const Icon = config.icon; + + const DisplayIcon = actionId === "markRead" + ? (isUnread ? MailOpen : Mail) + : actionId === "star" && isStarred + ? Star + : Icon; + + return ( + + ); + }); + + if (hoverActionsMode === 'floating') { + return ( + + ); + } + return (
- {hoverActions.map((actionId) => { - const config = ACTION_CONFIG[actionId]; - if (!config) return null; - const Icon = config.icon; - - const DisplayIcon = actionId === "markRead" - ? (isUnread ? MailOpen : Mail) - : actionId === "star" && isStarred - ? Star - : Icon; - - return ( - - ); - })} + {actionButtons}
); diff --git a/components/settings/email-settings.tsx b/components/settings/email-settings.tsx index 1861ff61..31fccf2c 100644 --- a/components/settings/email-settings.tsx +++ b/components/settings/email-settings.tsx @@ -4,7 +4,7 @@ import { useState, useCallback } from 'react'; import { useTranslations } from 'next-intl'; import { useConfig } from '@/hooks/use-config'; import { useSettingsStore } from '@/stores/settings-store'; -import type { ArchiveMode, HoverAction } from '@/stores/settings-store'; +import type { ArchiveMode, HoverAction, HoverActionsMode, HoverActionsCorner } from '@/stores/settings-store'; import { ALL_HOVER_ACTIONS } from '@/stores/settings-store'; import { useAuthStore } from '@/stores/auth-store'; import { useEmailStore } from '@/stores/email-store'; @@ -47,6 +47,8 @@ export function EmailSettings() { emailAlwaysLightMode, archiveMode, hoverActions, + hoverActionsMode, + hoverActionsCorner, trustedSenders, updateSetting, } = useSettingsStore(); @@ -251,6 +253,52 @@ export function EmailSettings() { ); })}
+ + {/* Hover Actions Display Mode */} +
+ +
+ {(['inline', 'floating'] as const).map((mode) => ( + + ))} +
+
+ + {/* Corner Selection (only when floating) */} + {hoverActionsMode === 'floating' && ( +
+ +
+ {(['top-left', 'top-right', 'bottom-left', 'bottom-right'] as const).map((corner) => ( + + ))} +
+
+ )} )} diff --git a/locales/de/common.json b/locales/de/common.json index 3ad471ce..7fa1c454 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -861,7 +861,15 @@ "archive": "Archivieren", "tag": "Schlagwort", "spam": "Als Spam markieren", - "none_selected": "Keine Aktionen ausgewählt" + "none_selected": "Keine Aktionen ausgewählt", + "mode_label": "Anzeigemodus", + "mode_inline": "Eingebettet", + "mode_floating": "Schwebend", + "corner_label": "Schwebende Position", + "corner_top-left": "Oben links", + "corner_top-right": "Oben rechts", + "corner_bottom-left": "Unten links", + "corner_bottom-right": "Unten rechts" }, "default_mail_program": { "label": "Standard-E-Mail-Programm", diff --git a/locales/en/common.json b/locales/en/common.json index 398ff121..bbb63317 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -861,7 +861,15 @@ "archive": "Archive", "tag": "Tag", "spam": "Mark as Spam", - "none_selected": "No actions selected" + "none_selected": "No actions selected", + "mode_label": "Display Mode", + "mode_inline": "Inline", + "mode_floating": "Floating", + "corner_label": "Floating Position", + "corner_top-left": "Top Left", + "corner_top-right": "Top Right", + "corner_bottom-left": "Bottom Left", + "corner_bottom-right": "Bottom Right" }, "default_mail_program": { "label": "Default Mail Program", diff --git a/locales/es/common.json b/locales/es/common.json index a03a9432..5cd5c85c 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -861,7 +861,15 @@ "archive": "Archivar", "tag": "Etiqueta", "spam": "Marcar como spam", - "none_selected": "No hay acciones seleccionadas" + "none_selected": "No hay acciones seleccionadas", + "mode_label": "Modo de visualización", + "mode_inline": "En línea", + "mode_floating": "Flotante", + "corner_label": "Posición flotante", + "corner_top-left": "Arriba izquierda", + "corner_top-right": "Arriba derecha", + "corner_bottom-left": "Abajo izquierda", + "corner_bottom-right": "Abajo derecha" }, "default_mail_program": { "label": "Programa de correo predeterminado", diff --git a/locales/fr/common.json b/locales/fr/common.json index 684062cb..de0de0cb 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -861,7 +861,15 @@ "archive": "Archiver", "tag": "Étiquette", "spam": "Marquer comme spam", - "none_selected": "Aucune action sélectionnée" + "none_selected": "Aucune action sélectionnée", + "mode_label": "Mode d'affichage", + "mode_inline": "En ligne", + "mode_floating": "Flottant", + "corner_label": "Position flottante", + "corner_top-left": "Haut gauche", + "corner_top-right": "Haut droit", + "corner_bottom-left": "Bas gauche", + "corner_bottom-right": "Bas droit" }, "default_mail_program": { "label": "Programme de messagerie par défaut", diff --git a/locales/it/common.json b/locales/it/common.json index b11e9617..ab585cb4 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -861,7 +861,15 @@ "archive": "Archivia", "tag": "Etichetta", "spam": "Segna come spam", - "none_selected": "Nessuna azione selezionata" + "none_selected": "Nessuna azione selezionata", + "mode_label": "Modalità di visualizzazione", + "mode_inline": "In linea", + "mode_floating": "Fluttuante", + "corner_label": "Posizione fluttuante", + "corner_top-left": "In alto a sinistra", + "corner_top-right": "In alto a destra", + "corner_bottom-left": "In basso a sinistra", + "corner_bottom-right": "In basso a destra" }, "default_mail_program": { "label": "Programma di posta predefinito", diff --git a/locales/ja/common.json b/locales/ja/common.json index 938cf6ec..f7c60259 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -861,7 +861,15 @@ "archive": "アーカイブ", "tag": "タグ", "spam": "スパムとしてマーク", - "none_selected": "アクションが選択されていません" + "none_selected": "アクションが選択されていません", + "mode_label": "表示モード", + "mode_inline": "インライン", + "mode_floating": "フローティング", + "corner_label": "フローティング位置", + "corner_top-left": "左上", + "corner_top-right": "右上", + "corner_bottom-left": "左下", + "corner_bottom-right": "右下" }, "default_mail_program": { "label": "既定のメールプログラム", diff --git a/locales/nl/common.json b/locales/nl/common.json index 4379a8b9..4eafbaa4 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -861,7 +861,15 @@ "archive": "Archiveren", "tag": "Label", "spam": "Markeer als spam", - "none_selected": "Geen acties geselecteerd" + "none_selected": "Geen acties geselecteerd", + "mode_label": "Weergavemodus", + "mode_inline": "Inline", + "mode_floating": "Zwevend", + "corner_label": "Zwevende positie", + "corner_top-left": "Linksboven", + "corner_top-right": "Rechtsboven", + "corner_bottom-left": "Linksonder", + "corner_bottom-right": "Rechtsonder" }, "default_mail_program": { "label": "Standaard e-mailprogramma", diff --git a/locales/pt/common.json b/locales/pt/common.json index 042486a3..92dbfb69 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -861,7 +861,15 @@ "archive": "Arquivar", "tag": "Etiqueta", "spam": "Marcar como spam", - "none_selected": "Nenhuma ação selecionada" + "none_selected": "Nenhuma ação selecionada", + "mode_label": "Modo de exibição", + "mode_inline": "Em linha", + "mode_floating": "Flutuante", + "corner_label": "Posição flutuante", + "corner_top-left": "Superior esquerdo", + "corner_top-right": "Superior direito", + "corner_bottom-left": "Inferior esquerdo", + "corner_bottom-right": "Inferior direito" }, "default_mail_program": { "label": "Programa de e-mail padrão", diff --git a/locales/ru/common.json b/locales/ru/common.json index 5e5cc306..731dec7a 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -861,7 +861,15 @@ "archive": "Архивировать", "tag": "Тег", "spam": "Отметить как спам", - "none_selected": "Действия не выбраны" + "none_selected": "Действия не выбраны", + "mode_label": "Режим отображения", + "mode_inline": "Встроенный", + "mode_floating": "Плавающий", + "corner_label": "Позиция плавающих действий", + "corner_top-left": "Вверху слева", + "corner_top-right": "Вверху справа", + "corner_bottom-left": "Внизу слева", + "corner_bottom-right": "Внизу справа" }, "default_mail_program": { "label": "Почтовая программа по умолчанию", diff --git a/stores/settings-store.ts b/stores/settings-store.ts index caaede37..68a0f205 100644 --- a/stores/settings-store.ts +++ b/stores/settings-store.ts @@ -35,6 +35,8 @@ export type ToolbarPosition = 'top' | 'below-subject'; export type ArchiveMode = 'single' | 'year' | 'month'; export type HoverAction = 'delete' | 'star' | 'markRead' | 'archive' | 'tag' | 'spam'; +export type HoverActionsMode = 'inline' | 'floating'; +export type HoverActionsCorner = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'; export const ALL_HOVER_ACTIONS: { id: HoverAction; labelKey: string }[] = [ { id: 'delete', labelKey: 'delete' }, @@ -110,6 +112,8 @@ interface SettingsState { emailAlwaysLightMode: boolean; // Always render email content in light mode archiveMode: ArchiveMode; // How to organize archived emails: single folder, by year, or by year+month hoverActions: HoverAction[]; // Quick actions shown on hover in mail list + hoverActionsMode: HoverActionsMode; // Display mode: inline (current) or floating corner + hoverActionsCorner: HoverActionsCorner; // Corner for floating mode // Composer autoSaveDraftInterval: number; // milliseconds @@ -226,6 +230,8 @@ const DEFAULT_SETTINGS = { emailAlwaysLightMode: false, archiveMode: 'single' as ArchiveMode, hoverActions: ['delete', 'star', 'markRead', 'archive'] as HoverAction[], + hoverActionsMode: 'inline' as HoverActionsMode, + hoverActionsCorner: 'top-right' as HoverActionsCorner, // Composer autoSaveDraftInterval: 60000, // 1 minute @@ -331,6 +337,8 @@ export const useSettingsStore = create()( attachmentPosition: state.attachmentPosition, archiveMode: state.archiveMode, hoverActions: state.hoverActions, + hoverActionsMode: state.hoverActionsMode, + hoverActionsCorner: state.hoverActionsCorner, disableThreading: state.disableThreading, trustedSenders: state.trustedSenders, autoSaveDraftInterval: state.autoSaveDraftInterval,