@remit/web-client 0.0.195 → 0.0.197
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.
- package/package.json +1 -1
- package/src/components/mail/intelligence-auto-open-pref.render.test.ts +412 -0
- package/src/components/mail/intelligence-shortcut-surface.render.test.ts +40 -10
- package/src/components/settings/DeleteFolderDialog.render.test.ts +220 -5
- package/src/components/settings/DeleteFolderDialog.tsx +90 -13
- package/src/hooks/search-mirror-convergence.render.test.ts +1 -0
- package/src/hooks/search-mirror-detail.render.test.ts +1 -0
- package/src/hooks/useDeleteFolder.ts +113 -0
- package/src/hooks/useIntelligenceSurface.ts +9 -4
- package/src/hooks/useRailPanels.ts +128 -0
- package/src/lib/delete-folder.test.ts +14 -0
- package/src/lib/delete-folder.ts +6 -0
- package/src/lib/fresh-mailbox-count.test.ts +145 -0
- package/src/lib/fresh-mailbox-count.ts +114 -0
- package/src/lib/intelligence-pref.test.ts +68 -1
- package/src/lib/intelligence-pref.ts +20 -6
- package/src/lib/mail-context.ts +8 -0
- package/src/lib/mailbox-sync-wait.ts +6 -2
- package/src/routes/mail.tsx +15 -68
package/src/routes/mail.tsx
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
useNavigate,
|
|
11
11
|
useRouterState,
|
|
12
12
|
} from "@tanstack/react-router";
|
|
13
|
-
import { useCallback, useEffect, useMemo
|
|
13
|
+
import { useCallback, useEffect, useMemo } from "react";
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
import { ComposeFab } from "@/components/layout/ComposeFab";
|
|
16
16
|
import { MailShellProvider } from "@/components/layout/MailShell";
|
|
@@ -21,28 +21,16 @@ import { KeyboardShortcutsModal } from "@/components/ui/KeyboardShortcutsModal";
|
|
|
21
21
|
import { useKeyboardNavigation } from "@/hooks/useKeyboardNavigation";
|
|
22
22
|
import { isSinglePaneTier, useLayoutTier } from "@/hooks/useLayoutTier";
|
|
23
23
|
import { useMailboxNameIndex } from "@/hooks/useMailboxNameIndex";
|
|
24
|
+
import { useRailPanels } from "@/hooks/useRailPanels";
|
|
24
25
|
import { useResultFolderIndex } from "@/hooks/useResultFolderIndex";
|
|
25
26
|
import { useSearchField } from "@/hooks/useSearchField";
|
|
26
27
|
import { useStaleAccountSync } from "@/hooks/useStaleAccountSync";
|
|
27
|
-
import {
|
|
28
|
-
readIntelligencePref,
|
|
29
|
-
resolveRailOpen,
|
|
30
|
-
writeIntelligencePref,
|
|
31
|
-
} from "@/lib/intelligence-pref";
|
|
32
28
|
import { MailContext } from "@/lib/mail-context";
|
|
33
29
|
import { MailFreshnessProvider } from "@/lib/mail-freshness";
|
|
34
30
|
import { mailListRoute } from "@/lib/mail-route";
|
|
35
31
|
import { buildAccountNameIndex } from "@/lib/search-token-index";
|
|
36
32
|
import { wizardEntryValue, wizardStepValue } from "@/lib/wizard-history";
|
|
37
|
-
import {
|
|
38
|
-
isOverlayPanel,
|
|
39
|
-
type OverlayPanel,
|
|
40
|
-
useIsComposing,
|
|
41
|
-
useOpenCompose,
|
|
42
|
-
useOpenPanels,
|
|
43
|
-
useOpenThreadPath,
|
|
44
|
-
useSetOpenPanels,
|
|
45
|
-
} from "@/routing";
|
|
33
|
+
import { useIsComposing, useOpenCompose } from "@/routing";
|
|
46
34
|
import "@/lib/client";
|
|
47
35
|
|
|
48
36
|
// `MailContext` / `useMailContext` live in `@/lib/mail-context` so the provider
|
|
@@ -87,56 +75,18 @@ function MailLayout() {
|
|
|
87
75
|
// tablet with no compose surface (compose lives in the reading pane, which
|
|
88
76
|
// tablet doesn't mount) — the "c" shortcut / FAB opened nothing.
|
|
89
77
|
const isSinglePane = isSinglePaneTier(tier);
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
78
|
+
// What the address, the stored preference and the two rail verbs come to
|
|
79
|
+
// (`hooks/useRailPanels`): a raise surfaces the rail for the thread in hand,
|
|
80
|
+
// the reader's own toggle is the one that stores where they want it (#778).
|
|
81
|
+
const {
|
|
82
|
+
openOverlay,
|
|
83
|
+
intelligenceOpen,
|
|
84
|
+
showOverlay,
|
|
85
|
+
toggleIntelligence,
|
|
86
|
+
raiseIntelligence,
|
|
87
|
+
} = useRailPanels();
|
|
97
88
|
const showShortcuts = openOverlay === "shortcuts";
|
|
98
89
|
const drawerOpen = openOverlay === "nav";
|
|
99
|
-
// Pane 4 on desktop, the details drawer below it. `resolveRailOpen` is the
|
|
100
|
-
// one place the address and the stored preference meet: the address decides
|
|
101
|
-
// whenever it says anything at all, and the preference opens the rail with
|
|
102
|
-
// the thread where it is silent (#782).
|
|
103
|
-
const openThread = useOpenThreadPath();
|
|
104
|
-
// Held in state, not read back from storage each render: closing the rail
|
|
105
|
-
// where the address is silent changes nothing about the address, and the
|
|
106
|
-
// answer has to move anyway.
|
|
107
|
-
const [prefersRail, setPrefersRail] = useState(readIntelligencePref);
|
|
108
|
-
const intelligenceOpen = resolveRailOpen({
|
|
109
|
-
panels: openPanels,
|
|
110
|
-
prefersOpen: prefersRail,
|
|
111
|
-
isDesktop: tier === "desktop",
|
|
112
|
-
hasThread: openThread !== undefined,
|
|
113
|
-
});
|
|
114
|
-
// Every write states the whole set, because it is composed from what is
|
|
115
|
-
// showing rather than from what the address happens to spell: the rail open
|
|
116
|
-
// by preference alone is still open, and an overlay must not close it.
|
|
117
|
-
const showPanels = useCallback(
|
|
118
|
-
(rail: boolean, overlay: OverlayPanel | undefined) => {
|
|
119
|
-
setOpenPanels([
|
|
120
|
-
...(rail ? (["intelligence"] as const) : []),
|
|
121
|
-
...(overlay ? [overlay] : []),
|
|
122
|
-
]);
|
|
123
|
-
},
|
|
124
|
-
[setOpenPanels],
|
|
125
|
-
);
|
|
126
|
-
const handleSetIntelligenceOpen = useCallback(
|
|
127
|
-
(open: boolean) => {
|
|
128
|
-
writeIntelligencePref(open);
|
|
129
|
-
setPrefersRail(open);
|
|
130
|
-
showPanels(open, openOverlay);
|
|
131
|
-
},
|
|
132
|
-
[openOverlay, showPanels],
|
|
133
|
-
);
|
|
134
|
-
const showOverlay = useCallback(
|
|
135
|
-
(overlay: OverlayPanel | undefined) => {
|
|
136
|
-
showPanels(intelligenceOpen, overlay);
|
|
137
|
-
},
|
|
138
|
-
[intelligenceOpen, showPanels],
|
|
139
|
-
);
|
|
140
90
|
|
|
141
91
|
// The one search field and the query it commits (`useSearchField`): seeded
|
|
142
92
|
// from the URL, mirrored back by each list route's own `useSearchMirror`,
|
|
@@ -210,10 +160,6 @@ function MailLayout() {
|
|
|
210
160
|
setSearchInput("");
|
|
211
161
|
}, [setSearchInput]);
|
|
212
162
|
|
|
213
|
-
const handleToggleIntelligence = useCallback(() => {
|
|
214
|
-
handleSetIntelligenceOpen(!intelligenceOpen);
|
|
215
|
-
}, [handleSetIntelligenceOpen, intelligenceOpen]);
|
|
216
|
-
|
|
217
163
|
const accounts = config?.accounts ?? [];
|
|
218
164
|
const accountIds = useMemo(
|
|
219
165
|
() => accounts.map((account) => account.accountId),
|
|
@@ -253,7 +199,8 @@ function MailLayout() {
|
|
|
253
199
|
onSearchClear: handleSearchClear,
|
|
254
200
|
onSearchClearQuery: handleSearchClearQuery,
|
|
255
201
|
intelligenceOpen,
|
|
256
|
-
onToggleIntelligence:
|
|
202
|
+
onToggleIntelligence: toggleIntelligence,
|
|
203
|
+
onRaiseIntelligence: raiseIntelligence,
|
|
257
204
|
};
|
|
258
205
|
|
|
259
206
|
// Single nav node: the kit renders it as a pane (≥1024px) or inside its
|