@rapidmx/web-client 0.19.0 → 0.20.0
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/README.md +381 -381
- package/apps/admin/branding/index.tsx +39 -39
- package/apps/admin/data-requests/index.tsx +482 -482
- package/apps/admin/domains/[uid].tsx +166 -166
- package/apps/admin/escrow-scopes/[uid].tsx +350 -350
- package/apps/admin/index.tsx +129 -129
- package/apps/admin/mailboxes/[uid].tsx +271 -271
- package/apps/admin/mailboxes/new/index.tsx +30 -30
- package/apps/admin/plugins/index.tsx +15 -15
- package/apps/admin/retention-policy/index.tsx +39 -39
- package/apps/admin/signing-certificates/index.tsx +343 -343
- package/apps/escrow/audit-log/index.tsx +196 -196
- package/apps/escrow/matters/[uid].tsx +621 -621
- package/apps/shared/auth/adminAccess.ts +99 -99
- package/apps/shared/components/admin/diagnostics/HostCard.tsx +2 -0
- package/apps/shared/components/admin/diagnostics/PressureTiles.tsx +108 -0
- package/apps/shared/components/admin/diagnostics/PvcTable.tsx +20 -6
- package/apps/shared/components/admin/diagnostics/diagnosticsApi.ts +21 -2
- package/apps/shared/components/admin/layout/AdminShell.tsx +384 -384
- package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +238 -238
- package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +152 -152
- package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +194 -194
- package/apps/shared/components/admin/settings/BrandingForm.tsx +423 -423
- package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +119 -119
- package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +198 -198
- package/apps/shared/components/admin/settings/PluginsManager.tsx +2093 -1620
- package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +182 -182
- package/apps/shared/components/admin/settings/pluginPreferences.ts +34 -0
- package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +288 -288
- package/apps/shared/components/admin/setup/SetupWizard.tsx +446 -446
- package/apps/shared/components/admin/usePagedList.tsx +129 -129
- package/apps/shared/components/calendar/EventModal.tsx +206 -206
- package/apps/shared/components/calendar/MonthView.tsx +185 -185
- package/apps/shared/components/calendar/RecurrenceEditor.tsx +227 -227
- package/apps/shared/components/calendar/SplitDayView.tsx +144 -144
- package/apps/shared/components/calendar/TimeGridView.tsx +246 -246
- package/apps/shared/components/calendar/allDay.ts +124 -124
- package/apps/shared/components/contacts/ContactForm.tsx +383 -383
- package/apps/shared/components/contacts/ContactsToolbar.tsx +103 -103
- package/apps/shared/components/escrow/layout/EscrowShell.tsx +155 -155
- package/apps/shared/components/layout/AppShell.tsx +461 -461
- package/apps/shared/components/layout/KeyEnrollmentGate.tsx +398 -398
- package/apps/shared/components/layout/MailboxProvisioning.tsx +168 -168
- package/apps/shared/components/layout/ResponsiveToolbar.tsx +315 -315
- package/apps/shared/components/layout/ThemeSwitch.tsx +84 -84
- package/apps/shared/components/layout/UserMenu.tsx +439 -439
- package/apps/shared/components/mail/ConversationList.tsx +332 -323
- package/apps/shared/components/mail/ConversationThreadPane.tsx +613 -613
- package/apps/shared/components/mail/MailSelectionBar.tsx +240 -240
- package/apps/shared/components/mail/MenuButton.tsx +404 -404
- package/apps/shared/components/mail/MessageDetailPane.tsx +1757 -1757
- package/apps/shared/components/mail/compose/ComposeContext.tsx +312 -312
- package/apps/shared/components/mail/compose/ComposeToolbar.tsx +422 -422
- package/apps/shared/components/mail/compose/ComposeWindow.tsx +1681 -1681
- package/apps/shared/components/mail/compose/RichTextEditor.tsx +147 -147
- package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -60
- package/apps/shared/components/mail/compose/quotedBody.ts +161 -161
- package/apps/shared/components/mail/listPreferences.ts +3 -3
- package/apps/shared/components/mail/reading/MessageMoreMenu.tsx +258 -258
- package/apps/shared/components/mail/reading/MessageSourceDialog.tsx +79 -79
- package/apps/shared/components/mail/reading/messageExport.ts +59 -59
- package/apps/shared/components/mail/reading/printMessage.ts +99 -99
- package/apps/shared/components/mail/reading/useMessageActions.ts +443 -443
- package/apps/shared/components/mail/verificationSeals.ts +125 -125
- package/apps/shared/components/rules/RuleBuilder.tsx +311 -311
- package/apps/shared/components/settings/SigningCertificateCard.tsx +344 -344
- package/apps/shared/keyboard/GlobalShortcuts.tsx +51 -51
- package/apps/shared/keyboard/ShortcutProvider.tsx +62 -62
- package/apps/shared/keyboard/ShortcutsDialog.tsx +84 -84
- package/apps/shared/keyboard/dispatch.ts +124 -124
- package/apps/shared/keyboard/format.ts +89 -89
- package/apps/shared/keyboard/keymap.ts +114 -114
- package/apps/shared/keyboard/registry.ts +65 -65
- package/apps/shared/keyboard/targets.ts +79 -79
- package/apps/shared/mail/folderOfType.ts +49 -49
- package/apps/shared/mail/folderTree.ts +143 -143
- package/apps/shared/mail/listAllPages.ts +39 -39
- package/apps/shared/mail/newMailNotifications.ts +171 -171
- package/apps/shared/mail/outbox/sendJob.ts +445 -445
- package/apps/shared/mail/outbox/sendOutcomes.ts +155 -155
- package/apps/shared/mail/reportNotices.ts +66 -66
- package/apps/shared/mail/senderBlocking.ts +141 -141
- package/apps/shared/mail/useMailConnection.ts +205 -205
- package/apps/shared/mail/useMailLiveUpdates.ts +277 -277
- package/apps/shared/mail/useMailboxUpdateAccess.ts +60 -60
- package/apps/shared/mail/useMarkMessageRead.ts +47 -47
- package/apps/shared/mail/useNewMailNotifications.ts +178 -178
- package/apps/shared/notifications/store.ts +560 -560
- package/apps/shared/search/LocalIndexLifecycle.tsx +114 -114
- package/apps/shared/search/localIndexBuilder.ts +481 -481
- package/apps/shared/signing/enrollmentStorage.ts +33 -33
- package/apps/shared/signing/enrollmentTracker.ts +385 -385
- package/apps/shared/signing/enrollmentView.ts +251 -251
- package/apps/shared/signing/useNow.ts +19 -19
- package/apps/shared/signing/useSigningEnrollmentWatcher.ts +90 -90
- package/apps/shared/styles/app.css +396 -396
- package/apps/www/calendar/index.tsx +581 -581
- package/apps/www/contacts/[uid].tsx +112 -112
- package/apps/www/index.tsx +3012 -2962
- package/apps/www/messages/[uid].tsx +139 -139
- package/apps/www/settings/auto-reply/index.tsx +136 -136
- package/apps/www/settings/blocked-senders/index.tsx +303 -303
- package/apps/www/settings/encryption/index.tsx +1290 -1290
- package/apps/www/settings/filters/[uid].tsx +179 -179
- package/apps/www/settings/filters/index.tsx +105 -105
- package/apps/www/settings/filters/new/index.tsx +165 -165
- package/apps/www/settings/labels/index.tsx +207 -207
- package/apps/www/settings/privacy/index.tsx +495 -495
- package/apps/www/settings/profile/index.tsx +251 -251
- package/apps/www/settings/read-receipts/index.tsx +150 -150
- package/apps/www/settings/sharing/index.tsx +259 -259
- package/apps/www/settings/signatures/[uid].tsx +175 -175
- package/apps/www/settings/signatures/index.tsx +91 -91
- package/apps/www/settings/signatures/new/index.tsx +138 -138
- package/apps/www/tasks/index.tsx +654 -654
- package/dist/apps/shared/components/admin/diagnostics/HostCard.js +2 -1
- package/dist/apps/shared/components/admin/diagnostics/PressureTiles.d.ts +22 -0
- package/dist/apps/shared/components/admin/diagnostics/PressureTiles.js +52 -0
- package/dist/apps/shared/components/admin/diagnostics/PvcTable.js +9 -4
- package/dist/apps/shared/components/admin/diagnostics/diagnosticsApi.d.ts +35 -2
- package/dist/apps/shared/components/admin/settings/BrandingForm.js +3 -3
- package/dist/apps/shared/components/admin/settings/PluginsManager.js +267 -35
- package/dist/apps/shared/components/admin/settings/pluginPreferences.d.ts +2 -0
- package/dist/apps/shared/components/admin/settings/pluginPreferences.js +35 -0
- package/dist/apps/shared/components/mail/ConversationList.d.ts +10 -3
- package/dist/apps/shared/components/mail/ConversationList.js +9 -5
- package/dist/apps/shared/components/mail/listPreferences.d.ts +1 -1
- package/dist/apps/shared/components/mail/reading/printMessage.js +11 -11
- package/dist/apps/shared/styles/app.css +396 -396
- package/dist/apps/www/index.js +51 -10
- package/package.json +2 -2
|
@@ -13,6 +13,10 @@ import { listConversationMessages } from "@rapidmx/react-shared/mail/conversatio
|
|
|
13
13
|
import { ROW_FOCUS_CLASS, UnreadBar, UnreadLabel, dateClass, isUnread, rowClass, senderClass, subjectClass } from "./unreadStyle.js";
|
|
14
14
|
import SwipeRow from "./SwipeRow.js";
|
|
15
15
|
import InviteRowChip from "./invite/InviteRowChip.js";
|
|
16
|
+
/** What tells a row apart from the others: the same conversation id in two mailboxes (a message sent to both) is two rows. */
|
|
17
|
+
export function conversationRowKey(conversation) {
|
|
18
|
+
return conversation.mailboxUid ? `${conversation.mailboxUid}\u0000${conversation.conversationId}` : conversation.conversationId;
|
|
19
|
+
}
|
|
16
20
|
/** Every participant as `Name <address>`, for the tooltip and the accessible text of the "+N" a crowded row folds them into. */
|
|
17
21
|
function participantList(conversation) {
|
|
18
22
|
return conversation.participants.map((participant) => formatMailAddress(participant)).join(", ");
|
|
@@ -41,7 +45,7 @@ export default function ConversationList({ conversations, mailboxUid, selectedUi
|
|
|
41
45
|
setAnswers((prev) => ({ ...prev, [updated.uid]: updated.meetingResponse }));
|
|
42
46
|
}
|
|
43
47
|
function toggle(conversation) {
|
|
44
|
-
const id = conversation
|
|
48
|
+
const id = conversationRowKey(conversation);
|
|
45
49
|
setExpanded((prev) => {
|
|
46
50
|
const next = new Set(prev);
|
|
47
51
|
if (next.has(id)) {
|
|
@@ -61,7 +65,7 @@ export default function ConversationList({ conversations, mailboxUid, selectedUi
|
|
|
61
65
|
delete next[id];
|
|
62
66
|
return next;
|
|
63
67
|
});
|
|
64
|
-
listConversationMessages(mailboxUid,
|
|
68
|
+
listConversationMessages(conversation.mailboxUid ?? mailboxUid, conversation.conversationId)
|
|
65
69
|
.then((loaded) => setMessagesById((prev) => ({ ...prev, [id]: loaded })))
|
|
66
70
|
.catch((err) => setErrorsById((prev) => ({
|
|
67
71
|
...prev,
|
|
@@ -77,15 +81,15 @@ export default function ConversationList({ conversations, mailboxUid, selectedUi
|
|
|
77
81
|
return _jsx("p", { className: "p-4 text-sm text-text-muted", children: "No conversations in this folder." });
|
|
78
82
|
}
|
|
79
83
|
return (_jsx("ul", { className: swipe?.enabled ? "overflow-x-clip" : undefined, children: conversations.map((conversation) => {
|
|
80
|
-
const id = conversation
|
|
84
|
+
const id = conversationRowKey(conversation);
|
|
81
85
|
const isExpanded = expanded.has(id);
|
|
82
86
|
const unread = conversation.unreadCount > 0;
|
|
83
87
|
const loaded = messagesById[id];
|
|
84
88
|
// `listConversationMessages()` answers oldest first; the rows read in whichever sense the
|
|
85
89
|
// list itself is arranged in. Copied before reversing - the fetched array is cached.
|
|
86
90
|
const children = loaded && newestFirst ? [...loaded].reverse() : loaded;
|
|
87
|
-
const panelId = `conversation-messages-${
|
|
88
|
-
const ticked = selectedConversationIds?.has(
|
|
91
|
+
const panelId = `conversation-messages-${conversation.mailboxUid ? `${conversation.mailboxUid}-` : ""}${conversation.conversationId}`;
|
|
92
|
+
const ticked = selectedConversationIds?.has(conversation.conversationId) ?? false;
|
|
89
93
|
return (_jsxs("li", { children: [_jsxs(SwipeRow, { as: "div", enabled: !!swipe?.enabled && !selectMode, onArchive: () => swipe.onArchive(conversation), onMove: () => swipe.onMove(conversation), "data-message-uid": conversation.latestMessageUid, "data-unread": unread ? "true" : undefined, className: rowClass({ unread, selected: conversation.latestMessageUid === selectedUid || ticked }, "flex items-stretch"), children: [_jsx(UnreadBar, { unread: unread }), selectMode && (_jsx("span", { className: "shrink-0 flex items-center pl-3", children: _jsx("input", { type: "checkbox", checked: ticked, onChange: () => onToggleSelected?.(conversation), "aria-label": `Select conversation: ${conversation.subject || "(no subject)"}`, className: "w-4 h-4 accent-primary" }) })), _jsx("button", { type: "button", onClick: () => toggle(conversation), "aria-expanded": isExpanded, "aria-controls": panelId, "aria-label": `${isExpanded ? "Collapse" : "Expand"} conversation: ${conversation.subject || "(no subject)"}`, className: ["shrink-0 px-2 text-text-muted hover:text-text", ROW_FOCUS_CLASS].join(" "), children: isExpanded ? (_jsx(HiChevronDown, { size: 16, "aria-hidden": "true" })) : (_jsx(HiChevronRight, { size: 16, "aria-hidden": "true" })) }), _jsxs("div", { className: "flex-1 min-w-0 flex flex-col", children: [_jsxs("button", { type: "button", "data-row-open": true, onClick: () => onOpenMessage(conversation, conversation.latestMessageUid), className: ["w-full text-left pr-4 py-3", ROW_FOCUS_CLASS].join(" "), children: [_jsx(UnreadLabel, { unread: unread }), _jsxs("div", { className: "flex items-center justify-between gap-2 text-sm", children: [_jsx(MailAddress, { recipient: conversation.participants[0] ?? conversation.latestFrom, className: ["flex-1", senderClass(unread)].join(" ") }), conversation.participants.length > 1 && (_jsxs("span", { className: "text-xs text-text-muted shrink-0 font-normal", title: participantList(conversation), children: ["+", conversation.participants.length - 1, _jsxs("span", { className: "sr-only", children: [" more: ", participantList(conversation)] })] })), _jsx("span", { className: ["text-xs shrink-0", dateClass(unread)].join(" "), children: new Date(conversation.latestDate).toLocaleDateString() })] }), _jsx("div", { className: ["text-sm truncate", subjectClass(unread)].join(" "), children: conversation.subject || "(no subject)" }), _jsx("div", { className: "text-xs text-text-muted truncate font-normal", children: conversationLooksEncrypted(conversation) ? _jsx(EncryptedPreview, {}) : conversation.latestPreview }), _jsxs("div", { className: "flex items-center gap-2 mt-1 text-xs text-text-muted font-normal", children: [conversation.messageCount > 1 && _jsxs("span", { children: [conversation.messageCount, " messages"] }), unread && conversation.messageCount > 1 && (_jsxs("span", { className: "py-0.5 px-2 rounded-pill bg-primary/15 text-primary-dark font-bold", children: [conversation.unreadCount, " unread"] })), conversation.hasAttachments && (_jsx(HiOutlinePaperClip, { size: 13, "aria-label": "Has attachments" })), conversation.flagged && (_jsx(HiOutlineFlag, { size: 13, "aria-label": "Flagged", className: "text-danger" }))] })] }), _jsx(InviteRowChip, { message: {
|
|
90
94
|
uid: conversation.latestMessageUid,
|
|
91
95
|
meetingMethod: conversation.latestMeetingMethod ?? undefined,
|
|
@@ -89,7 +89,7 @@ export declare const CONVERSATION_SORT_NOTE = "Conversations are ordered within
|
|
|
89
89
|
* order that would mean nothing. Ties break newest first whichever direction is in force, so two rows the
|
|
90
90
|
* key can't tell apart still read in a stable, familiar order.
|
|
91
91
|
*/
|
|
92
|
-
export declare function sortConversations(conversations:
|
|
92
|
+
export declare function sortConversations<T extends ConversationSummary>(conversations: T[], sortBy: MessageListSort, sortOrder: MessageSortOrder): T[];
|
|
93
93
|
/** The direction the server itself would pick for a key if none were sent (see `MessageSortOrder`) - what
|
|
94
94
|
* this list switches to when the reader picks a different field, so changing "Date" to "Subject" reads A-Z
|
|
95
95
|
* rather than inheriting Date's newest-first as a surprising Z-A. */
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { attachmentSource, makeCidResolver } from "./bodyContent.js";
|
|
2
2
|
import { prepareBodyHtml } from "./bodyHtml.js";
|
|
3
3
|
import { frameCsp } from "./frameDocument.js";
|
|
4
|
-
const PRINT_CSS = `
|
|
5
|
-
html{font:14px/1.5 system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;color:#000;background:#fff}
|
|
6
|
-
body{margin:0;padding:24px}
|
|
7
|
-
h1{font-size:20px;margin:0 0 12px}
|
|
8
|
-
dl{margin:0 0 12px;display:grid;grid-template-columns:max-content 1fr;gap:2px 12px}
|
|
9
|
-
dt{font-weight:600;color:#444}
|
|
10
|
-
dd{margin:0;overflow-wrap:anywhere}
|
|
11
|
-
hr{border:0;border-top:1px solid #999;margin:0 0 16px}
|
|
12
|
-
#rr-body{overflow-wrap:break-word}
|
|
13
|
-
#rr-body img{max-width:100%;height:auto}
|
|
14
|
-
#rr-body pre,pre.rr-text{white-space:pre-wrap;font:inherit;margin:0}
|
|
4
|
+
const PRINT_CSS = `
|
|
5
|
+
html{font:14px/1.5 system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;color:#000;background:#fff}
|
|
6
|
+
body{margin:0;padding:24px}
|
|
7
|
+
h1{font-size:20px;margin:0 0 12px}
|
|
8
|
+
dl{margin:0 0 12px;display:grid;grid-template-columns:max-content 1fr;gap:2px 12px}
|
|
9
|
+
dt{font-weight:600;color:#444}
|
|
10
|
+
dd{margin:0;overflow-wrap:anywhere}
|
|
11
|
+
hr{border:0;border-top:1px solid #999;margin:0 0 16px}
|
|
12
|
+
#rr-body{overflow-wrap:break-word}
|
|
13
|
+
#rr-body img{max-width:100%;height:auto}
|
|
14
|
+
#rr-body pre,pre.rr-text{white-space:pre-wrap;font:inherit;margin:0}
|
|
15
15
|
`;
|
|
16
16
|
export function escapeHtml(text) {
|
|
17
17
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|