fixes from review
This commit is contained in:
@@ -117,6 +117,30 @@ export default function Home() {
|
||||
const sendDelaySeconds = useSettingsStore((state) => state.sendDelaySeconds);
|
||||
const { loadTrustedSendersBook, trustedSendersLoaded } = useContactStore();
|
||||
|
||||
const promptForRescheduleDelayedUntil = useCallback((): string | null => {
|
||||
const value = window.prompt(t('email_viewer.reschedule_prompt'));
|
||||
if (!value) return null;
|
||||
const time = new Date(value).getTime();
|
||||
if (!Number.isFinite(time)) {
|
||||
toast.error(t('email_composer.schedule_send_invalid'));
|
||||
return null;
|
||||
}
|
||||
if (time <= Date.now()) {
|
||||
toast.error(t('email_composer.schedule_send_future'));
|
||||
return null;
|
||||
}
|
||||
if (!client?.hasDelayedSend()) {
|
||||
toast.error(t('email_composer.schedule_send_unsupported'));
|
||||
return null;
|
||||
}
|
||||
const maxDelayedSend = client.getMaxDelayedSend();
|
||||
if (maxDelayedSend > 0 && time > Date.now() + maxDelayedSend * 1000) {
|
||||
toast.error(t('email_composer.schedule_send_too_late'));
|
||||
return null;
|
||||
}
|
||||
return new Date(time).toISOString();
|
||||
}, [client, t]);
|
||||
|
||||
// Load trusted senders address book when feature is enabled
|
||||
useEffect(() => {
|
||||
if (trustedSendersAddressBook && client && !trustedSendersLoaded) {
|
||||
@@ -2721,6 +2745,12 @@ export default function Home() {
|
||||
setShowComposer(true);
|
||||
if (isMobile) setActiveView('viewer');
|
||||
}}
|
||||
onRescheduleScheduled={async (email) => {
|
||||
const delayedUntil = promptForRescheduleDelayedUntil();
|
||||
if (delayedUntil && client && email.emailSubmissionId && email.scheduledIdentityId) {
|
||||
await rescheduleScheduledEmail(client, email.emailSubmissionId, email.id, email.scheduledIdentityId, delayedUntil);
|
||||
}
|
||||
}}
|
||||
onEmailSelect={handleEmailSelect}
|
||||
onEmailDoubleClick={isEmbedded ? ((email) => {
|
||||
useProTabStore.getState().openEmailTab({
|
||||
|
||||
@@ -45,6 +45,7 @@ interface EmailListProps {
|
||||
onLoadMoreScheduled?: () => void;
|
||||
onCancelScheduled?: (email: Email) => void | Promise<void>;
|
||||
onCancelScheduledForEdit?: (email: Email) => void | Promise<void>;
|
||||
onRescheduleScheduled?: (email: Email) => void | Promise<void>;
|
||||
}
|
||||
|
||||
export function EmailList({
|
||||
@@ -73,6 +74,7 @@ export function EmailList({
|
||||
onLoadMoreScheduled,
|
||||
onCancelScheduled,
|
||||
onCancelScheduledForEdit,
|
||||
onRescheduleScheduled,
|
||||
}: EmailListProps) {
|
||||
const t = useTranslations('email_list');
|
||||
const { client } = useAuthStore();
|
||||
@@ -535,9 +537,9 @@ export function EmailList({
|
||||
onMarkAsSpam={() => onMarkAsSpam?.(contextMenu.data!)}
|
||||
onUndoSpam={() => onUndoSpam?.(contextMenu.data!)}
|
||||
onEditDraft={() => onEditDraft?.(contextMenu.data!)}
|
||||
onCancelScheduled={() => onCancelScheduled?.(contextMenu.data!)}
|
||||
onCancelScheduledForEdit={() => onCancelScheduledForEdit?.(contextMenu.data!)}
|
||||
onRescheduleScheduled={undefined}
|
||||
onCancelScheduled={onCancelScheduled ? () => onCancelScheduled(contextMenu.data!) : undefined}
|
||||
onCancelScheduledForEdit={onCancelScheduledForEdit ? () => onCancelScheduledForEdit(contextMenu.data!) : undefined}
|
||||
onRescheduleScheduled={onRescheduleScheduled ? () => onRescheduleScheduled(contextMenu.data!) : undefined}
|
||||
onBatchMarkAsRead={(read) => client && batchMarkAsRead(client, read)}
|
||||
onBatchDelete={() => client && batchDelete(client)}
|
||||
onBatchArchive={async () => {
|
||||
|
||||
@@ -335,16 +335,18 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
||||
</div>
|
||||
|
||||
{/* Hover Quick Actions */}
|
||||
<EmailHoverActions
|
||||
email={email}
|
||||
backgroundClassName={resolvedColorTag ? resolvedColorTag : ((selected || isChecked) ? "bg-accent" : "bg-muted")}
|
||||
onToggleStar={onToggleStar}
|
||||
onMarkAsRead={onMarkAsRead}
|
||||
onDelete={onDelete}
|
||||
onArchive={onArchive}
|
||||
onSetColorTag={onSetColorTag}
|
||||
onMarkAsSpam={onMarkAsSpam}
|
||||
/>
|
||||
{!email.isScheduled && (
|
||||
<EmailHoverActions
|
||||
email={email}
|
||||
backgroundClassName={resolvedColorTag ? resolvedColorTag : ((selected || isChecked) ? "bg-accent" : "bg-muted")}
|
||||
onToggleStar={onToggleStar}
|
||||
onMarkAsRead={onMarkAsRead}
|
||||
onDelete={onDelete}
|
||||
onArchive={onArchive}
|
||||
onSetColorTag={onSetColorTag}
|
||||
onMarkAsSpam={onMarkAsSpam}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -751,16 +753,18 @@ export const ThreadListItem = React.forwardRef<HTMLDivElement, ThreadListItemPro
|
||||
</div>
|
||||
|
||||
{/* Hover Quick Actions for thread header */}
|
||||
<EmailHoverActions
|
||||
email={latestEmail}
|
||||
backgroundClassName={colorTag ? colorTag : ((isSelected || isChecked) ? "bg-accent" : "bg-muted")}
|
||||
onToggleStar={onToggleStar ? () => onToggleStar(latestEmail) : undefined}
|
||||
onMarkAsRead={onMarkAsRead ? (read) => onMarkAsRead(latestEmail, read) : undefined}
|
||||
onDelete={onDelete ? () => onDelete(latestEmail) : undefined}
|
||||
onArchive={onArchive ? () => onArchive(latestEmail) : undefined}
|
||||
onSetColorTag={onSetColorTag ? (color) => onSetColorTag(latestEmail.id, color) : undefined}
|
||||
onMarkAsSpam={onMarkAsSpam ? () => onMarkAsSpam(latestEmail) : undefined}
|
||||
/>
|
||||
{!latestEmail.isScheduled && (
|
||||
<EmailHoverActions
|
||||
email={latestEmail}
|
||||
backgroundClassName={colorTag ? colorTag : ((isSelected || isChecked) ? "bg-accent" : "bg-muted")}
|
||||
onToggleStar={onToggleStar ? () => onToggleStar(latestEmail) : undefined}
|
||||
onMarkAsRead={onMarkAsRead ? (read) => onMarkAsRead(latestEmail, read) : undefined}
|
||||
onDelete={onDelete ? () => onDelete(latestEmail) : undefined}
|
||||
onArchive={onArchive ? () => onArchive(latestEmail) : undefined}
|
||||
onSetColorTag={onSetColorTag ? (color) => onSetColorTag(latestEmail.id, color) : undefined}
|
||||
onMarkAsSpam={onMarkAsSpam ? () => onMarkAsSpam(latestEmail) : undefined}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isExpanded && !isMobile && !isFocusedMailLayout && (
|
||||
|
||||
@@ -2566,6 +2566,15 @@ export const useEmailStore = create<EmailStore>((set, get) => ({
|
||||
const submissionId = email.emailSubmissionId;
|
||||
if (!submissionId) return null;
|
||||
await client.cancelEmailSubmission(submissionId);
|
||||
if (email.isSmimeScheduled) {
|
||||
await client.deleteEmail(email.id);
|
||||
set(state => ({
|
||||
selectedEmail: state.selectedEmail?.id === email.id ? null : state.selectedEmail,
|
||||
selectedEmailIds: new Set(Array.from(state.selectedEmailIds).filter(id => id !== email.id)),
|
||||
}));
|
||||
await get().fetchScheduledEmails(client);
|
||||
return null;
|
||||
}
|
||||
const mailboxes = get().mailboxes.length > 0 ? get().mailboxes : await client.getMailboxes();
|
||||
const draftsMailbox = mailboxes.find(mb => mb.role === 'drafts');
|
||||
const sentMailbox = mailboxes.find(mb => mb.role === 'sent');
|
||||
|
||||
Reference in New Issue
Block a user