Merge branch 'main' into feature/scheduled-send

# Conflicts:
#	app/(main)/[locale]/page.tsx
#	components/layout/sidebar.tsx
#	stores/email-store.ts
#	stores/settings-store.ts
This commit is contained in:
Lucas Gaitzsch
2026-05-22 12:31:06 +02:00
155 changed files with 4702 additions and 869 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ interface ProComposeTabBodyProps {
/**
* Renders a standalone `<EmailComposer />` inside its own Pro tab. Sending,
* draft autosave, and discard all flow through the shared `email-store`, so
* the result is identical to composing inline in the mail page the
* the result is identical to composing inline in the mail page - the
* composer is just hosted in its own tab instead of in the right pane.
*/
export function ProComposeTabBody({ tabId, data }: ProComposeTabBodyProps) {
+2 -2
View File
@@ -39,7 +39,7 @@ function buildReplyContext(email: Email): ProReplyContext {
/**
* Renders a single email in its own Pro tab. Fetches the email content on
* mount via `email-store.fetchEmailContent` so the tab is self-sufficient
* mount via `email-store.fetchEmailContent` so the tab is self-sufficient -
* it doesn't depend on what the Mail tab has selected.
*/
export function ProEmailTabBody({ tabId, data }: ProEmailTabBodyProps) {
@@ -160,7 +160,7 @@ export function ProEmailTabBody({ tabId, data }: ProEmailTabBodyProps) {
if (!client || !email) return;
try {
await toggleStar(client, email.id);
// Reflect locally the viewer re-reads from email-store's selectedEmail
// Reflect locally - the viewer re-reads from email-store's selectedEmail
// shape only for the mail tab; here we update our local copy too.
setEmail((prev) => prev ? {
...prev,
+38
View File
@@ -0,0 +1,38 @@
"use client";
import { useEffect } from "react";
import { usePathname, useRouter } from "@/i18n/navigation";
import { useSettingsStore } from "@/stores/settings-store";
import { useIsDesktop } from "@/hooks/use-media-query";
import { useProTabStore, type ProTabKind } from "@/stores/pro-tab-store";
const STANDARD_PATH_TO_TAB: Record<string, Exclude<ProTabKind, 'compose' | 'email'>> = {
'/': 'mail',
'/calendar': 'calendar',
'/contacts': 'contacts',
'/files': 'files',
'/settings': 'settings',
};
/**
* When the Pro interface is enabled, the standard mail/calendar/contacts/
* files/settings routes are taken over by the Pro shell - the user shouldn't
* have to click "Open" in settings to land there. Mobile/tablet keeps the
* standard layout because Pro is desktop-only (see pro/page.tsx).
*/
export function ProInterfaceRedirect() {
const router = useRouter();
const pathname = usePathname();
const proInterface = useSettingsStore((s) => s.proInterface);
const isDesktop = useIsDesktop();
useEffect(() => {
if (!proInterface || !isDesktop) return;
const tabKind = STANDARD_PATH_TO_TAB[pathname];
if (!tabKind) return;
useProTabStore.getState().openTab(tabKind);
router.replace('/pro');
}, [proInterface, isDesktop, pathname, router]);
return null;
}