@remit/web-client 0.0.310 → 0.0.312

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,8 @@
8
8
  * The conversation reads it off the address and opens it at its head.
9
9
  */
10
10
  import { createFileRoute } from "@tanstack/react-router";
11
+ import { replySearchSchemas } from "@/lib/mail-search";
11
12
 
12
13
  export const Route = createFileRoute(
13
14
  "/mail/$mailboxId/$threadId/$messageId/$mode/{-$outboxMessageId}",
14
- )({});
15
+ )({ validateSearch: replySearchSchemas.mailbox });
@@ -20,7 +20,8 @@
20
20
  * the pane reads the reply off the address, the way the shell reads compose.
21
21
  */
22
22
  import { createFileRoute } from "@tanstack/react-router";
23
+ import { replySearchSchemas } from "@/lib/mail-search";
23
24
 
24
25
  export const Route = createFileRoute(
25
26
  "/mail/brief/$threadId/$messageId/$mode/{-$outboxMessageId}",
26
- )({});
27
+ )({ validateSearch: replySearchSchemas.brief });
@@ -8,7 +8,8 @@
8
8
  * The conversation reads it off the address and opens it at its head.
9
9
  */
10
10
  import { createFileRoute } from "@tanstack/react-router";
11
+ import { replySearchSchemas } from "@/lib/mail-search";
11
12
 
12
13
  export const Route = createFileRoute(
13
14
  "/mail/flagged/$threadId/$messageId/$mode/{-$outboxMessageId}",
14
- )({});
15
+ )({ validateSearch: replySearchSchemas.flagged });
@@ -1,5 +1,6 @@
1
1
  import { useNavigate, useParams } from "@tanstack/react-router";
2
2
  import { useCallback } from "react";
3
+ import { withoutComposeSeed } from "@/lib/mail-search";
3
4
  import { useBrowsedList, useNavigateToBrowsedList } from "./browsed-list";
4
5
  import { useRetainOpenPanels } from "./fragment";
5
6
 
