feat: enhance compose functionality with button integration and translations

This commit is contained in:
Linus Rath
2026-03-28 22:53:10 +01:00
parent 1ba8e2fd47
commit 8d7cd26fa9
4 changed files with 33 additions and 28 deletions
+21 -14
View File
@@ -1497,20 +1497,23 @@ export default function Home() {
</ErrorBoundary> </ErrorBoundary>
</div> </div>
{/* Floating Compose Button (mobile) */} {/* Floating Compose Button */}
{isMobile && ( <Button
<Button onClick={() => {
onClick={() => { setComposerMode('compose');
setComposerMode('compose'); setShowComposer(true);
setShowComposer(true); if (isMobile) setActiveView('viewer');
setActiveView('viewer'); }}
}} className={cn(
className="absolute bottom-4 right-4 z-40 h-14 w-14 rounded-full shadow-lg" "absolute z-40 rounded-full shadow-lg",
aria-label={t('sidebar.compose')} isMobile ? "bottom-4 right-4 h-14 w-14" : "bottom-4 right-4 h-12 w-12"
> )}
<PenSquare className="h-6 w-6" /> aria-label={t('sidebar.compose')}
</Button> title={t('sidebar.compose_hint')}
)} data-tour="compose-button"
>
<PenSquare className={isMobile ? "h-6 w-6" : "h-5 w-5"} />
</Button>
</div> </div>
{/* Email list resize handle (desktop only) */} {/* Email list resize handle (desktop only) */}
@@ -1665,6 +1668,10 @@ export default function Home() {
onNavigatePrev={handleNavigatePrev} onNavigatePrev={handleNavigatePrev}
onShowShortcuts={() => setShowShortcutsModal(true)} onShowShortcuts={() => setShowShortcutsModal(true)}
onEditDraft={handleEditDraft} onEditDraft={handleEditDraft}
onCompose={() => {
setComposerMode('compose');
setShowComposer(true);
}}
currentUserEmail={client?.getUsername()} currentUserEmail={client?.getUsername()}
currentUserName={client?.getUsername()?.split("@")[0]} currentUserName={client?.getUsername()?.split("@")[0]}
currentMailboxRole={mailboxes.find(m => m.id === selectedMailbox)?.role} currentMailboxRole={mailboxes.find(m => m.id === selectedMailbox)?.role}
+9
View File
@@ -68,6 +68,7 @@ import {
HelpCircle, HelpCircle,
EditIcon, EditIcon,
PlayCircle, PlayCircle,
PenSquare,
} from "lucide-react"; } from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import type { Attachment as PostalMimeAttachment } from 'postal-mime'; import type { Attachment as PostalMimeAttachment } from 'postal-mime';
@@ -121,6 +122,7 @@ interface EmailViewerProps {
onNavigatePrev?: () => void; onNavigatePrev?: () => void;
onShowShortcuts?: () => void; onShowShortcuts?: () => void;
onEditDraft?: () => void; onEditDraft?: () => void;
onCompose?: () => void;
currentUserEmail?: string; currentUserEmail?: string;
currentUserName?: string; currentUserName?: string;
currentMailboxRole?: string; currentMailboxRole?: string;
@@ -865,6 +867,7 @@ export function EmailViewer({
onNavigatePrev, onNavigatePrev,
onShowShortcuts, onShowShortcuts,
onEditDraft, onEditDraft,
onCompose,
currentUserEmail, currentUserEmail,
currentUserName, currentUserName,
currentMailboxRole, currentMailboxRole,
@@ -2836,6 +2839,12 @@ export function EmailViewer({
</div> </div>
<h3 className="text-xl font-semibold text-foreground mb-2">{t('no_conversation_selected')}</h3> <h3 className="text-xl font-semibold text-foreground mb-2">{t('no_conversation_selected')}</h3>
<p className="text-muted-foreground">{t('no_conversation_description')}</p> <p className="text-muted-foreground">{t('no_conversation_description')}</p>
{onCompose && (
<Button onClick={onCompose} className="mt-6" title={t('compose_hint')}>
<PenSquare className="w-4 h-4 mr-2" />
{t('compose')}
</Button>
)}
</div> </div>
</div> </div>
); );
+1 -14
View File
@@ -12,7 +12,6 @@ import {
Star, Star,
Trash2, Trash2,
Archive, Archive,
PenSquare,
ChevronsLeft, ChevronsLeft,
ChevronsRight, ChevronsRight,
ChevronRight, ChevronRight,
@@ -762,19 +761,7 @@ export function Sidebar({
{!isCollapsed && <PluginSlot name="sidebar-widget" className="border-t border-border" />} {!isCollapsed && <PluginSlot name="sidebar-widget" className="border-t border-border" />}
</div> </div>
{/* Compose Button */}
<div className={cn("border-t border-border", isCollapsed ? "flex justify-center py-3" : "px-3 py-3")}>
{isCollapsed ? (
<Button onClick={onCompose} variant="ghost" size="icon" title={t("compose_hint")} data-tour="compose-button">
<PenSquare className="w-5 h-5" />
</Button>
) : (
<Button onClick={onCompose} className="w-full" title={t("compose_hint")} data-tour="compose-button">
<PenSquare className="w-4 h-4 mr-2" />
{t("compose")}
</Button>
)}
</div>
</div> </div>
); );
} }
+2
View File
@@ -197,6 +197,8 @@
"no_email_description": "Select an email from the list to view it here", "no_email_description": "Select an email from the list to view it here",
"no_conversation_selected": "No conversation selected", "no_conversation_selected": "No conversation selected",
"no_conversation_description": "Choose a conversation from the list to read it here", "no_conversation_description": "Choose a conversation from the list to read it here",
"compose": "Compose",
"compose_hint": "Compose new message",
"no_subject": "(No Subject)", "no_subject": "(No Subject)",
"loading_email": "Loading email...", "loading_email": "Loading email...",
"loading": "Loading...", "loading": "Loading...",