fix(signatures): apply reply signature to replies and forwards
Publish Docker Image / prepare (push) Successful in 3s
Publish Docker Image / build (linux/amd64, ubuntu-latest) (push) Failing after 19s
Publish Docker Image / build (linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
Publish Docker Image / merge (push) Canceled after 0s
Publish Docker Image / prepare (push) Successful in 3s
Publish Docker Image / build (linux/amd64, ubuntu-latest) (push) Failing after 19s
Publish Docker Image / build (linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
Publish Docker Image / merge (push) Canceled after 0s
This commit is contained in:
@@ -61,6 +61,7 @@ import { Input } from "@/components/ui/input";
|
|||||||
import { FilePreviewModal } from "@/components/files/file-preview-modal";
|
import { FilePreviewModal } from "@/components/files/file-preview-modal";
|
||||||
import { isFilePreviewable } from "@/lib/file-preview";
|
import { isFilePreviewable } from "@/lib/file-preview";
|
||||||
import { appendHtmlSignature, appendPlainTextSignature } from "@/lib/signature-utils";
|
import { appendHtmlSignature, appendPlainTextSignature } from "@/lib/signature-utils";
|
||||||
|
import { useSignatureStore } from "@/stores/signature-store";
|
||||||
import { computeReplyThreadingHeaders } from "@/lib/email-threading";
|
import { computeReplyThreadingHeaders } from "@/lib/email-threading";
|
||||||
import { EML_IMPORT_ACCEPT, expandImportableEmails } from "@/lib/eml-import";
|
import { EML_IMPORT_ACCEPT, expandImportableEmails } from "@/lib/eml-import";
|
||||||
import { findDraftIdentityId, resolveReplyFrom, type ReplyFromResolution } from "@/lib/reply-identity";
|
import { findDraftIdentityId, resolveReplyFrom, type ReplyFromResolution } from "@/lib/reply-identity";
|
||||||
@@ -2615,8 +2616,16 @@ export default function Home() {
|
|||||||
|
|
||||||
// Append signature from the sending identity (fall back to primary
|
// Append signature from the sending identity (fall back to primary
|
||||||
// when the reply-from lives on the same identity but a different alias).
|
// when the reply-from lives on the same identity but a different alias).
|
||||||
|
// The signature store's reply signature takes precedence over the legacy
|
||||||
|
// identity signature, matching the composer's send path.
|
||||||
|
const signatureStore = useSignatureStore.getState();
|
||||||
|
const replySigId = signatureStore.getIdentityReplySignatureId(sendingIdentity?.id ?? '');
|
||||||
|
const replySig = replySigId ? signatureStore.getSignatureById(replySigId) : undefined;
|
||||||
|
const signatureSource = replySig
|
||||||
|
? { htmlSignature: replySig.body, textSignature: replySig.plainText }
|
||||||
|
: sendingIdentity;
|
||||||
const separator = useSettingsStore.getState().signatureSeparatorEnabled;
|
const separator = useSettingsStore.getState().signatureSeparatorEnabled;
|
||||||
const finalBody = appendPlainTextSignature(body, sendingIdentity, { separator });
|
const finalBody = appendPlainTextSignature(body, signatureSource, { separator });
|
||||||
|
|
||||||
// When the identity has an HTML signature, send a matching HTML body so the
|
// When the identity has an HTML signature, send a matching HTML body so the
|
||||||
// signature keeps its formatting; appendPlainTextSignature would otherwise
|
// signature keeps its formatting; appendPlainTextSignature would otherwise
|
||||||
@@ -2627,8 +2636,8 @@ export default function Home() {
|
|||||||
.replace(/</g, '<')
|
.replace(/</g, '<')
|
||||||
.replace(/>/g, '>')
|
.replace(/>/g, '>')
|
||||||
.replace(/\n/g, '<br>');
|
.replace(/\n/g, '<br>');
|
||||||
const finalHtmlBody = sendingIdentity?.htmlSignature?.trim()
|
const finalHtmlBody = signatureSource?.htmlSignature?.trim()
|
||||||
? appendHtmlSignature(`<div>${escapedBody}</div>`, sendingIdentity, { separator })
|
? appendHtmlSignature(`<div>${escapedBody}</div>`, signatureSource, { separator })
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const originalEmailId = selectedEmail.id;
|
const originalEmailId = selectedEmail.id;
|
||||||
|
|||||||
@@ -653,6 +653,15 @@ export function EmailComposer({
|
|||||||
? currentIdentity
|
? currentIdentity
|
||||||
: primaryIdentity;
|
: primaryIdentity;
|
||||||
|
|
||||||
|
// The signature store (default/reply/per-identity) takes precedence over the
|
||||||
|
// legacy per-identity html/text signature. `selectedSignature` is resolved in
|
||||||
|
// resolveStoreSignatureId for the current mode (compose → default; reply/
|
||||||
|
// forward → reply), so replies and forwards pick up the reply signature.
|
||||||
|
// Falls back to the legacy identity signature when no store signature is set.
|
||||||
|
const effectiveSignature = selectedSignature
|
||||||
|
? { htmlSignature: selectedSignature.body, textSignature: selectedSignature.plainText }
|
||||||
|
: signatureIdentity;
|
||||||
|
|
||||||
// Hold the TipTap editor instance so we can swap the embedded signature
|
// Hold the TipTap editor instance so we can swap the embedded signature
|
||||||
// when the user switches identity in "above quote" mode without rebuilding
|
// when the user switches identity in "above quote" mode without rebuilding
|
||||||
// the whole body (which would lose user edits to the surrounding draft).
|
// the whole body (which would lose user edits to the surrounding draft).
|
||||||
@@ -1883,6 +1892,7 @@ export function EmailComposer({
|
|||||||
// duplicate it.
|
// duplicate it.
|
||||||
const signatureAlreadyInBody =
|
const signatureAlreadyInBody =
|
||||||
shouldEmbedSignatureInNewMail ||
|
shouldEmbedSignatureInNewMail ||
|
||||||
|
(!plainTextMode && !!selectedSignature && mode === 'compose') ||
|
||||||
((mode === 'reply' || mode === 'replyAll' || mode === 'forward') &&
|
((mode === 'reply' || mode === 'replyAll' || mode === 'forward') &&
|
||||||
signaturePosition === 'above_quote');
|
signaturePosition === 'above_quote');
|
||||||
|
|
||||||
@@ -1890,11 +1900,11 @@ export function EmailComposer({
|
|||||||
const buildSignatureHtml = (): string => {
|
const buildSignatureHtml = (): string => {
|
||||||
if (signatureAlreadyInBody) return '';
|
if (signatureAlreadyInBody) return '';
|
||||||
const sep = signatureSeparatorEnabled ? `<br><br>-- <br>` : `<br><br>`;
|
const sep = signatureSeparatorEnabled ? `<br><br>-- <br>` : `<br><br>`;
|
||||||
if (signatureIdentity?.htmlSignature) {
|
if (effectiveSignature?.htmlSignature) {
|
||||||
return `${sep}${sanitizeSignatureHtml(signatureIdentity.htmlSignature)}`;
|
return `${sep}${sanitizeSignatureHtml(effectiveSignature.htmlSignature)}`;
|
||||||
}
|
}
|
||||||
if (signatureIdentity?.textSignature) {
|
if (effectiveSignature?.textSignature) {
|
||||||
return `${sep}${signatureIdentity.textSignature.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br>')}`;
|
return `${sep}${effectiveSignature.textSignature.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br>')}`;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
@@ -1907,8 +1917,8 @@ export function EmailComposer({
|
|||||||
// In plain text mode, send text/plain only (no HTML body)
|
// In plain text mode, send text/plain only (no HTML body)
|
||||||
const signatureOpts = { separator: signatureSeparatorEnabled };
|
const signatureOpts = { separator: signatureSeparatorEnabled };
|
||||||
const finalBody = plainTextMode
|
const finalBody = plainTextMode
|
||||||
? (signatureAlreadyInBody ? body : appendPlainTextSignature(body, signatureIdentity, signatureOpts))
|
? (signatureAlreadyInBody ? body : appendPlainTextSignature(body, effectiveSignature, signatureOpts))
|
||||||
: (signatureAlreadyInBody ? htmlToPlainText(body) : appendPlainTextSignature(htmlToPlainText(body), signatureIdentity, signatureOpts));
|
: (signatureAlreadyInBody ? htmlToPlainText(body) : appendPlainTextSignature(htmlToPlainText(body), effectiveSignature, signatureOpts));
|
||||||
|
|
||||||
const rewritten = plainTextMode ? null : rewriteInlineImages(body);
|
const rewritten = plainTextMode ? null : rewriteInlineImages(body);
|
||||||
const finalHtmlBody = plainTextMode
|
const finalHtmlBody = plainTextMode
|
||||||
|
|||||||
Reference in New Issue
Block a user