@rapidmx/web-client 0.10.0 → 0.12.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 +183 -2
- package/apps/admin/_layout.tsx +8 -2
- package/apps/admin/index.tsx +7 -1
- package/apps/admin/ingest-queue/index.tsx +2 -1
- package/apps/admin/mailboxes/[uid].tsx +23 -10
- package/apps/admin/mailboxes/new/index.tsx +3 -3
- package/apps/admin/quarantine/index.tsx +2 -1
- package/apps/admin/signing-certificates/index.tsx +343 -0
- package/apps/escrow/_layout.tsx +8 -2
- package/apps/shared/appearance/AppearanceForm.tsx +392 -0
- package/apps/shared/appearance/AppearanceHead.tsx +49 -0
- package/apps/shared/appearance/AppearanceProvider.tsx +470 -0
- package/apps/shared/appearance/ColorField.tsx +107 -0
- package/apps/shared/appearance/appearanceCache.ts +106 -0
- package/apps/shared/appearance/appearanceContext.ts +77 -0
- package/apps/shared/appearance/bootScript.ts +35 -0
- package/apps/shared/appearance/color.ts +169 -0
- package/apps/shared/appearance/photo.ts +88 -0
- package/apps/shared/appearance/resolvedTheme.ts +67 -0
- package/apps/shared/appearance/theme.ts +355 -0
- package/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.tsx +4 -4
- package/apps/shared/components/admin/layout/AdminShell.tsx +22 -10
- package/apps/shared/components/admin/mailboxes/ShareAccessCard.tsx +107 -60
- package/apps/shared/components/admin/settings/BrandingForm.tsx +24 -0
- package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +60 -14
- package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +65 -16
- package/apps/shared/components/admin/settings/PluginsManager.tsx +228 -25
- package/apps/shared/components/admin/setup/SetupWizard.tsx +2 -1
- package/apps/shared/components/calendar/CalendarListSidebar.tsx +4 -5
- package/apps/shared/components/contacts/ContactForm.tsx +11 -5
- package/apps/shared/components/contacts/ContactsSidebar.tsx +5 -3
- package/apps/shared/components/contacts/ContactsToolbar.tsx +25 -52
- package/apps/shared/components/contacts/layout/ContactsShell.tsx +10 -5
- package/apps/shared/components/escrow/layout/EscrowShell.tsx +13 -6
- package/apps/shared/components/layout/AppShell.tsx +98 -32
- package/apps/shared/components/layout/BrandingChrome.tsx +200 -13
- package/apps/shared/components/layout/RailIcon.tsx +100 -0
- package/apps/shared/components/layout/ResponsiveToolbar.tsx +315 -0
- package/apps/shared/components/layout/ThemeSwitch.tsx +84 -0
- package/apps/shared/components/layout/UserMenu.tsx +75 -6
- package/apps/shared/components/mail/ConversationList.tsx +4 -2
- package/apps/shared/components/mail/ConversationThreadPane.tsx +487 -475
- package/apps/shared/components/mail/LazyReadingPane.tsx +14 -16
- package/apps/shared/components/mail/MailSelectionBar.tsx +2 -10
- package/apps/shared/components/mail/MessageDetailPane.tsx +366 -287
- package/apps/shared/components/mail/OutboxBadge.tsx +44 -0
- package/apps/shared/components/mail/OutboxRowStatus.tsx +31 -0
- package/apps/shared/components/mail/compose/ComposeContext.tsx +35 -2
- package/apps/shared/components/mail/compose/ComposeWindow.tsx +239 -437
- package/apps/shared/components/mail/compose/encryptionRequirement.ts +86 -0
- package/apps/shared/components/mail/layout/MailShell.tsx +39 -25
- package/apps/shared/components/mail/reading/EncryptedBody.tsx +65 -0
- package/apps/shared/components/mail/reading/EncryptedPreview.tsx +35 -0
- package/apps/shared/components/mail/reading/MessageBody.tsx +240 -0
- package/apps/shared/components/mail/reading/MessageCard.tsx +174 -0
- package/apps/shared/components/mail/reading/bodyContent.ts +100 -0
- package/apps/shared/components/mail/reading/bodyHtml.ts +298 -0
- package/apps/shared/components/mail/reading/color.ts +245 -0
- package/apps/shared/components/mail/reading/frameControl.ts +142 -0
- package/apps/shared/components/mail/reading/frameDocument.ts +123 -0
- package/apps/shared/components/mail/reading/safeDocument.ts +24 -0
- package/apps/shared/components/mail/reading/themeAdaptation.ts +221 -0
- package/apps/shared/components/mail/reading/themeSurface.ts +90 -0
- package/apps/shared/components/mail/reading/viewOriginal.ts +38 -0
- package/apps/shared/components/settings/SigningCertificateCard.tsx +344 -0
- package/apps/shared/components/settings/layout/SettingsShell.tsx +1 -0
- package/apps/shared/components/sharing/PrincipalListField.tsx +82 -0
- package/apps/shared/components/sharing/PrincipalPicker.tsx +76 -0
- package/apps/shared/components/sharing/PrincipalResolver.tsx +164 -0
- package/apps/shared/components/tasks/TasksSidebar.tsx +5 -3
- package/apps/shared/components/tasks/layout/TasksShell.tsx +9 -5
- package/apps/shared/mail/folderCounts.ts +9 -3
- package/apps/shared/mail/folderTree.ts +143 -0
- package/apps/shared/mail/outbox/UnlockBridge.tsx +23 -0
- package/apps/shared/mail/outbox/composeBridge.ts +69 -0
- package/apps/shared/mail/outbox/outboxState.ts +88 -0
- package/apps/shared/mail/outbox/pendingSends.ts +146 -0
- package/apps/shared/mail/outbox/sendDecision.ts +157 -0
- package/apps/shared/mail/outbox/sendJob.ts +427 -0
- package/apps/shared/mail/outbox/sendOutcomes.ts +146 -0
- package/apps/shared/mail/outbox/sendState.ts +35 -0
- package/apps/shared/mail/outbox/useOutboxStatus.ts +61 -0
- package/apps/shared/mail/useMailConnection.ts +81 -28
- package/apps/shared/mail/useMailLiveUpdates.ts +55 -10
- package/apps/shared/mail/useNewMailNotifications.ts +47 -32
- package/apps/shared/navigation/AppRouter.tsx +2 -2
- package/apps/shared/notifications/NotificationCenter.tsx +215 -0
- package/apps/shared/notifications/NotificationHistoryDialog.tsx +90 -0
- package/apps/shared/notifications/apiErrors.ts +98 -0
- package/apps/shared/notifications/headerOffset.ts +35 -0
- package/apps/shared/notifications/pushStatus.ts +56 -0
- package/apps/shared/notifications/store.ts +549 -0
- package/apps/shared/notifications/systemErrors.ts +63 -0
- package/apps/shared/notifications/useNotifications.ts +41 -0
- package/apps/shared/signing/enrollmentStorage.ts +33 -0
- package/apps/shared/signing/enrollmentTracker.ts +385 -0
- package/apps/shared/signing/enrollmentView.ts +251 -0
- package/apps/shared/signing/signingInfo.ts +58 -0
- package/apps/shared/signing/useNow.ts +19 -0
- package/apps/shared/signing/useSigningEnrollmentWatcher.ts +90 -0
- package/apps/shared/styles/app.css +80 -0
- package/apps/www/_layout.tsx +8 -2
- package/apps/www/_routes.ts +1 -0
- package/apps/www/calendar/index.tsx +9 -14
- package/apps/www/contacts/[uid].tsx +5 -8
- package/apps/www/contacts/index.tsx +587 -584
- package/apps/www/index.tsx +38 -27
- package/apps/www/messages/[uid].tsx +3 -1
- package/apps/www/settings/appearance/index.tsx +21 -0
- package/apps/www/settings/auto-reply/index.tsx +3 -7
- package/apps/www/settings/encryption/index.tsx +151 -116
- package/apps/www/settings/filters/[uid].tsx +3 -1
- package/apps/www/settings/filters/new/index.tsx +3 -1
- package/apps/www/settings/privacy/index.tsx +3 -8
- package/apps/www/settings/read-receipts/index.tsx +3 -7
- package/apps/www/settings/sharing/index.tsx +44 -65
- package/apps/www/settings/signatures/[uid].tsx +3 -1
- package/apps/www/settings/signatures/new/index.tsx +3 -2
- package/apps/www/tasks/index.tsx +11 -16
- package/dist/apps/admin/_layout.d.ts +5 -1
- package/dist/apps/admin/_layout.js +3 -2
- package/dist/apps/admin/index.js +3 -2
- package/dist/apps/admin/ingest-queue/index.js +2 -1
- package/dist/apps/admin/mailboxes/[uid].js +9 -6
- package/dist/apps/admin/mailboxes/new/index.js +1 -1
- package/dist/apps/admin/quarantine/index.js +2 -1
- package/dist/apps/admin/signing-certificates/index.d.ts +3 -0
- package/dist/apps/admin/signing-certificates/index.js +161 -0
- package/dist/apps/escrow/_layout.d.ts +5 -1
- package/dist/apps/escrow/_layout.js +3 -2
- package/dist/apps/shared/appearance/AppearanceForm.d.ts +7 -0
- package/dist/apps/shared/appearance/AppearanceForm.js +131 -0
- package/dist/apps/shared/appearance/AppearanceHead.d.ts +15 -0
- package/dist/apps/shared/appearance/AppearanceHead.js +31 -0
- package/dist/apps/shared/appearance/AppearanceProvider.d.ts +32 -0
- package/dist/apps/shared/appearance/AppearanceProvider.js +390 -0
- package/dist/apps/shared/appearance/ColorField.d.ts +22 -0
- package/dist/apps/shared/appearance/ColorField.js +40 -0
- package/dist/apps/shared/appearance/appearanceCache.d.ts +45 -0
- package/dist/apps/shared/appearance/appearanceCache.js +80 -0
- package/dist/apps/shared/appearance/appearanceContext.d.ts +45 -0
- package/dist/apps/shared/appearance/appearanceContext.js +29 -0
- package/dist/apps/shared/appearance/bootScript.d.ts +16 -0
- package/dist/apps/shared/appearance/bootScript.js +33 -0
- package/dist/apps/shared/appearance/color.d.ts +65 -0
- package/dist/apps/shared/appearance/color.js +132 -0
- package/dist/apps/shared/appearance/photo.d.ts +17 -0
- package/dist/apps/shared/appearance/photo.js +79 -0
- package/dist/apps/shared/appearance/resolvedTheme.d.ts +21 -0
- package/dist/apps/shared/appearance/resolvedTheme.js +55 -0
- package/dist/apps/shared/appearance/theme.d.ts +111 -0
- package/dist/apps/shared/appearance/theme.js +251 -0
- package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +3 -2
- package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
- package/dist/apps/shared/components/admin/layout/AdminShell.js +16 -6
- package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.d.ts +10 -5
- package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +49 -34
- package/dist/apps/shared/components/admin/settings/BrandingForm.d.ts +2 -0
- package/dist/apps/shared/components/admin/settings/BrandingForm.js +7 -1
- package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +25 -5
- package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +18 -7
- package/dist/apps/shared/components/admin/settings/PluginsManager.js +106 -20
- package/dist/apps/shared/components/admin/setup/SetupWizard.js +2 -1
- package/dist/apps/shared/components/calendar/CalendarListSidebar.js +8 -8
- package/dist/apps/shared/components/contacts/ContactForm.js +1 -1
- package/dist/apps/shared/components/contacts/ContactsSidebar.js +4 -2
- package/dist/apps/shared/components/contacts/ContactsToolbar.d.ts +3 -1
- package/dist/apps/shared/components/contacts/ContactsToolbar.js +24 -9
- package/dist/apps/shared/components/contacts/layout/ContactsShell.js +4 -1
- package/dist/apps/shared/components/escrow/layout/EscrowShell.js +7 -4
- package/dist/apps/shared/components/layout/AppShell.d.ts +6 -1
- package/dist/apps/shared/components/layout/AppShell.js +59 -13
- package/dist/apps/shared/components/layout/BrandingChrome.d.ts +69 -10
- package/dist/apps/shared/components/layout/BrandingChrome.js +140 -12
- package/dist/apps/shared/components/layout/RailIcon.d.ts +21 -0
- package/dist/apps/shared/components/layout/RailIcon.js +85 -0
- package/dist/apps/shared/components/layout/ResponsiveToolbar.d.ts +55 -0
- package/dist/apps/shared/components/layout/ResponsiveToolbar.js +199 -0
- package/dist/apps/shared/components/layout/ThemeSwitch.d.ts +9 -0
- package/dist/apps/shared/components/layout/ThemeSwitch.js +54 -0
- package/dist/apps/shared/components/layout/UserMenu.d.ts +7 -1
- package/dist/apps/shared/components/layout/UserMenu.js +41 -7
- package/dist/apps/shared/components/mail/ConversationList.js +3 -2
- package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +2 -1
- package/dist/apps/shared/components/mail/ConversationThreadPane.js +42 -20
- package/dist/apps/shared/components/mail/LazyReadingPane.js +9 -8
- package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +3 -4
- package/dist/apps/shared/components/mail/MailSelectionBar.js +2 -3
- package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +18 -7
- package/dist/apps/shared/components/mail/MessageDetailPane.js +86 -41
- package/dist/apps/shared/components/mail/OutboxBadge.d.ts +17 -0
- package/dist/apps/shared/components/mail/OutboxBadge.js +18 -0
- package/dist/apps/shared/components/mail/OutboxRowStatus.d.ts +10 -0
- package/dist/apps/shared/components/mail/OutboxRowStatus.js +19 -0
- package/dist/apps/shared/components/mail/compose/ComposeContext.d.ts +8 -0
- package/dist/apps/shared/components/mail/compose/ComposeContext.js +28 -3
- package/dist/apps/shared/components/mail/compose/ComposeWindow.d.ts +2 -1
- package/dist/apps/shared/components/mail/compose/ComposeWindow.js +229 -328
- package/dist/apps/shared/components/mail/compose/encryptionRequirement.d.ts +49 -0
- package/dist/apps/shared/components/mail/compose/encryptionRequirement.js +35 -0
- package/dist/apps/shared/components/mail/layout/MailShell.d.ts +2 -0
- package/dist/apps/shared/components/mail/layout/MailShell.js +20 -14
- package/dist/apps/shared/components/mail/reading/EncryptedBody.d.ts +21 -0
- package/dist/apps/shared/components/mail/reading/EncryptedBody.js +22 -0
- package/dist/apps/shared/components/mail/reading/EncryptedPreview.d.ts +18 -0
- package/dist/apps/shared/components/mail/reading/EncryptedPreview.js +22 -0
- package/dist/apps/shared/components/mail/reading/MessageBody.d.ts +32 -0
- package/dist/apps/shared/components/mail/reading/MessageBody.js +136 -0
- package/dist/apps/shared/components/mail/reading/MessageCard.d.ts +62 -0
- package/dist/apps/shared/components/mail/reading/MessageCard.js +58 -0
- package/dist/apps/shared/components/mail/reading/bodyContent.d.ts +38 -0
- package/dist/apps/shared/components/mail/reading/bodyContent.js +84 -0
- package/dist/apps/shared/components/mail/reading/bodyHtml.d.ts +47 -0
- package/dist/apps/shared/components/mail/reading/bodyHtml.js +267 -0
- package/dist/apps/shared/components/mail/reading/color.d.ts +63 -0
- package/dist/apps/shared/components/mail/reading/color.js +201 -0
- package/dist/apps/shared/components/mail/reading/frameControl.d.ts +33 -0
- package/dist/apps/shared/components/mail/reading/frameControl.js +120 -0
- package/dist/apps/shared/components/mail/reading/frameDocument.d.ts +52 -0
- package/dist/apps/shared/components/mail/reading/frameDocument.js +98 -0
- package/dist/apps/shared/components/mail/reading/safeDocument.d.ts +3 -0
- package/dist/apps/shared/components/mail/reading/safeDocument.js +12 -0
- package/dist/apps/shared/components/mail/reading/themeAdaptation.d.ts +56 -0
- package/dist/apps/shared/components/mail/reading/themeAdaptation.js +144 -0
- package/dist/apps/shared/components/mail/reading/themeSurface.d.ts +17 -0
- package/dist/apps/shared/components/mail/reading/themeSurface.js +83 -0
- package/dist/apps/shared/components/mail/reading/viewOriginal.d.ts +9 -0
- package/dist/apps/shared/components/mail/reading/viewOriginal.js +32 -0
- package/dist/apps/shared/components/settings/SigningCertificateCard.d.ts +32 -0
- package/dist/apps/shared/components/settings/SigningCertificateCard.js +98 -0
- package/dist/apps/shared/components/settings/layout/SettingsShell.js +1 -0
- package/dist/apps/shared/components/sharing/PrincipalListField.d.ts +24 -0
- package/dist/apps/shared/components/sharing/PrincipalListField.js +23 -0
- package/dist/apps/shared/components/sharing/PrincipalPicker.d.ts +28 -0
- package/dist/apps/shared/components/sharing/PrincipalPicker.js +24 -0
- package/dist/apps/shared/components/sharing/PrincipalResolver.d.ts +44 -0
- package/dist/apps/shared/components/sharing/PrincipalResolver.js +92 -0
- package/dist/apps/shared/components/tasks/TasksSidebar.js +4 -2
- package/dist/apps/shared/components/tasks/layout/TasksShell.js +3 -1
- package/dist/apps/shared/mail/folderCounts.d.ts +1 -1
- package/dist/apps/shared/mail/folderCounts.js +9 -3
- package/dist/apps/shared/mail/folderTree.d.ts +55 -0
- package/dist/apps/shared/mail/folderTree.js +116 -0
- package/dist/apps/shared/mail/outbox/UnlockBridge.d.ts +5 -0
- package/dist/apps/shared/mail/outbox/UnlockBridge.js +18 -0
- package/dist/apps/shared/mail/outbox/composeBridge.d.ts +34 -0
- package/dist/apps/shared/mail/outbox/composeBridge.js +32 -0
- package/dist/apps/shared/mail/outbox/outboxState.d.ts +41 -0
- package/dist/apps/shared/mail/outbox/outboxState.js +42 -0
- package/dist/apps/shared/mail/outbox/pendingSends.d.ts +39 -0
- package/dist/apps/shared/mail/outbox/pendingSends.js +109 -0
- package/dist/apps/shared/mail/outbox/sendDecision.d.ts +80 -0
- package/dist/apps/shared/mail/outbox/sendDecision.js +94 -0
- package/dist/apps/shared/mail/outbox/sendJob.d.ts +68 -0
- package/dist/apps/shared/mail/outbox/sendJob.js +319 -0
- package/dist/apps/shared/mail/outbox/sendOutcomes.d.ts +3 -0
- package/dist/apps/shared/mail/outbox/sendOutcomes.js +141 -0
- package/dist/apps/shared/mail/outbox/sendState.d.ts +25 -0
- package/dist/apps/shared/mail/outbox/sendState.js +8 -0
- package/dist/apps/shared/mail/outbox/useOutboxStatus.d.ts +11 -0
- package/dist/apps/shared/mail/outbox/useOutboxStatus.js +49 -0
- package/dist/apps/shared/mail/useMailConnection.d.ts +9 -8
- package/dist/apps/shared/mail/useMailConnection.js +64 -22
- package/dist/apps/shared/mail/useMailLiveUpdates.d.ts +17 -4
- package/dist/apps/shared/mail/useMailLiveUpdates.js +36 -10
- package/dist/apps/shared/mail/useNewMailNotifications.d.ts +4 -10
- package/dist/apps/shared/mail/useNewMailNotifications.js +43 -23
- package/dist/apps/shared/navigation/AppRouter.js +2 -2
- package/dist/apps/shared/notifications/NotificationCenter.d.ts +19 -0
- package/dist/apps/shared/notifications/NotificationCenter.js +90 -0
- package/dist/apps/shared/notifications/NotificationHistoryDialog.d.ts +10 -0
- package/dist/apps/shared/notifications/NotificationHistoryDialog.js +36 -0
- package/dist/apps/shared/notifications/apiErrors.d.ts +19 -0
- package/dist/apps/shared/notifications/apiErrors.js +86 -0
- package/dist/apps/shared/notifications/headerOffset.d.ts +8 -0
- package/dist/apps/shared/notifications/headerOffset.js +33 -0
- package/dist/apps/shared/notifications/pushStatus.d.ts +9 -0
- package/dist/apps/shared/notifications/pushStatus.js +54 -0
- package/dist/apps/shared/notifications/store.d.ts +136 -0
- package/dist/apps/shared/notifications/store.js +416 -0
- package/dist/apps/shared/notifications/systemErrors.d.ts +9 -0
- package/dist/apps/shared/notifications/systemErrors.js +58 -0
- package/dist/apps/shared/notifications/useNotifications.d.ts +17 -0
- package/dist/apps/shared/notifications/useNotifications.js +18 -0
- package/dist/apps/shared/signing/enrollmentStorage.d.ts +10 -0
- package/dist/apps/shared/signing/enrollmentStorage.js +33 -0
- package/dist/apps/shared/signing/enrollmentTracker.d.ts +73 -0
- package/dist/apps/shared/signing/enrollmentTracker.js +307 -0
- package/dist/apps/shared/signing/enrollmentView.d.ts +57 -0
- package/dist/apps/shared/signing/enrollmentView.js +214 -0
- package/dist/apps/shared/signing/signingInfo.d.ts +11 -0
- package/dist/apps/shared/signing/signingInfo.js +48 -0
- package/dist/apps/shared/signing/useNow.d.ts +2 -0
- package/dist/apps/shared/signing/useNow.js +18 -0
- package/dist/apps/shared/signing/useSigningEnrollmentWatcher.d.ts +16 -0
- package/dist/apps/shared/signing/useSigningEnrollmentWatcher.js +87 -0
- package/dist/apps/shared/styles/app.css +80 -0
- package/dist/apps/www/_layout.d.ts +5 -1
- package/dist/apps/www/_layout.js +3 -2
- package/dist/apps/www/_routes.js +1 -0
- package/dist/apps/www/calendar/index.js +3 -4
- package/dist/apps/www/contacts/[uid].js +5 -7
- package/dist/apps/www/contacts/index.js +14 -21
- package/dist/apps/www/index.js +37 -19
- package/dist/apps/www/messages/[uid].js +3 -1
- package/dist/apps/www/settings/appearance/index.d.ts +4 -0
- package/dist/apps/www/settings/appearance/index.js +13 -0
- package/dist/apps/www/settings/auto-reply/index.js +3 -6
- package/dist/apps/www/settings/encryption/index.js +103 -95
- package/dist/apps/www/settings/filters/[uid].js +3 -1
- package/dist/apps/www/settings/filters/new/index.js +3 -1
- package/dist/apps/www/settings/privacy/index.js +5 -8
- package/dist/apps/www/settings/read-receipts/index.js +3 -6
- package/dist/apps/www/settings/sharing/index.js +19 -33
- package/dist/apps/www/settings/signatures/[uid].js +3 -1
- package/dist/apps/www/settings/signatures/new/index.js +3 -2
- package/dist/apps/www/tasks/index.js +8 -14
- package/package.json +2 -2
- package/apps/shared/components/mail/NewMailToasts.tsx +0 -141
- package/apps/shared/components/mail/compose/SendFailureAlert.tsx +0 -48
- package/dist/apps/shared/components/mail/NewMailToasts.d.ts +0 -19
- package/dist/apps/shared/components/mail/NewMailToasts.js +0 -55
- package/dist/apps/shared/components/mail/compose/SendFailureAlert.d.ts +0 -14
- package/dist/apps/shared/components/mail/compose/SendFailureAlert.js +0 -11
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
3
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
4
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
5
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
6
|
+
import { useEffect, useRef } from "react";
|
|
7
|
+
import Modal from "@rapidmx/react-shared/components/overlays/Modal.js";
|
|
8
|
+
import CopyButton from "@rapidmx/react-shared/components/buttons/CopyButton.js";
|
|
9
|
+
import { useNotifications } from "./useNotifications.js";
|
|
10
|
+
const KIND_LABEL = {
|
|
11
|
+
mail: "New message",
|
|
12
|
+
info: "Information",
|
|
13
|
+
success: "Done",
|
|
14
|
+
warning: "Warning",
|
|
15
|
+
error: "Error",
|
|
16
|
+
};
|
|
17
|
+
function HistoryItem({ entry, unseen }) {
|
|
18
|
+
return (_jsxs("li", { className: ["border-b border-border py-2.5 last:border-b-0", unseen ? "-mx-2 rounded-sm bg-danger-bg/60 px-2" : ""].join(" "), children: [_jsxs("div", { className: "flex items-baseline justify-between gap-3 text-xs text-text-muted", children: [_jsx("span", { className: ["font-semibold uppercase tracking-wide", entry.kind === "error" ? "text-danger" : ""].join(" "), children: KIND_LABEL[entry.kind] }), _jsx("time", { dateTime: new Date(entry.at).toISOString(), children: new Date(entry.at).toLocaleTimeString() })] }), _jsxs("p", { className: "mt-0.5 text-sm font-semibold [overflow-wrap:anywhere]", children: [entry.title, entry.count > 1 && _jsxs("span", { className: "ml-1.5 text-xs font-medium text-text-muted", children: ["\u00D7", entry.count] })] }), entry.message && _jsx("p", { className: "text-sm text-text-muted [overflow-wrap:anywhere]", children: entry.message }), entry.details.length > 0 && (_jsxs("details", { className: "mt-1", children: [_jsx("summary", { className: "cursor-pointer text-xs font-semibold text-text-muted", children: "Technical details" }), _jsx("ul", { "aria-label": "Technical details", className: "mt-1.5 max-h-40 overflow-auto rounded-sm border border-border bg-surface-alt p-2 font-mono text-xs select-text", children: entry.details.map((line, index) => (_jsx("li", { className: "whitespace-pre-wrap break-words", children: line }, index))) }), _jsx("div", { className: "mt-1.5", children: _jsx(CopyButton, { value: entry.details.join("\n"), label: "Copy technical details" }) })] }))] }));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* "Recent notifications": the last few pop-ups, newest first, so nothing is lost when one expires. Opening it counts as having seen
|
|
22
|
+
* them (the unseen-error count on the account menu goes), but the errors that were unseen when it opened stay highlighted until it closes.
|
|
23
|
+
*/
|
|
24
|
+
export default function NotificationHistoryDialog({ open, onClose }) {
|
|
25
|
+
const { history, markHistorySeen, clearHistory } = useNotifications();
|
|
26
|
+
const unseenAtOpenRef = useRef(new Set());
|
|
27
|
+
if (!open) {
|
|
28
|
+
unseenAtOpenRef.current = new Set(history.filter((entry) => entry.unseen && entry.kind === "error").map((entry) => entry.id));
|
|
29
|
+
}
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (open) {
|
|
32
|
+
markHistorySeen();
|
|
33
|
+
}
|
|
34
|
+
}, [open, markHistorySeen]);
|
|
35
|
+
return (_jsx(Modal, { open: open, onClose: onClose, title: "Recent notifications", children: history.length === 0 ? (_jsx("p", { className: "text-sm text-text-muted", children: "Nothing yet. Errors, sent messages and other pop-ups from this session are listed here." })) : (_jsxs(_Fragment, { children: [_jsx("ul", { "aria-label": "Recent notifications", children: history.map((entry) => (_jsx(HistoryItem, { entry: entry, unseen: unseenAtOpenRef.current.has(entry.id) }, entry.id))) }), _jsx("div", { className: "mt-4", children: _jsx("button", { type: "button", onClick: clearHistory, className: "rounded-sm px-2.5 py-1 text-xs font-semibold text-primary-dark hover:bg-surface-alt", children: "Clear list" }) })] })) }));
|
|
36
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NotificationAction } from "./store.js";
|
|
2
|
+
/** Whether `err` is a request that was cancelled (`AbortError`) - by name, since a `DOMException` is not always an `Error` (jsdom's is not). */
|
|
3
|
+
export declare function isAbortError(err: unknown): boolean;
|
|
4
|
+
export declare function setSignInUrl(authServerUrl: string | undefined): void;
|
|
5
|
+
/** The "Your session expired" pop-up: one however many requests noticed, with a "Sign in" action. Returns its id. */
|
|
6
|
+
export declare function notifySessionExpired(): string;
|
|
7
|
+
export interface NotifyApiErrorOptions {
|
|
8
|
+
/** Extra actions (a "Retry"). */
|
|
9
|
+
actions?: NotificationAction[];
|
|
10
|
+
/** Replaces the default key (`api:<context>:<status>`): errors with one key are one pop-up with a count. */
|
|
11
|
+
dedupeKey?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Turns the failure of something the user did into an `error` pop-up and returns its id - or, for a `401`, into "Your session expired"
|
|
15
|
+
* with a Sign in action, and for a request that was cancelled into nothing (`""`). `context` says what was being attempted, as the
|
|
16
|
+
* pop-up's title ("Couldn't archive this message"); the message is the server's own, and its technical facts (`describeSendFailure()`'s
|
|
17
|
+
* lines, the status and code) are the expandable details. The same failing thing repeating is one pop-up with a count.
|
|
18
|
+
*/
|
|
19
|
+
export declare function notifyApiError(err: unknown, context: string, options?: NotifyApiErrorOptions): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { ApiRequestError } from "@rapidmx/react-shared/util/api.js";
|
|
6
|
+
import { describeSendFailure } from "@rapidmx/react-shared/mail/sendFailure.js";
|
|
7
|
+
import { notify } from "./store.js";
|
|
8
|
+
/** Whether `err` is a request that was cancelled (`AbortError`) - by name, since a `DOMException` is not always an `Error` (jsdom's is not). */
|
|
9
|
+
export function isAbortError(err) {
|
|
10
|
+
return typeof err === "object" && err !== null && err.name === "AbortError";
|
|
11
|
+
}
|
|
12
|
+
/** Where "Sign in" goes: auth-server's base URL, set once by the app frame. Without one it reloads the page, which redirects when signed out. */
|
|
13
|
+
let signInBaseUrl;
|
|
14
|
+
export function setSignInUrl(authServerUrl) {
|
|
15
|
+
signInBaseUrl = authServerUrl;
|
|
16
|
+
}
|
|
17
|
+
/** The "Your session expired" pop-up: one however many requests noticed, with a "Sign in" action. Returns its id. */
|
|
18
|
+
export function notifySessionExpired() {
|
|
19
|
+
return notify({
|
|
20
|
+
kind: "error",
|
|
21
|
+
title: "Your session expired",
|
|
22
|
+
message: "Sign in again to keep working. Anything not yet saved in this tab is still here until you leave it.",
|
|
23
|
+
dedupeKey: "session-expired",
|
|
24
|
+
actions: [
|
|
25
|
+
{
|
|
26
|
+
label: "Sign in",
|
|
27
|
+
onClick: () => {
|
|
28
|
+
if (signInBaseUrl) {
|
|
29
|
+
window.location.href = `${signInBaseUrl}/auth/signin?return_to=${encodeURIComponent(window.location.href)}`;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
window.location.reload();
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/** Whether `err` is a request that never got an answer (offline, DNS, a dropped connection) rather than an error response. */
|
|
40
|
+
function isNetworkFailure(err) {
|
|
41
|
+
return err instanceof TypeError || (err instanceof Error && /network|failed to fetch|load failed/i.test(err.message));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Turns the failure of something the user did into an `error` pop-up and returns its id - or, for a `401`, into "Your session expired"
|
|
45
|
+
* with a Sign in action, and for a request that was cancelled into nothing (`""`). `context` says what was being attempted, as the
|
|
46
|
+
* pop-up's title ("Couldn't archive this message"); the message is the server's own, and its technical facts (`describeSendFailure()`'s
|
|
47
|
+
* lines, the status and code) are the expandable details. The same failing thing repeating is one pop-up with a count.
|
|
48
|
+
*/
|
|
49
|
+
export function notifyApiError(err, context, options = {}) {
|
|
50
|
+
if (isAbortError(err)) {
|
|
51
|
+
return "";
|
|
52
|
+
}
|
|
53
|
+
if (err instanceof ApiRequestError) {
|
|
54
|
+
if (err.status === 401) {
|
|
55
|
+
return notifySessionExpired();
|
|
56
|
+
}
|
|
57
|
+
const failure = describeSendFailure(err, context);
|
|
58
|
+
const facts = [`Status: ${err.status}${err.code ? ` (${err.code})` : ""}`, ...failure.lines];
|
|
59
|
+
return notify({
|
|
60
|
+
kind: "error",
|
|
61
|
+
title: context,
|
|
62
|
+
message: failure.message,
|
|
63
|
+
details: facts,
|
|
64
|
+
actions: options.actions,
|
|
65
|
+
dedupeKey: options.dedupeKey ?? `api:${context}:${err.status}`,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (isNetworkFailure(err)) {
|
|
69
|
+
return notify({
|
|
70
|
+
kind: "error",
|
|
71
|
+
title: context,
|
|
72
|
+
message: "The server couldn't be reached. Check your connection and try again.",
|
|
73
|
+
details: [err.message],
|
|
74
|
+
actions: options.actions,
|
|
75
|
+
dedupeKey: options.dedupeKey ?? `api:${context}:network`,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return notify({
|
|
79
|
+
kind: "error",
|
|
80
|
+
title: context,
|
|
81
|
+
message: "Something unexpected went wrong.",
|
|
82
|
+
details: err instanceof Error ? [`${err.name}: ${err.message}`] : [String(err)],
|
|
83
|
+
actions: options.actions,
|
|
84
|
+
dedupeKey: options.dedupeKey ?? `api:${context}:unexpected`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** The CSS variable (on `<html>`) that holds the height, in px, of the frame's sticky header - its title bar or the branding header. */
|
|
2
|
+
export declare const HEADER_HEIGHT_VAR = "--rr-header-h";
|
|
3
|
+
/**
|
|
4
|
+
* A ref callback for the frame's sticky `<header>`: publishes its height as `--rr-header-h` (and keeps it current as the header resizes -
|
|
5
|
+
* a branded header can be any height and wraps on a phone), so the pop-up stack (`NotificationCenter`) can stick just below it instead of
|
|
6
|
+
* sliding under it or over the account menu. When the header goes (a page without one) the variable is set to 0 rather than left stale.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useHeaderHeightRef(): (element: HTMLElement | null) => void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { useCallback, useRef } from "react";
|
|
6
|
+
/** The CSS variable (on `<html>`) that holds the height, in px, of the frame's sticky header - its title bar or the branding header. */
|
|
7
|
+
export const HEADER_HEIGHT_VAR = "--rr-header-h";
|
|
8
|
+
/**
|
|
9
|
+
* A ref callback for the frame's sticky `<header>`: publishes its height as `--rr-header-h` (and keeps it current as the header resizes -
|
|
10
|
+
* a branded header can be any height and wraps on a phone), so the pop-up stack (`NotificationCenter`) can stick just below it instead of
|
|
11
|
+
* sliding under it or over the account menu. When the header goes (a page without one) the variable is set to 0 rather than left stale.
|
|
12
|
+
*/
|
|
13
|
+
export function useHeaderHeightRef() {
|
|
14
|
+
const stop = useRef(undefined);
|
|
15
|
+
return useCallback((element) => {
|
|
16
|
+
stop.current?.();
|
|
17
|
+
stop.current = undefined;
|
|
18
|
+
const root = document.documentElement;
|
|
19
|
+
if (!element) {
|
|
20
|
+
root.style.setProperty(HEADER_HEIGHT_VAR, "0px");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const publish = () => root.style.setProperty(HEADER_HEIGHT_VAR, `${Math.round(element.getBoundingClientRect().height)}px`);
|
|
24
|
+
publish();
|
|
25
|
+
const observer = typeof ResizeObserver === "undefined" ? undefined : new ResizeObserver(publish);
|
|
26
|
+
observer?.observe(element);
|
|
27
|
+
window.addEventListener("resize", publish);
|
|
28
|
+
stop.current = () => {
|
|
29
|
+
observer?.disconnect();
|
|
30
|
+
window.removeEventListener("resize", publish);
|
|
31
|
+
};
|
|
32
|
+
}, []);
|
|
33
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** How long the live connection has to be down before anyone is told: a reconnect within a few seconds is not worth a word. */
|
|
2
|
+
export declare const PUSH_OFFLINE_NOTICE_MS = 10000;
|
|
3
|
+
export declare const PUSH_NOTICE_ID = "push-connection";
|
|
4
|
+
/**
|
|
5
|
+
* A subtle info pop-up when the live connection (new mail, folder counts, send results) has been down for more than `PUSH_OFFLINE_NOTICE_MS`,
|
|
6
|
+
* which goes by itself the moment it is back. Shown once per outage - dismissing it does not bring it back until the connection has
|
|
7
|
+
* reconnected and dropped again. The page keeps working meanwhile (it polls), which is what the message says.
|
|
8
|
+
*/
|
|
9
|
+
export declare function usePushConnectionNotice(enabled: boolean): void;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { useEffect } from "react";
|
|
6
|
+
import { getPushClient } from "@rapidmx/react-shared/mail/pushClient.js";
|
|
7
|
+
import { dismiss, notify } from "./store.js";
|
|
8
|
+
/** How long the live connection has to be down before anyone is told: a reconnect within a few seconds is not worth a word. */
|
|
9
|
+
export const PUSH_OFFLINE_NOTICE_MS = 10000;
|
|
10
|
+
export const PUSH_NOTICE_ID = "push-connection";
|
|
11
|
+
/**
|
|
12
|
+
* A subtle info pop-up when the live connection (new mail, folder counts, send results) has been down for more than `PUSH_OFFLINE_NOTICE_MS`,
|
|
13
|
+
* which goes by itself the moment it is back. Shown once per outage - dismissing it does not bring it back until the connection has
|
|
14
|
+
* reconnected and dropped again. The page keeps working meanwhile (it polls), which is what the message says.
|
|
15
|
+
*/
|
|
16
|
+
export function usePushConnectionNotice(enabled) {
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!enabled) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const client = getPushClient();
|
|
22
|
+
let timer;
|
|
23
|
+
let shown = false;
|
|
24
|
+
const off = client.onStatus((status) => {
|
|
25
|
+
if (status === "reconnecting") {
|
|
26
|
+
if (timer === undefined && !shown) {
|
|
27
|
+
timer = setTimeout(() => {
|
|
28
|
+
shown = true;
|
|
29
|
+
notify({
|
|
30
|
+
id: PUSH_NOTICE_ID,
|
|
31
|
+
kind: "info",
|
|
32
|
+
title: "Live updates are paused",
|
|
33
|
+
message: "The connection is being restored. The page keeps refreshing on its own, so new mail may take a little longer to appear.",
|
|
34
|
+
sticky: true,
|
|
35
|
+
history: false,
|
|
36
|
+
});
|
|
37
|
+
}, PUSH_OFFLINE_NOTICE_MS);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
timer = undefined;
|
|
43
|
+
if (status === "open" && shown) {
|
|
44
|
+
shown = false;
|
|
45
|
+
dismiss(PUSH_NOTICE_ID);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return () => {
|
|
50
|
+
off();
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
};
|
|
53
|
+
}, [enabled]);
|
|
54
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The app's one notification store: every pop-up - new mail, a failed send, an API error, an expired session - goes through
|
|
3
|
+
* `notify()`. It is deliberately framework-free (no React, no DOM beyond `sessionStorage`/timers), so it can be called from a hook,
|
|
4
|
+
* a plain function or an `apiFetch` error path alike; `NotificationCenter` (the view, mounted once in the app frame) and
|
|
5
|
+
* `useNotifications()` only *read* it.
|
|
6
|
+
*
|
|
7
|
+
* Rules, all enforced here rather than by the view so they hold whoever renders:
|
|
8
|
+
*
|
|
9
|
+
* - **At most `MAX_VISIBLE` (3) are visible**; the rest wait in a queue and appear as room is made. A sticky notification (an error, or
|
|
10
|
+
* anything with actions) that finds the stack full pushes out the oldest one that would have gone by itself, rather than waiting behind
|
|
11
|
+
* it. A queued notification that has waited `QUEUE_STALE_MS` is dropped (it would be news from the past) - it is still in the history.
|
|
12
|
+
* - **Sticky until dismissed or resolved**: errors and notifications with actions never expire (`update()` or `dismiss()` resolve them).
|
|
13
|
+
* Everything else goes by itself after its kind's default time, or `timeoutMs`. `sticky` overrides both ways.
|
|
14
|
+
* - **A clock that stops**: a notification's remaining time stops while it is hovered or focused (`setPaused()`) and while the tab is
|
|
15
|
+
* hidden (`setAllPaused()`), and continues from where it was.
|
|
16
|
+
* - **Deduplicated by `dedupeKey`**: a second notification with a key that is still on screen (or waiting) does not stack - it replaces
|
|
17
|
+
* the first one's content, restarts its clock and raises its `count`, so a flapping error is one pop-up saying "x3".
|
|
18
|
+
* - **Nothing is lost when one goes**: the last `HISTORY_LIMIT` (30, except new-mail pop-ups, which the inbox already holds) are
|
|
19
|
+
* kept, in memory and in `sessionStorage`, with which errors nobody has seen yet.
|
|
20
|
+
*
|
|
21
|
+
* Nothing is stored where there is no `window` (server-side rendering): the module state is shared between requests there, so
|
|
22
|
+
* `notify()` only hands back an id.
|
|
23
|
+
*/
|
|
24
|
+
export type NotificationKind = "mail" | "info" | "success" | "warning" | "error";
|
|
25
|
+
export interface NotificationAction {
|
|
26
|
+
label: string;
|
|
27
|
+
/** Runs when the action is used. */
|
|
28
|
+
onClick?: () => void;
|
|
29
|
+
/** Or a link to follow (a plain `<a>`, so the router's link handling applies). */
|
|
30
|
+
href?: string;
|
|
31
|
+
/** Leave the notification on screen after the action ran. By default an action resolves (dismisses) it. */
|
|
32
|
+
keepOpen?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface NotifyInput {
|
|
35
|
+
/** Reuse an id to replace a notification (it is the same one: its content is swapped and its clock restarted). Generated when absent. */
|
|
36
|
+
id?: string;
|
|
37
|
+
kind: NotificationKind;
|
|
38
|
+
title: string;
|
|
39
|
+
/** A second, muted line next to the title (a mail pop-up's sender address). */
|
|
40
|
+
subtitle?: string;
|
|
41
|
+
message?: string;
|
|
42
|
+
/** A mail pop-up's preview text, under `message` (its subject). */
|
|
43
|
+
preview?: string;
|
|
44
|
+
/** A small muted explanation above the actions (the desktop-notification offer). */
|
|
45
|
+
hint?: string;
|
|
46
|
+
/** Technical detail: a list of lines, or one block of text. Shown collapsed, monospace, with a copy button. */
|
|
47
|
+
details?: string[] | string;
|
|
48
|
+
actions?: NotificationAction[];
|
|
49
|
+
/** The whole pop-up is a link to this (new mail opens the message). */
|
|
50
|
+
href?: string;
|
|
51
|
+
/** Never expires by itself. Default: errors and anything with actions. */
|
|
52
|
+
sticky?: boolean;
|
|
53
|
+
/** How long it stays, in ms. Default by kind, see `DEFAULT_TIMEOUT_MS`. Ignored for a sticky one. */
|
|
54
|
+
timeoutMs?: number;
|
|
55
|
+
/** Notifications with the same key that are still showing are one: see the module doc comment. */
|
|
56
|
+
dedupeKey?: string;
|
|
57
|
+
/** Keep it out of the history (default: kept, except `mail`). */
|
|
58
|
+
history?: boolean;
|
|
59
|
+
}
|
|
60
|
+
/** A notification as a view renders it. */
|
|
61
|
+
export interface NotificationView {
|
|
62
|
+
id: string;
|
|
63
|
+
kind: NotificationKind;
|
|
64
|
+
title: string;
|
|
65
|
+
subtitle?: string;
|
|
66
|
+
message?: string;
|
|
67
|
+
preview?: string;
|
|
68
|
+
hint?: string;
|
|
69
|
+
details: string[];
|
|
70
|
+
actions: NotificationAction[];
|
|
71
|
+
href?: string;
|
|
72
|
+
/** How many times this one was raised (`dedupeKey`), 1 for a single one. */
|
|
73
|
+
count: number;
|
|
74
|
+
sticky: boolean;
|
|
75
|
+
createdAt: number;
|
|
76
|
+
}
|
|
77
|
+
export interface HistoryEntry {
|
|
78
|
+
id: string;
|
|
79
|
+
kind: NotificationKind;
|
|
80
|
+
title: string;
|
|
81
|
+
message?: string;
|
|
82
|
+
details: string[];
|
|
83
|
+
count: number;
|
|
84
|
+
/** When it was last raised (epoch ms). */
|
|
85
|
+
at: number;
|
|
86
|
+
/** Nobody has opened the history since it arrived. */
|
|
87
|
+
unseen: boolean;
|
|
88
|
+
}
|
|
89
|
+
export interface NotificationsSnapshot {
|
|
90
|
+
/** What is on screen, oldest first. */
|
|
91
|
+
visible: NotificationView[];
|
|
92
|
+
/** How many are waiting for room. */
|
|
93
|
+
queued: number;
|
|
94
|
+
/** The last `HISTORY_LIMIT`, newest first. */
|
|
95
|
+
history: HistoryEntry[];
|
|
96
|
+
/** Errors in the history that nobody has looked at. */
|
|
97
|
+
unseenErrors: number;
|
|
98
|
+
}
|
|
99
|
+
export declare const MAX_VISIBLE = 3;
|
|
100
|
+
export declare const MAX_QUEUED = 20;
|
|
101
|
+
export declare const QUEUE_STALE_MS = 30000;
|
|
102
|
+
export declare const HISTORY_LIMIT = 30;
|
|
103
|
+
export declare const HISTORY_STORAGE_KEY = "rapidmx-notification-history";
|
|
104
|
+
/** The most technical lines and the longest line kept per notification - a transport error can carry a whole SMTP transcript. */
|
|
105
|
+
export declare const MAX_DETAIL_LINES = 50;
|
|
106
|
+
export declare const MAX_DETAIL_LINE_LENGTH = 500;
|
|
107
|
+
/** How long a non-sticky notification stays, by kind. Errors are sticky, so theirs is only for an explicit `sticky: false`. */
|
|
108
|
+
export declare const DEFAULT_TIMEOUT_MS: Record<NotificationKind, number>;
|
|
109
|
+
/**
|
|
110
|
+
* Raises a notification and returns its id. See the module doc comment for what happens to it. Usable from anywhere - a component, a
|
|
111
|
+
* hook, a plain function, an `apiFetch` error path - and safe where there is no window (it does nothing there).
|
|
112
|
+
*/
|
|
113
|
+
export declare function notify(input: NotifyInput): string;
|
|
114
|
+
/**
|
|
115
|
+
* Changes a notification that is still showing or waiting - the way to resolve it ("Sending..." becoming "Sent"). Only the given
|
|
116
|
+
* fields change. Its clock restarts, and it may become sticky or stop being so with its new kind. Returns `false` when there is no such
|
|
117
|
+
* notification any more (it was dismissed or expired); its history entry is updated all the same.
|
|
118
|
+
*/
|
|
119
|
+
export declare function update(id: string, patch: Partial<Omit<NotifyInput, "id" | "dedupeKey">>): boolean;
|
|
120
|
+
/** Removes a notification from the screen (or the queue). Its history entry stays. Does nothing for an unknown id. */
|
|
121
|
+
export declare function dismiss(id: string): void;
|
|
122
|
+
/** Removes everything showing and waiting. */
|
|
123
|
+
export declare function dismissAll(): void;
|
|
124
|
+
/** Stops (or restarts) one notification's clock: it is being hovered or holds the keyboard focus. */
|
|
125
|
+
export declare function setPaused(id: string, paused: boolean): void;
|
|
126
|
+
/** Stops (or restarts) every clock: the tab is hidden, so nobody could have read what is on screen. */
|
|
127
|
+
export declare function setAllPaused(paused: boolean): void;
|
|
128
|
+
/** Marks every history entry as seen - the user has opened the history. */
|
|
129
|
+
export declare function markHistorySeen(): void;
|
|
130
|
+
/** Empties the history. */
|
|
131
|
+
export declare function clearHistory(): void;
|
|
132
|
+
export declare function subscribeNotifications(listener: () => void): () => void;
|
|
133
|
+
export declare function getNotificationsSnapshot(): NotificationsSnapshot;
|
|
134
|
+
export declare function getServerNotificationsSnapshot(): NotificationsSnapshot;
|
|
135
|
+
/** Forgets everything and stops every clock - for a test, or a page that outlives its session. */
|
|
136
|
+
export declare function resetNotifications(): void;
|