import { useSettings, type ReadReceiptPolicy } from "@/store/settings";
import { Switch } from "@/ui/misc";
import { browserTimeZone, listTimeZones } from "@/lib/dates";
import { toast } from "@/ui/toast";
import { useState } from "react";
import { t } from "@/lib/i18n";
import {
canUnregisterMailtoHandler,
isInstalledApp,
mailtoHandlerRequested,
mailtoHandlerSupport,
registerMailtoHandler,
unregisterMailtoHandler,
} from "@/lib/mailhandler";
import {
browserLocale,
formatClock,
formatDate,
formatFullDateTime,
getServerLocale,
localeLabel,
localeOptions,
withPrefs,
type DateFormat,
} from "@/lib/datetime";
/** Illustrative instant used for the format previews: 22 Nov 2025, 18:23. */
const SAMPLE = new Date(2025, 10, 22, 18, 23);
const DATE_FORMATS: Array<{ value: DateFormat; label: string }> = [
{ value: "auto", label: "Automatic" },
{ value: "dmy-dot", label: "Day.Month.Year" },
{ value: "dmy-slash", label: "Day/Month/Year" },
{ value: "mdy-slash", label: "Month/Day/Year" },
{ value: "ymd-dash", label: "Year-Month-Day (ISO 8601)" },
];
export function GeneralSettings() {
const s = useSettings((st) => st.settings);
const update = useSettings((st) => st.update);
const reset = useSettings((st) => st.reset);
const exportJson = useSettings((st) => st.exportJson);
const importJson = useSettings((st) => st.importJson);
const serverLocale = getServerLocale();
const autoLocale = serverLocale ?? browserLocale();
return (
{t("General")}
{t("Reading, sending and list behaviour. Settings are stored in this browser.")}
{t("Reading")}
update({ conversationMode: v })} label={t("Conversation view")} hint={t("Group messages from the same thread together.")} />
update({ showPreview: v })} label={t("Show message snippets")} hint={t("Preview the first line of each message in the list.")} />
update({ showAvatars: v })} label={t("Show sender avatars")} />
update({ confirmDelete: v })} label={t("Confirm before deleting")} />
{t("Composing")}
update({ includeQuote: v })} label={t("Quote original message in replies")} />
update({ signatureAboveQuote: v })} label={t("Place signature above quoted text")} />
update({ attachmentReminder: v })} label={t("Attachment reminder")} hint={t("Warn when the message mentions an attachment but none is attached.")} />
update({ requestReadReceipt: v })} label={t("Always request read receipts")} />
{t("A receipt tells whoever asked that this address is live and when the message was read, and the sender chooses where it goes — so there is no automatic option. Bulk mail, mailing lists and anything marked auto-submitted are never offered one at all.")}
update({ spellcheck: v })} label={t("Spell check while typing")} />
{t("Locale")}
{serverLocale ? `Your mail server reports ${localeLabel(serverLocale)} (${serverLocale}).` : "Your mail server does not report a locale, so the browser's is used."} Dates, times and month names follow this choice.
Preview: {formatFullDateTime(SAMPLE)}
{t("Default mail app")}
{t("Backup")}
);
}
/**
* Offer ihasmail as the browser's handler for `mailto:` links. The browser
* owns the decision, and nothing can read the answer back, so this states what
* it can and points at the browser's own settings for the rest.
*/
function MailHandlerSettings() {
const support = mailtoHandlerSupport();
const [requested, setRequested] = useState(mailtoHandlerRequested);
const ask = () => {
try {
registerMailtoHandler();
setRequested(true);
toast.success("Your browser will ask whether to open mail links in ihasmail");
} catch (err) {
toast.error(`Your browser refused the request: ${(err as Error).message}`);
}
};
const remove = () => {
unregisterMailtoHandler();
setRequested(false);
toast.show("Removed. Mail links will open in whatever your browser falls back to.");
};
if (support === "unsupported") {
return
This browser cannot register apps for mailto: links. Safari, in particular, has no such API — you can still make ihasmail the default from your operating system if you install it as an app.
;
}
if (support === "insecure") {
return
Registering for mailto: links requires a secure (HTTPS) connection.
;
}
return (
<>
Open mailto: links — in web pages, documents and other apps — in ihasmail instead of a desktop mail client.
Your browser will ask you to confirm, and you can change it later in its own settings (Chrome: Settings › Privacy and security › Site settings › Protocol handlers; Firefox: Settings › General › Applications).
{requested && canUnregisterMailtoHandler() && }
{requested &&
{t("Requested in this browser. Whether it took effect is up to the browser — check its settings if mail links still open elsewhere.")}
}
{!isInstalledApp() && (
{t("For a system-wide default, install ihasmail as an app first (in Chrome: the install icon in the address bar). Your operating system can then offer ihasmail directly wherever it asks which mail app to use.")}