mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 16:05:39 +00:00
fix: keep the text typed in quick reply when opening the full composer
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import type { Email } from '../../api/types';
|
||||
import { replyComposeParams } from '../reply-compose';
|
||||
|
||||
const source = {
|
||||
id: 'm1',
|
||||
threadId: 't1',
|
||||
mailboxIds: {},
|
||||
keywords: {},
|
||||
size: 1,
|
||||
receivedAt: '2026-10-14T10:00:00Z',
|
||||
subject: 'Hello',
|
||||
from: [{ name: 'Petra', email: 'petra@example.net' }],
|
||||
textBody: [{ partId: '1', type: 'text/plain' }],
|
||||
bodyValues: { 1: { value: 'Please confirm.' } },
|
||||
} as unknown as Email;
|
||||
|
||||
describe('replyComposeParams', () => {
|
||||
it('carries the text typed in quick reply into the composer', () => {
|
||||
const params = replyComposeParams('reply', source, undefined, 'Got it, thanks!');
|
||||
expect(params?.prefillBody).toBe('Got it, thanks!');
|
||||
expect(params?.replyTo?.from.email).toBe('petra@example.net');
|
||||
});
|
||||
|
||||
it('adds nothing when nothing was typed', () => {
|
||||
expect(replyComposeParams('reply', source)?.prefillBody).toBeUndefined();
|
||||
expect(replyComposeParams('reply', source, undefined, ' ')?.prefillBody).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -5,12 +5,15 @@ import { pickEmailBody, plainTextBody } from './email-body';
|
||||
/**
|
||||
* Composer params for a reply / reply-all / forward of `source`. Shared by
|
||||
* the thread viewer and the `mail/message/<id>?action=reply` deep link (the
|
||||
* triage widget). Null when there is nobody to reply to.
|
||||
* triage widget). Null when there is nobody to reply to. `typed` is text
|
||||
* the user already wrote (quick reply's "More options"); it goes above the
|
||||
* quote.
|
||||
*/
|
||||
export function replyComposeParams(
|
||||
mode: 'reply' | 'replyAll' | 'forward',
|
||||
source: Email,
|
||||
ownerAccountId?: string,
|
||||
typed?: string,
|
||||
): NonNullable<RootStackParamList['Compose']> | null {
|
||||
const from = source.from?.[0];
|
||||
if (!from && mode !== 'forward') return null;
|
||||
@@ -24,6 +27,7 @@ export function replyComposeParams(
|
||||
const body = !quoteHtml || picked.text ? plainTextBody(source) : undefined;
|
||||
return {
|
||||
mode,
|
||||
...(typed?.trim() ? { prefillBody: typed } : null),
|
||||
replyTo: {
|
||||
from: from ?? { email: '' },
|
||||
to: source.to,
|
||||
|
||||
@@ -557,10 +557,10 @@ function EmailViewer({ route, navigation, embedded = false, onActiveChange }: Pr
|
||||
};
|
||||
|
||||
// Reply / forward the given message (a thread card's own, or the active one).
|
||||
const navigateCompose = React.useCallback((mode: 'reply' | 'replyAll' | 'forward', target?: Email) => {
|
||||
const navigateCompose = React.useCallback((mode: 'reply' | 'replyAll' | 'forward', target?: Email, typed?: string) => {
|
||||
const source = target ?? email;
|
||||
if (!source) return;
|
||||
const params = replyComposeParams(mode, source, ownerAccountId);
|
||||
const params = replyComposeParams(mode, source, ownerAccountId, typed);
|
||||
if (params) navigation.navigate('Compose', params);
|
||||
}, [email, navigation, ownerAccountId]);
|
||||
|
||||
@@ -961,7 +961,7 @@ interface EmailPaneProps {
|
||||
onToggleStar: (email: Email) => void;
|
||||
onAddressPress: (address: EmailAddress) => void;
|
||||
onEmailPatched: (email: Email) => void;
|
||||
onReply: (mode: 'reply' | 'replyAll' | 'forward', email: Email) => void;
|
||||
onReply: (mode: 'reply' | 'replyAll' | 'forward', email: Email, typed?: string) => void;
|
||||
onSwipe: (direction: 'prev' | 'next') => void;
|
||||
onZoomChange: (zoom: { pinching: boolean; zoomed: boolean }) => void;
|
||||
}
|
||||
@@ -1182,7 +1182,8 @@ function EmailPane({
|
||||
<QuickReplyBox
|
||||
email={newest}
|
||||
jmapAccountId={jmapAccountId}
|
||||
onMoreOptions={() => onReply('reply', newest)}
|
||||
// The text typed so far moves into the full composer.
|
||||
onMoreOptions={(draft) => onReply('reply', newest, draft)}
|
||||
onSent={onEmailPatched}
|
||||
onFocus={handleQuickReplyFocus}
|
||||
onBlur={handleQuickReplyBlur}
|
||||
|
||||
Reference in New Issue
Block a user