mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 08:06:13 +00:00
87 lines
3.4 KiB
TypeScript
87 lines
3.4 KiB
TypeScript
// "Schedule send" presets and the release time of a scheduled message.
|
|
// Ports of the webmail's lib/schedule-presets.ts and
|
|
// lib/scheduled-send-label.ts.
|
|
|
|
import { intlLocale } from './intl-locale';
|
|
|
|
export type SchedulePresetKey = 'this_morning' | 'this_afternoon' | 'tomorrow_morning' | 'tomorrow_afternoon' | 'monday_morning';
|
|
|
|
export interface SchedulePreset {
|
|
key: SchedulePresetKey;
|
|
date: Date;
|
|
}
|
|
|
|
function at(base: Date, daysAhead: number, hour: number): Date {
|
|
const date = new Date(base);
|
|
date.setDate(date.getDate() + daysAhead);
|
|
date.setHours(hour, 0, 0, 0);
|
|
return date;
|
|
}
|
|
|
|
/** How far ahead a time for today must be to be offered, so it is not past by the tap. */
|
|
const TODAY_LEAD_MS = 5 * 60_000;
|
|
|
|
/**
|
|
* One-tap times for "Schedule send": tomorrow at 8:00 and 13:00, and next
|
|
* Monday at 8:00. Monday is left out when it is tomorrow anyway (on a
|
|
* Sunday). Today's 8:00 and 13:00 come first while they are still ahead, so
|
|
* a message written after midnight can go out the same morning (#1390).
|
|
*/
|
|
export function schedulePresets(now: Date = new Date()): SchedulePreset[] {
|
|
const presets: SchedulePreset[] = [
|
|
{ key: 'this_morning' as const, date: at(now, 0, 8) },
|
|
{ key: 'this_afternoon' as const, date: at(now, 0, 13) },
|
|
].filter((preset) => preset.date.getTime() - now.getTime() >= TODAY_LEAD_MS);
|
|
presets.push(
|
|
{ key: 'tomorrow_morning', date: at(now, 1, 8) },
|
|
{ key: 'tomorrow_afternoon', date: at(now, 1, 13) },
|
|
);
|
|
const daysToMonday = ((8 - now.getDay()) % 7) || 7;
|
|
if (daysToMonday > 1) presets.push({ key: 'monday_morning', date: at(now, daysToMonday, 8) });
|
|
return presets;
|
|
}
|
|
|
|
/** The label of a "Schedule send" preset (webmail email_composer.schedule_preset). */
|
|
export function schedulePresetLabel(
|
|
key: SchedulePresetKey,
|
|
t: (key: string, fallback?: string) => string,
|
|
): string {
|
|
switch (key) {
|
|
case 'this_morning': return t('email_composer.schedule_preset.this_morning', 'This morning');
|
|
case 'this_afternoon': return t('email_composer.schedule_preset.this_afternoon', 'This afternoon');
|
|
case 'tomorrow_morning': return t('email_composer.schedule_preset.tomorrow_morning', 'Tomorrow morning');
|
|
case 'tomorrow_afternoon': return t('email_composer.schedule_preset.tomorrow_afternoon', 'Tomorrow afternoon');
|
|
case 'monday_morning': return t('email_composer.schedule_preset.monday_morning', 'Monday morning');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The release time of a scheduled message, for lists, banners and the
|
|
* "Scheduled" confirmation.
|
|
*
|
|
* The server can land a second before the minute the user picked (08:00
|
|
* showed as 07:59), so the time is rounded to the nearest minute. A message
|
|
* that is not due today also shows its date; a bare "07:59" for tomorrow
|
|
* morning read like a time that had already passed.
|
|
*/
|
|
export function formatScheduledSendAt(
|
|
sendAt: string,
|
|
timeFormat: '12h' | '24h',
|
|
locale?: string,
|
|
now: Date = new Date(),
|
|
): string {
|
|
const ms = Date.parse(sendAt);
|
|
if (!Number.isFinite(ms)) return sendAt;
|
|
const rounded = new Date(Math.round(ms / 60_000) * 60_000);
|
|
const sameDay = rounded.toDateString() === now.toDateString();
|
|
const time = { hour: '2-digit', minute: '2-digit', hour12: timeFormat === '12h' } as const;
|
|
const options: Intl.DateTimeFormatOptions = sameDay
|
|
? time
|
|
: { ...time, weekday: 'short', month: 'short', day: 'numeric' };
|
|
try {
|
|
return rounded.toLocaleString(intlLocale(locale), options);
|
|
} catch {
|
|
return rounded.toLocaleString();
|
|
}
|
|
}
|