fix: clear identity signature fields when emptied

This commit is contained in:
Linus Rath
2026-05-18 00:53:54 +02:00
parent 7a72903632
commit ed6b5d5f33
5 changed files with 40 additions and 33 deletions
+14 -12
View File
@@ -36,10 +36,10 @@ function truncateToUtf8Bytes(s: string, maxBytes: number): string {
interface IdentityFormData {
name: string;
email: string;
replyTo?: EmailAddress[];
bcc?: EmailAddress[];
textSignature?: string;
htmlSignature?: string;
replyTo?: EmailAddress[] | null;
bcc?: EmailAddress[] | null;
textSignature?: string | null;
htmlSignature?: string | null;
}
interface IdentityFormProps {
@@ -121,14 +121,16 @@ export function IdentityForm({ identity, onSave, onCancel }: IdentityFormProps)
setIsSubmitting(true);
try {
// Sanitize HTML signature before sending to server
// JMAP needs explicit null to clear a field; undefined would be dropped
// from the JSON payload and leave the server-side value untouched.
const trimmedText = formData.textSignature?.trim() ?? '';
const trimmedHtml = formData.htmlSignature?.trim() ?? '';
const sanitizedData: IdentityFormData = {
...formData,
replyTo: parseEmailList(replyToInput),
bcc: parseEmailList(bccInput),
htmlSignature: formData.htmlSignature
? sanitizeSignatureHtml(formData.htmlSignature)
: undefined,
textSignature: trimmedText ? formData.textSignature : null,
htmlSignature: trimmedHtml ? sanitizeSignatureHtml(formData.htmlSignature!) : null,
replyTo: parseEmailList(replyToInput) ?? null,
bcc: parseEmailList(bccInput) ?? null,
};
await onSave(sanitizedData);
@@ -271,7 +273,7 @@ export function IdentityForm({ identity, onSave, onCancel }: IdentityFormProps)
</label>
<textarea
id="identity-text-sig"
value={formData.textSignature}
value={formData.textSignature ?? ''}
onChange={(e) => setFormData({ ...formData, textSignature: truncateToUtf8Bytes(e.target.value, SIGNATURE_MAX_BYTES) })}
rows={3}
disabled={isSubmitting}
@@ -289,7 +291,7 @@ export function IdentityForm({ identity, onSave, onCancel }: IdentityFormProps)
</label>
<textarea
id="identity-html-sig"
value={formData.htmlSignature}
value={formData.htmlSignature ?? ''}
onChange={(e) => setFormData({ ...formData, htmlSignature: truncateToUtf8Bytes(e.target.value, SIGNATURE_MAX_BYTES) })}
rows={5}
disabled={isSubmitting}
@@ -32,10 +32,10 @@ function emailMatchesUsername(email: string, username: string): boolean {
interface IdentityFormData {
name: string;
email: string;
replyTo?: EmailAddress[];
bcc?: EmailAddress[];
textSignature?: string;
htmlSignature?: string;
replyTo?: EmailAddress[] | null;
bcc?: EmailAddress[] | null;
textSignature?: string | null;
htmlSignature?: string | null;
}
interface IdentityManagerModalProps {
+8 -3
View File
@@ -530,7 +530,7 @@ export class DemoJMAPClient implements IJMAPClient {
async createIdentity(
name: string, email: string,
replyTo?: EmailAddress[] | null, bcc?: EmailAddress[] | null,
htmlSignature?: string, textSignature?: string,
textSignature?: string | null, htmlSignature?: string | null,
): Promise<Identity> {
const identity: Identity = {
id: generateDemoId('identity'), name, email,
@@ -542,9 +542,14 @@ export class DemoJMAPClient implements IJMAPClient {
return identity;
}
async updateIdentity(identityId: string, updates: { name?: string; replyTo?: EmailAddress[] | null; bcc?: EmailAddress[] | null; htmlSignature?: string; textSignature?: string }): Promise<void> {
async updateIdentity(identityId: string, updates: { name?: string | null; replyTo?: EmailAddress[] | null; bcc?: EmailAddress[] | null; textSignature?: string | null; htmlSignature?: string | null }): Promise<void> {
const identity = this.data.identities.find(i => i.id === identityId);
if (identity) Object.assign(identity, updates);
if (!identity) return;
if (updates.name !== undefined) identity.name = updates.name ?? '';
if (updates.replyTo !== undefined) identity.replyTo = updates.replyTo ?? undefined;
if (updates.bcc !== undefined) identity.bcc = updates.bcc ?? undefined;
if (updates.textSignature !== undefined) identity.textSignature = updates.textSignature ?? '';
if (updates.htmlSignature !== undefined) identity.htmlSignature = updates.htmlSignature ?? '';
}
async deleteIdentity(identityId: string): Promise<void> {
+5 -5
View File
@@ -183,17 +183,17 @@ export interface IJMAPClient {
email: string,
replyTo?: EmailAddress[] | null,
bcc?: EmailAddress[] | null,
htmlSignature?: string,
textSignature?: string,
textSignature?: string | null,
htmlSignature?: string | null,
): Promise<Identity>;
updateIdentity(
identityId: string,
updates: {
name?: string;
name?: string | null;
replyTo?: EmailAddress[] | null;
bcc?: EmailAddress[] | null;
htmlSignature?: string;
textSignature?: string;
textSignature?: string | null;
htmlSignature?: string | null;
},
): Promise<void>;
deleteIdentity(identityId: string): Promise<void>;
+9 -9
View File
@@ -1813,10 +1813,10 @@ export class JMAPClient implements IJMAPClient {
async createIdentity(
name: string,
email: string,
replyTo?: EmailAddress[],
bcc?: EmailAddress[],
textSignature?: string,
htmlSignature?: string
replyTo?: EmailAddress[] | null,
bcc?: EmailAddress[] | null,
textSignature?: string | null,
htmlSignature?: string | null
): Promise<Identity> {
const response = await this.request([
["Identity/set", {
@@ -1859,11 +1859,11 @@ export class JMAPClient implements IJMAPClient {
async updateIdentity(
identityId: string,
updates: {
name?: string;
replyTo?: EmailAddress[];
bcc?: EmailAddress[];
textSignature?: string;
htmlSignature?: string;
name?: string | null;
replyTo?: EmailAddress[] | null;
bcc?: EmailAddress[] | null;
textSignature?: string | null;
htmlSignature?: string | null;
}
): Promise<void> {
const response = await this.request([