@@ -108,7 +109,7 @@ function useComposeNavigate(): (
108
109
  ) => {
109
110
  navigate({
110
111
  ...composeTarget(list, mailboxId, outboxMessageId),
111
- search: (prev: Record<string, unknown>) => prev,
112
+ search: withoutComposeSeed,
112
113
  // Opening or closing the surface is going somewhere, so the panes the
113
114
  // reader keeps up travel and the overlays they were reading over do
114
115
  // not. Recording the draft is not going anywhere — the address is
@@ -1,5 +1,6 @@
1
1
  import { useNavigate, useParams } from "@tanstack/react-router";
2
2
  import { useCallback } from "react";
3
+ import { withoutComposeSeed } from "@/lib/mail-search";
3
4
  import { useNavigateToBrowsedList } from "./browsed-list";
4
5
  import { useRetainOpenPanels } from "./fragment";
5
6
 
@@ -29,7 +30,7 @@ export function useOpenOutboxDraft(): (outboxMessageId: string) => void {
29
30
  navigate({
30
31
  to: "/mail/outbox/draft/$outboxMessageId",
31
32
  params: { outboxMessageId },
32
- search: (prev: Record<string, unknown>) => prev,
33
+ search: withoutComposeSeed,
33
34
  hash: retainPanels,
34
35
  });
35
36
  },
@@ -1,7 +1,8 @@
1
- import { useNavigate, useParams } from "@tanstack/react-router";
1
+ import { useNavigate, useParams, useSearch } from "@tanstack/react-router";
2
2
  import { useCallback, useMemo } from "react";
3
3
  import { z } from "zod";
4
4
  import type { MailListRoute } from "@/lib/mail-route";
5
+ import { type ComposeSeed, withoutComposeSeed } from "@/lib/mail-search";
5
6
  import { useBrowsedList } from "./browsed-list";
6
7
  import { useRetainOpenPanels } from "./fragment";
7
8
 
@@ -53,6 +54,7 @@ export interface ReplyAddress {
53
54
  sourceMessageId: string;
54
55
  /** The draft it writes to, once the first autosave has made one. */
55
56
  outboxMessageId: string | undefined;
57
+ seed: ComposeSeed | undefined;
56
58
  }
57
59
 
58
60
  export type ReplySurface =
@@ -79,6 +81,20 @@ function useReplyParams(): ReplyParams | undefined {
79
81
  return brief ?? flagged ?? mailbox;
80
82
  }
81
83
 
84
+ function useReplySeed(): string | undefined {
85
+ const brief = useSearch({ from: BRIEF_REPLY, shouldThrow: false });
86
+ const flagged = useSearch({ from: FLAGGED_REPLY, shouldThrow: false });
87
+ const mailbox = useSearch({ from: MAILBOX_REPLY, shouldThrow: false });
88
+ return (brief ?? flagged ?? mailbox)?.body;
89
+ }
90
+
91
+ const seededSearch =
92
+ (seed: ComposeSeed | undefined) =>
93
+ (prev: Record<string, unknown>): Record<string, unknown> =>
94
+ seed === undefined
95
+ ? withoutComposeSeed(prev)
96
+ : { ...withoutComposeSeed(prev), body: seed.body };
97
+
82
98
  /**
83
99
  * The reply surface the address names, or none.
84
100
  *
@@ -89,6 +105,7 @@ function useReplyParams(): ReplyParams | undefined {
89
105
  */
90
106
  export function useReplySurface(): ReplySurface | undefined {
91
107
  const params = useReplyParams();
108
+ const seedBody = useReplySeed();
92
109
  return useMemo(() => {
93
110
  if (!params) return undefined;
94
111
  const mode = replyModeSchema.safeParse(params.mode);
@@ -99,8 +116,9 @@ export function useReplySurface(): ReplySurface | undefined {
99
116
  threadId: params.threadId,
100
117
  sourceMessageId: params.messageId,
101
118
  outboxMessageId: params.outboxMessageId,
119
+ seed: seedBody === undefined ? undefined : { body: seedBody },
102
120
  };
103
- }, [params]);
121
+ }, [params, seedBody]);
104
122
  }
105
123
 
106
124
  /**
@@ -183,17 +201,25 @@ function inheritedDraft(
183
201
  * A push, so Back leaves the reply and returns the message it was written
184
202
  * under, and the query travels with it.
185
203
  */
186
- export function useOpenReply(): (target: ReplyTarget) => void {
204
+ export function useOpenReply(): (
205
+ target: ReplyTarget,
206
+ seed?: ComposeSeed,
207
+ ) => void {
187
208
  const navigate = useNavigate();
188
209
  const retainPanels = useRetainOpenPanels();
189
210
  const { list, mailboxId } = useBrowsedList();
190
211
  const open = useReplySurface();
191
212
 
192
213
  return useCallback(
193
- (target: ReplyTarget) => {
214
+ (target: ReplyTarget, seed?: ComposeSeed) => {
194
215
  navigate({
195
- ...replyTarget(list, mailboxId, target, inheritedDraft(open, target)),
196
- search: (prev: Record<string, unknown>) => prev,
216
+ ...replyTarget(
217
+ list,
218
+ mailboxId,
219
+ target,
220
+ seed === undefined ? inheritedDraft(open, target) : undefined,
221
+ ),
222
+ search: seededSearch(seed),
197
223
  hash: retainPanels,
198
224
  });
199
225
  },
@@ -254,7 +280,7 @@ export function useAdoptReplyDraft(): (outboxMessageId: string) => void {
254
280
  },
255
281
  outboxMessageId,
256
282
  ),
257
- search: (prev: Record<string, unknown>) => prev,
283
+ search: seededSearch(undefined),
258
284
  hash: true,
259
285
  replace: true,
260
286
  });
@@ -278,7 +304,7 @@ export function useCloseReply(): () => void {
278
304
 
279
305
  return useCallback(() => {
280
306
  if (!params) return;
281
- const search = (prev: Record<string, unknown>) => prev;
307
+ const search = seededSearch(undefined);
282
308
  const hash = retainPanels;
283
309
  const message = { threadId: params.threadId, messageId: params.messageId };
284
310
  if (list === "flagged") {