@remit/web-client 0.0.325 → 0.0.326
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/dist/harness/index.html +50 -0
- package/dist/harness/vite-preset.d.ts +10 -0
- package/dist/harness/vite-preset.js +151 -0
- package/dist/spellcheck/languages.d.ts +33 -0
- package/dist/spellcheck/languages.js +66 -0
- package/dist/spellcheck/vite-plugin.d.ts +43 -0
- package/dist/spellcheck/vite-plugin.js +294 -0
- package/dist/spellcheck/worker-stub.d.ts +15 -0
- package/dist/spellcheck/worker-stub.js +33 -0
- package/dist/src/auth/AccountMenu.d.ts +1 -0
- package/dist/src/auth/AccountMenu.js +4 -0
- package/dist/src/auth/AccountSession.d.ts +14 -0
- package/dist/src/auth/AccountSession.js +12 -0
- package/dist/src/auth/BetterAuthShell.d.ts +18 -0
- package/dist/src/auth/BetterAuthShell.js +88 -0
- package/dist/src/auth/SessionRateLimited.d.ts +12 -0
- package/dist/src/auth/SessionRateLimited.js +10 -0
- package/dist/src/auth/SignInAgain.d.ts +1 -0
- package/dist/src/auth/SignInAgain.js +6 -0
- package/dist/src/auth/account-menu-mode.d.ts +13 -0
- package/dist/src/auth/account-menu-mode.js +15 -0
- package/dist/src/auth/amplify-config.d.ts +9 -0
- package/dist/src/auth/amplify-config.js +43 -0
- package/dist/src/auth/auth-error.d.ts +42 -0
- package/dist/src/auth/auth-error.js +81 -0
- package/dist/src/auth/auth-interceptor.d.ts +12 -0
- package/dist/src/auth/auth-interceptor.js +24 -0
- package/dist/src/auth/better-auth/BetterAuthAccount.d.ts +7 -0
- package/dist/src/auth/better-auth/BetterAuthAccount.js +18 -0
- package/dist/src/auth/better-auth-config.d.ts +43 -0
- package/dist/src/auth/better-auth-config.js +215 -0
- package/dist/src/auth/better-auth-provider.d.ts +7 -0
- package/dist/src/auth/better-auth-provider.js +15 -0
- package/dist/src/auth/cognito/CognitoAccount.d.ts +8 -0
- package/dist/src/auth/cognito/CognitoAccount.js +32 -0
- package/dist/src/auth/cognito/CognitoShell.d.ts +6 -0
- package/dist/src/auth/cognito/CognitoShell.js +204 -0
- package/dist/src/auth/cognito/cognito-token.d.ts +9 -0
- package/dist/src/auth/cognito/cognito-token.js +36 -0
- package/dist/src/auth/cognito-provider.d.ts +8 -0
- package/dist/src/auth/cognito-provider.js +17 -0
- package/dist/src/auth/combined-provider.d.ts +2 -0
- package/dist/src/auth/combined-provider.js +27 -0
- package/dist/src/auth/provider.d.ts +51 -0
- package/dist/src/auth/provider.js +18 -0
- package/dist/src/auth/session-state.d.ts +29 -0
- package/dist/src/auth/session-state.js +16 -0
- package/dist/src/auth/sign-out-visibility.d.ts +5 -0
- package/dist/src/auth/sign-out-visibility.js +1 -0
- package/dist/src/components/calendar/AgendaStrip.d.ts +64 -0
- package/dist/src/components/calendar/AgendaStrip.js +19 -0
- package/dist/src/components/calendar/AgendaView.d.ts +42 -0
- package/dist/src/components/calendar/AgendaView.js +131 -0
- package/dist/src/components/calendar/CalendarComposePane.d.ts +49 -0
- package/dist/src/components/calendar/CalendarComposePane.js +8 -0
- package/dist/src/components/calendar/CalendarComposeSeed.d.ts +7 -0
- package/dist/src/components/calendar/CalendarComposeSeed.js +19 -0
- package/dist/src/components/calendar/CalendarEventPane.d.ts +48 -0
- package/dist/src/components/calendar/CalendarEventPane.js +48 -0
- package/dist/src/components/calendar/CalendarShell.d.ts +43 -0
- package/dist/src/components/calendar/CalendarShell.js +35 -0
- package/dist/src/components/calendar/CalendarUnavailable.d.ts +13 -0
- package/dist/src/components/calendar/CalendarUnavailable.js +24 -0
- package/dist/src/components/calendar/CalendarViewPlaceholder.d.ts +1 -0
- package/dist/src/components/calendar/CalendarViewPlaceholder.js +5 -0
- package/dist/src/components/calendar/CalendarWaiting.d.ts +25 -0
- package/dist/src/components/calendar/CalendarWaiting.js +14 -0
- package/dist/src/components/calendar/CalendarWorkspace.d.ts +49 -0
- package/dist/src/components/calendar/CalendarWorkspace.js +65 -0
- package/dist/src/components/calendar/ChangeCalendarSuggestion.d.ts +5 -0
- package/dist/src/components/calendar/ChangeCalendarSuggestion.js +66 -0
- package/dist/src/components/calendar/OpenCalendarEvent.d.ts +20 -0
- package/dist/src/components/calendar/OpenCalendarEvent.js +169 -0
- package/dist/src/components/calendar/PendingSuggestions.d.ts +9 -0
- package/dist/src/components/calendar/PendingSuggestions.js +50 -0
- package/dist/src/components/calendar/WriteCalendarEvent.d.ts +13 -0
- package/dist/src/components/calendar/WriteCalendarEvent.js +59 -0
- package/dist/src/components/calendar/calendar-story-fixtures.d.ts +21 -0
- package/dist/src/components/calendar/calendar-story-fixtures.js +95 -0
- package/dist/src/components/calendar/calendar-story-server.d.ts +37 -0
- package/dist/src/components/calendar/calendar-story-server.js +108 -0
- package/dist/src/components/compose/AddressField.d.ts +13 -0
- package/dist/src/components/compose/AddressField.js +23 -0
- package/dist/src/components/compose/ComposeForm.d.ts +31 -0
- package/dist/src/components/compose/ComposeForm.js +925 -0
- package/dist/src/components/compose/ComposeProvider.d.ts +38 -0
- package/dist/src/components/compose/ComposeProvider.js +101 -0
- package/dist/src/components/compose/ComposeSmtpMissingBanner.d.ts +8 -0
- package/dist/src/components/compose/ComposeSmtpMissingBanner.js +10 -0
- package/dist/src/components/compose/ConversationCompose.d.ts +17 -0
- package/dist/src/components/compose/ConversationCompose.js +46 -0
- package/dist/src/components/compose/FromSelector.d.ts +7 -0
- package/dist/src/components/compose/FromSelector.js +29 -0
- package/dist/src/components/compose/FullCompose.d.ts +6 -0
- package/dist/src/components/compose/FullCompose.js +38 -0
- package/dist/src/components/compose/MobileComposeSheet.d.ts +1 -0
- package/dist/src/components/compose/MobileComposeSheet.js +65 -0
- package/dist/src/components/compose/compose-spellcheck.d.ts +17 -0
- package/dist/src/components/compose/compose-spellcheck.js +43 -0
- package/dist/src/components/compose/compose-title.d.ts +9 -0
- package/dist/src/components/compose/compose-title.js +9 -0
- package/dist/src/components/compose/mail-sync-off-refusal.d.ts +1 -0
- package/dist/src/components/compose/mail-sync-off-refusal.js +7 -0
- package/dist/src/components/compose/quoted-message.d.ts +59 -0
- package/dist/src/components/compose/quoted-message.js +162 -0
- package/dist/src/components/compose/reply-with-times.d.ts +6 -0
- package/dist/src/components/compose/reply-with-times.js +12 -0
- package/dist/src/components/config-import/ConfigImportWizard.d.ts +24 -0
- package/dist/src/components/config-import/ConfigImportWizard.js +425 -0
- package/dist/src/components/config-import/config-import.fixtures.d.ts +27 -0
- package/dist/src/components/config-import/config-import.fixtures.js +167 -0
- package/dist/src/components/config-import/steps.d.ts +100 -0
- package/dist/src/components/config-import/steps.js +143 -0
- package/dist/src/components/layout/AppShellSkeleton.d.ts +9 -0
- package/dist/src/components/layout/AppShellSkeleton.js +12 -0
- package/dist/src/components/layout/ComposeFab.d.ts +12 -0
- package/dist/src/components/layout/ComposeFab.js +21 -0
- package/dist/src/components/layout/Drawer.d.ts +28 -0
- package/dist/src/components/layout/Drawer.js +37 -0
- package/dist/src/components/layout/MailShell.d.ts +51 -0
- package/dist/src/components/layout/MailShell.js +39 -0
- package/dist/src/components/layout/MailTopBar.d.ts +14 -0
- package/dist/src/components/layout/MailTopBar.js +44 -0
- package/dist/src/components/mail/AuthenticityBanner.d.ts +14 -0
- package/dist/src/components/mail/AuthenticityBanner.js +18 -0
- package/dist/src/components/mail/AutoMovedIndicator.d.ts +20 -0
- package/dist/src/components/mail/AutoMovedIndicator.js +25 -0
- package/dist/src/components/mail/BlockedImagesNotice.d.ts +17 -0
- package/dist/src/components/mail/BlockedImagesNotice.js +8 -0
- package/dist/src/components/mail/BriefPane.d.ts +33 -0
- package/dist/src/components/mail/BriefPane.js +255 -0
- package/dist/src/components/mail/BulkRunProvider.d.ts +90 -0
- package/dist/src/components/mail/BulkRunProvider.js +203 -0
- package/dist/src/components/mail/ConversationView.d.ts +52 -0
- package/dist/src/components/mail/ConversationView.js +279 -0
- package/dist/src/components/mail/DailyBrief.d.ts +46 -0
- package/dist/src/components/mail/DailyBrief.js +584 -0
- package/dist/src/components/mail/DeleteConfirmDialog.d.ts +25 -0
- package/dist/src/components/mail/DeleteConfirmDialog.js +70 -0
- package/dist/src/components/mail/DraftsView.d.ts +15 -0
- package/dist/src/components/mail/DraftsView.js +84 -0
- package/dist/src/components/mail/EmptyTrashBar.d.ts +47 -0
- package/dist/src/components/mail/EmptyTrashBar.js +73 -0
- package/dist/src/components/mail/FlaggedList.d.ts +20 -0
- package/dist/src/components/mail/FlaggedList.js +173 -0
- package/dist/src/components/mail/FlaggedPane.d.ts +29 -0
- package/dist/src/components/mail/FlaggedPane.js +225 -0
- package/dist/src/components/mail/IntelligenceDrawer.d.ts +19 -0
- package/dist/src/components/mail/IntelligenceDrawer.js +16 -0
- package/dist/src/components/mail/IntelligencePane.d.ts +59 -0
- package/dist/src/components/mail/IntelligencePane.js +130 -0
- package/dist/src/components/mail/LabelApplyTrigger.d.ts +15 -0
- package/dist/src/components/mail/LabelApplyTrigger.js +29 -0
- package/dist/src/components/mail/MailListHeader.d.ts +102 -0
- package/dist/src/components/mail/MailListHeader.js +303 -0
- package/dist/src/components/mail/MailNav.d.ts +17 -0
- package/dist/src/components/mail/MailNav.js +20 -0
- package/dist/src/components/mail/MailSidebarAdapter.d.ts +23 -0
- package/dist/src/components/mail/MailSidebarAdapter.js +161 -0
- package/dist/src/components/mail/MailViewChrome.d.ts +54 -0
- package/dist/src/components/mail/MailViewChrome.js +43 -0
- package/dist/src/components/mail/MailboxPane.d.ts +36 -0
- package/dist/src/components/mail/MailboxPane.js +705 -0
- package/dist/src/components/mail/MessageActionMenu.d.ts +36 -0
- package/dist/src/components/mail/MessageActionMenu.js +129 -0
- package/dist/src/components/mail/MessageAttachments.d.ts +21 -0
- package/dist/src/components/mail/MessageAttachments.js +96 -0
- package/dist/src/components/mail/MessageBody.d.ts +72 -0
- package/dist/src/components/mail/MessageBody.js +68 -0
- package/dist/src/components/mail/MessageBodyErrorBanner.d.ts +20 -0
- package/dist/src/components/mail/MessageBodyErrorBanner.js +29 -0
- package/dist/src/components/mail/MessageCard.d.ts +29 -0
- package/dist/src/components/mail/MessageCard.js +77 -0
- package/dist/src/components/mail/MessageList.d.ts +130 -0
- package/dist/src/components/mail/MessageList.js +896 -0
- package/dist/src/components/mail/MessageListItem.d.ts +32 -0
- package/dist/src/components/mail/MessageListItem.js +41 -0
- package/dist/src/components/mail/MessageRow.d.ts +57 -0
- package/dist/src/components/mail/MessageRow.js +137 -0
- package/dist/src/components/mail/MessageSettlementAlert.d.ts +27 -0
- package/dist/src/components/mail/MessageSettlementAlert.js +79 -0
- package/dist/src/components/mail/MessageToolbar.d.ts +58 -0
- package/dist/src/components/mail/MessageToolbar.js +80 -0
- package/dist/src/components/mail/MobileMessageBar.d.ts +25 -0
- package/dist/src/components/mail/MobileMessageBar.js +61 -0
- package/dist/src/components/mail/MoveToTrigger.d.ts +30 -0
- package/dist/src/components/mail/MoveToTrigger.js +114 -0
- package/dist/src/components/mail/NavMenuButton.d.ts +1 -0
- package/dist/src/components/mail/NavMenuButton.js +17 -0
- package/dist/src/components/mail/OutboxPane.d.ts +27 -0
- package/dist/src/components/mail/OutboxPane.js +247 -0
- package/dist/src/components/mail/PullToRefresh.d.ts +12 -0
- package/dist/src/components/mail/PullToRefresh.js +12 -0
- package/dist/src/components/mail/RawMessageView.d.ts +18 -0
- package/dist/src/components/mail/RawMessageView.js +30 -0
- package/dist/src/components/mail/RoleAppointmentPromptProvider.d.ts +39 -0
- package/dist/src/components/mail/RoleAppointmentPromptProvider.js +137 -0
- package/dist/src/components/mail/SelectionWizardHost.d.ts +110 -0
- package/dist/src/components/mail/SelectionWizardHost.js +721 -0
- package/dist/src/components/mail/SpamRescue.d.ts +17 -0
- package/dist/src/components/mail/SpamRescue.js +64 -0
- package/dist/src/components/mail/SwipeableMessageRow.d.ts +31 -0
- package/dist/src/components/mail/SwipeableMessageRow.js +69 -0
- package/dist/src/components/mail/ThreadListInteraction.d.ts +106 -0
- package/dist/src/components/mail/ThreadListInteraction.js +319 -0
- package/dist/src/components/mail/bulk-run-state.d.ts +37 -0
- package/dist/src/components/mail/bulk-run-state.js +64 -0
- package/dist/src/components/mail/intelligence-story-calendar.d.ts +7 -0
- package/dist/src/components/mail/intelligence-story-calendar.js +17 -0
- package/dist/src/components/mail/message-body-error-banner-content.d.ts +31 -0
- package/dist/src/components/mail/message-body-error-banner-content.js +70 -0
- package/dist/src/components/mail/organize-run-state.d.ts +26 -0
- package/dist/src/components/mail/organize-run-state.js +24 -0
- package/dist/src/components/mail/selection-wizard-run-controls.d.ts +66 -0
- package/dist/src/components/mail/selection-wizard-run-controls.js +65 -0
- package/dist/src/components/mail/useModifierSelect.d.ts +35 -0
- package/dist/src/components/mail/useModifierSelect.js +75 -0
- package/dist/src/components/onboarding/OnboardingWizard.d.ts +83 -0
- package/dist/src/components/onboarding/OnboardingWizard.js +661 -0
- package/dist/src/components/onboarding/credential-steps.d.ts +58 -0
- package/dist/src/components/onboarding/credential-steps.js +198 -0
- package/dist/src/components/self-update/SelfUpdateOverlay.d.ts +1 -0
- package/dist/src/components/self-update/SelfUpdateOverlay.js +25 -0
- package/dist/src/components/settings/AccountFormPanel.d.ts +29 -0
- package/dist/src/components/settings/AccountFormPanel.js +337 -0
- package/dist/src/components/settings/AccountServices.d.ts +6 -0
- package/dist/src/components/settings/AccountServices.js +100 -0
- package/dist/src/components/settings/AccountServicesCard.d.ts +16 -0
- package/dist/src/components/settings/AccountServicesCard.js +13 -0
- package/dist/src/components/settings/AdvancedNavIcon.d.ts +1 -0
- package/dist/src/components/settings/AdvancedNavIcon.js +17 -0
- package/dist/src/components/settings/CalendarCreateCard.d.ts +12 -0
- package/dist/src/components/settings/CalendarCreateCard.js +42 -0
- package/dist/src/components/settings/CalendarDetailsForm.d.ts +15 -0
- package/dist/src/components/settings/CalendarDetailsForm.js +34 -0
- package/dist/src/components/settings/CalendarFeedCard.d.ts +18 -0
- package/dist/src/components/settings/CalendarFeedCard.js +58 -0
- package/dist/src/components/settings/CalendarFeedPanel.d.ts +13 -0
- package/dist/src/components/settings/CalendarFeedPanel.js +7 -0
- package/dist/src/components/settings/CalendarSettingsPanel.d.ts +13 -0
- package/dist/src/components/settings/CalendarSettingsPanel.js +21 -0
- package/dist/src/components/settings/CalendarSubscribeCard.d.ts +11 -0
- package/dist/src/components/settings/CalendarSubscribeCard.js +30 -0
- package/dist/src/components/settings/CalendarSubscriptionStatus.d.ts +12 -0
- package/dist/src/components/settings/CalendarSubscriptionStatus.js +20 -0
- package/dist/src/components/settings/ConfigExportCard.d.ts +18 -0
- package/dist/src/components/settings/ConfigExportCard.js +16 -0
- package/dist/src/components/settings/ConfigTransferPanel.d.ts +15 -0
- package/dist/src/components/settings/ConfigTransferPanel.js +55 -0
- package/dist/src/components/settings/DangerZone.d.ts +1 -0
- package/dist/src/components/settings/DangerZone.js +8 -0
- package/dist/src/components/settings/DeleteAccountDialog.d.ts +13 -0
- package/dist/src/components/settings/DeleteAccountDialog.js +62 -0
- package/dist/src/components/settings/DeleteFolderDialog.d.ts +21 -0
- package/dist/src/components/settings/DeleteFolderDialog.js +116 -0
- package/dist/src/components/settings/FilterActionError.d.ts +8 -0
- package/dist/src/components/settings/FilterActionError.js +10 -0
- package/dist/src/components/settings/FilterEditor.d.ts +22 -0
- package/dist/src/components/settings/FilterEditor.js +143 -0
- package/dist/src/components/settings/FilterEditorSurface.d.ts +18 -0
- package/dist/src/components/settings/FilterEditorSurface.js +18 -0
- package/dist/src/components/settings/FiltersList.d.ts +31 -0
- package/dist/src/components/settings/FiltersList.js +58 -0
- package/dist/src/components/settings/LabelsList.d.ts +15 -0
- package/dist/src/components/settings/LabelsList.js +37 -0
- package/dist/src/components/settings/SelfUpdatePanel.d.ts +1 -0
- package/dist/src/components/settings/SelfUpdatePanel.js +19 -0
- package/dist/src/components/settings/TimeZoneSelect.d.ts +12 -0
- package/dist/src/components/settings/TimeZoneSelect.js +10 -0
- package/dist/src/components/settings/TlsRootCaDownload.d.ts +1 -0
- package/dist/src/components/settings/TlsRootCaDownload.js +15 -0
- package/dist/src/components/settings/WarningsNavIcon.d.ts +1 -0
- package/dist/src/components/settings/WarningsNavIcon.js +8 -0
- package/dist/src/components/settings/WarningsPanel.d.ts +21 -0
- package/dist/src/components/settings/WarningsPanel.js +93 -0
- package/dist/src/components/settings/account-form-helpers.d.ts +53 -0
- package/dist/src/components/settings/account-form-helpers.js +78 -0
- package/dist/src/components/ui/AppVersion.d.ts +12 -0
- package/dist/src/components/ui/AppVersion.js +19 -0
- package/dist/src/components/ui/BugReportButton.d.ts +6 -0
- package/dist/src/components/ui/BugReportButton.js +11 -0
- package/dist/src/components/ui/ErrorBannerProvider.d.ts +27 -0
- package/dist/src/components/ui/ErrorBannerProvider.js +82 -0
- package/dist/src/components/ui/FatalErrorOverlay.d.ts +31 -0
- package/dist/src/components/ui/FatalErrorOverlay.js +71 -0
- package/dist/src/components/ui/error-banners.d.ts +43 -0
- package/dist/src/components/ui/error-banners.js +69 -0
- package/dist/src/components/ui/folder-role-refusal.d.ts +29 -0
- package/dist/src/components/ui/folder-role-refusal.js +44 -0
- package/dist/src/components/ui/placement-refusal.d.ts +31 -0
- package/dist/src/components/ui/placement-refusal.js +39 -0
- package/dist/src/hooks/calendar/agenda-window.d.ts +110 -0
- package/dist/src/hooks/calendar/agenda-window.js +159 -0
- package/dist/src/hooks/calendar/draft.d.ts +59 -0
- package/dist/src/hooks/calendar/draft.js +142 -0
- package/dist/src/hooks/calendar/index.d.ts +24 -0
- package/dist/src/hooks/calendar/index.js +24 -0
- package/dist/src/hooks/calendar/instance.d.ts +61 -0
- package/dist/src/hooks/calendar/instance.js +145 -0
- package/dist/src/hooks/calendar/recurrence-rule.d.ts +29 -0
- package/dist/src/hooks/calendar/recurrence-rule.js +159 -0
- package/dist/src/hooks/calendar/resource.d.ts +14 -0
- package/dist/src/hooks/calendar/resource.js +87 -0
- package/dist/src/hooks/calendar/selection.d.ts +38 -0
- package/dist/src/hooks/calendar/selection.js +54 -0
- package/dist/src/hooks/calendar/suggestion-draft.d.ts +11 -0
- package/dist/src/hooks/calendar/suggestion-draft.js +45 -0
- package/dist/src/hooks/calendar/useCalendarCollectionWrites.d.ts +26 -0
- package/dist/src/hooks/calendar/useCalendarCollectionWrites.js +75 -0
- package/dist/src/hooks/calendar/useCalendarEvent.d.ts +8 -0
- package/dist/src/hooks/calendar/useCalendarEvent.js +32 -0
- package/dist/src/hooks/calendar/useCalendarEvents.d.ts +58 -0
- package/dist/src/hooks/calendar/useCalendarEvents.js +128 -0
- package/dist/src/hooks/calendar/useCalendarFeed.d.ts +29 -0
- package/dist/src/hooks/calendar/useCalendarFeed.js +115 -0
- package/dist/src/hooks/calendar/useCalendarFreeBusy.d.ts +15 -0
- package/dist/src/hooks/calendar/useCalendarFreeBusy.js +61 -0
- package/dist/src/hooks/calendar/useCalendarJump.d.ts +24 -0
- package/dist/src/hooks/calendar/useCalendarJump.js +95 -0
- package/dist/src/hooks/calendar/useCalendarSubscriptions.d.ts +17 -0
- package/dist/src/hooks/calendar/useCalendarSubscriptions.js +66 -0
- package/dist/src/hooks/calendar/useCalendarSuggestions.d.ts +45 -0
- package/dist/src/hooks/calendar/useCalendarSuggestions.js +171 -0
- package/dist/src/hooks/calendar/useCalendarWrites.d.ts +44 -0
- package/dist/src/hooks/calendar/useCalendarWrites.js +109 -0
- package/dist/src/hooks/calendar/useCalendars.d.ts +20 -0
- package/dist/src/hooks/calendar/useCalendars.js +30 -0
- package/dist/src/hooks/calendar/useDraftClashes.d.ts +15 -0
- package/dist/src/hooks/calendar/useDraftClashes.js +68 -0
- package/dist/src/hooks/calendar/window.d.ts +57 -0
- package/dist/src/hooks/calendar/window.js +135 -0
- package/dist/src/hooks/queries/keys.d.ts +5 -0
- package/dist/src/hooks/queries/keys.js +5 -0
- package/dist/src/hooks/use-system-update.d.ts +40 -0
- package/dist/src/hooks/use-system-update.js +237 -0
- package/dist/src/hooks/useApplyLabel.d.ts +17 -0
- package/dist/src/hooks/useApplyLabel.js +41 -0
- package/dist/src/hooks/useArchiveMailbox.d.ts +74 -0
- package/dist/src/hooks/useArchiveMailbox.js +120 -0
- package/dist/src/hooks/useAutoMovedBadge.d.ts +56 -0
- package/dist/src/hooks/useAutoMovedBadge.js +86 -0
- package/dist/src/hooks/useBriefSections.d.ts +70 -0
- package/dist/src/hooks/useBriefSections.js +210 -0
- package/dist/src/hooks/useCalendarData.d.ts +37 -0
- package/dist/src/hooks/useCalendarData.js +23 -0
- package/dist/src/hooks/useClauseSuggestions.d.ts +14 -0
- package/dist/src/hooks/useClauseSuggestions.js +39 -0
- package/dist/src/hooks/useComposeAttachments.d.ts +20 -0
- package/dist/src/hooks/useComposeAttachments.js +72 -0
- package/dist/src/hooks/useComposeLanguages.d.ts +11 -0
- package/dist/src/hooks/useComposeLanguages.js +44 -0
- package/dist/src/hooks/useCreateMailbox.d.ts +40 -0
- package/dist/src/hooks/useCreateMailbox.js +123 -0
- package/dist/src/hooks/useCurrentMailboxName.d.ts +39 -0
- package/dist/src/hooks/useCurrentMailboxName.js +109 -0
- package/dist/src/hooks/useDebouncedValue.d.ts +1 -0
- package/dist/src/hooks/useDebouncedValue.js +9 -0
- package/dist/src/hooks/useDeleteFolder.d.ts +36 -0
- package/dist/src/hooks/useDeleteFolder.js +280 -0
- package/dist/src/hooks/useDeleteMessages.d.ts +41 -0
- package/dist/src/hooks/useDeleteMessages.js +171 -0
- package/dist/src/hooks/useDeleteOutcome.d.ts +14 -0
- package/dist/src/hooks/useDeleteOutcome.js +46 -0
- package/dist/src/hooks/useEmptyTrash.d.ts +16 -0
- package/dist/src/hooks/useEmptyTrash.js +130 -0
- package/dist/src/hooks/useEscalatedActions.d.ts +83 -0
- package/dist/src/hooks/useEscalatedActions.js +175 -0
- package/dist/src/hooks/useFilters.d.ts +57 -0
- package/dist/src/hooks/useFilters.js +147 -0
- package/dist/src/hooks/useFolderLabelTranslator.d.ts +6 -0
- package/dist/src/hooks/useFolderLabelTranslator.js +11 -0
- package/dist/src/hooks/useFollowFocusOpen.d.ts +28 -0
- package/dist/src/hooks/useFollowFocusOpen.js +52 -0
- package/dist/src/hooks/useInitialSyncProgress.d.ts +41 -0
- package/dist/src/hooks/useInitialSyncProgress.js +111 -0
- package/dist/src/hooks/useInlineImages.d.ts +16 -0
- package/dist/src/hooks/useInlineImages.js +52 -0
- package/dist/src/hooks/useIntelligenceCalendar.d.ts +20 -0
- package/dist/src/hooks/useIntelligenceCalendar.js +230 -0
- package/dist/src/hooks/useIntelligenceData.d.ts +58 -0
- package/dist/src/hooks/useIntelligenceData.js +242 -0
- package/dist/src/hooks/useIntelligenceDrawer.d.ts +21 -0
- package/dist/src/hooks/useIntelligenceDrawer.js +22 -0
- package/dist/src/hooks/useIntelligenceSurface.d.ts +44 -0
- package/dist/src/hooks/useIntelligenceSurface.js +57 -0
- package/dist/src/hooks/useIsDark.d.ts +8 -0
- package/dist/src/hooks/useIsDark.js +21 -0
- package/dist/src/hooks/useKeyboardNavigation.d.ts +57 -0
- package/dist/src/hooks/useKeyboardNavigation.js +61 -0
- package/dist/src/hooks/useLabels.d.ts +40 -0
- package/dist/src/hooks/useLabels.js +98 -0
- package/dist/src/hooks/useLayoutTier.d.ts +33 -0
- package/dist/src/hooks/useLayoutTier.js +33 -0
- package/dist/src/hooks/useMailboxAccount.d.ts +18 -0
- package/dist/src/hooks/useMailboxAccount.js +48 -0
- package/dist/src/hooks/useMailboxNameIndex.d.ts +2 -0
- package/dist/src/hooks/useMailboxNameIndex.js +21 -0
- package/dist/src/hooks/useMarkAsRead.d.ts +59 -0
- package/dist/src/hooks/useMarkAsRead.js +206 -0
- package/dist/src/hooks/useMatchSample.d.ts +30 -0
- package/dist/src/hooks/useMatchSample.js +74 -0
- package/dist/src/hooks/useMediaQuery.d.ts +11 -0
- package/dist/src/hooks/useMediaQuery.js +12 -0
- package/dist/src/hooks/useMessageBodyContent.d.ts +148 -0
- package/dist/src/hooks/useMessageBodyContent.js +272 -0
- package/dist/src/hooks/useMoveMessages.d.ts +27 -0
- package/dist/src/hooks/useMoveMessages.js +128 -0
- package/dist/src/hooks/useOrganizeJob.d.ts +39 -0
- package/dist/src/hooks/useOrganizeJob.js +95 -0
- package/dist/src/hooks/useRailPanels.d.ts +17 -0
- package/dist/src/hooks/useRailPanels.js +94 -0
- package/dist/src/hooks/useRedirectEnded.d.ts +41 -0
- package/dist/src/hooks/useRedirectEnded.js +106 -0
- package/dist/src/hooks/useRefreshControl.d.ts +97 -0
- package/dist/src/hooks/useRefreshControl.js +234 -0
- package/dist/src/hooks/useReportSpam.d.ts +102 -0
- package/dist/src/hooks/useReportSpam.js +173 -0
- package/dist/src/hooks/useRescueCandidates.d.ts +15 -0
- package/dist/src/hooks/useRescueCandidates.js +41 -0
- package/dist/src/hooks/useResultCount.d.ts +26 -0
- package/dist/src/hooks/useResultCount.js +40 -0
- package/dist/src/hooks/useResultFolderIndex.d.ts +8 -0
- package/dist/src/hooks/useResultFolderIndex.js +45 -0
- package/dist/src/hooks/useReturnFromRedirect.d.ts +19 -0
- package/dist/src/hooks/useReturnFromRedirect.js +38 -0
- package/dist/src/hooks/useRulePreview.d.ts +28 -0
- package/dist/src/hooks/useRulePreview.js +77 -0
- package/dist/src/hooks/useSaveDraft.d.ts +31 -0
- package/dist/src/hooks/useSaveDraft.js +183 -0
- package/dist/src/hooks/useSearchScope.d.ts +15 -0
- package/dist/src/hooks/useSearchScope.js +30 -0
- package/dist/src/hooks/useSearchSuggestions.d.ts +12 -0
- package/dist/src/hooks/useSearchSuggestions.js +77 -0
- package/dist/src/hooks/useSearchTokenContext.d.ts +16 -0
- package/dist/src/hooks/useSearchTokenContext.js +26 -0
- package/dist/src/hooks/useSelectedSubjects.d.ts +6 -0
- package/dist/src/hooks/useSelectedSubjects.js +62 -0
- package/dist/src/hooks/useSignature.d.ts +9 -0
- package/dist/src/hooks/useSignature.js +47 -0
- package/dist/src/hooks/useSpamMatchCounts.d.ts +15 -0
- package/dist/src/hooks/useSpamMatchCounts.js +74 -0
- package/dist/src/hooks/useStaleAccountSync.d.ts +101 -0
- package/dist/src/hooks/useStaleAccountSync.js +252 -0
- package/dist/src/hooks/useStarredThreads.d.ts +42 -0
- package/dist/src/hooks/useStarredThreads.js +100 -0
- package/dist/src/hooks/useThreadActions.d.ts +41 -0
- package/dist/src/hooks/useThreadActions.js +64 -0
- package/dist/src/hooks/useThreadMessageIds.d.ts +10 -0
- package/dist/src/hooks/useThreadMessageIds.js +22 -0
- package/dist/src/hooks/useThreadRow.d.ts +23 -0
- package/dist/src/hooks/useThreadRow.js +40 -0
- package/dist/src/hooks/useToggleStar.d.ts +31 -0
- package/dist/src/hooks/useToggleStar.js +96 -0
- package/dist/src/hooks/useToggleTrusted.d.ts +23 -0
- package/dist/src/hooks/useToggleTrusted.js +100 -0
- package/dist/src/hooks/useTriageLayer.d.ts +80 -0
- package/dist/src/hooks/useTriageLayer.js +99 -0
- package/dist/src/hooks/useTriggerSync.d.ts +30 -0
- package/dist/src/hooks/useTriggerSync.js +42 -0
- package/dist/src/hooks/useUpdateAddressFlags.d.ts +18 -0
- package/dist/src/hooks/useUpdateAddressFlags.js +93 -0
- package/dist/src/hooks/useUpdateFilter.d.ts +16 -0
- package/dist/src/hooks/useUpdateFilter.js +45 -0
- package/dist/src/hooks/useVisualViewport.d.ts +13 -0
- package/dist/src/hooks/useVisualViewport.js +37 -0
- package/dist/src/hooks/useWarningsAttention.d.ts +9 -0
- package/dist/src/hooks/useWarningsAttention.js +31 -0
- package/dist/src/index.css +27 -0
- package/dist/src/lib/account-order.d.ts +3 -0
- package/dist/src/lib/account-order.js +6 -0
- package/dist/src/lib/adjacent-message.d.ts +9 -0
- package/dist/src/lib/adjacent-message.js +19 -0
- package/dist/src/lib/api.d.ts +35 -0
- package/dist/src/lib/api.js +73 -0
- package/dist/src/lib/app-info.d.ts +24 -0
- package/dist/src/lib/app-info.js +26 -0
- package/dist/src/lib/attachment-download.d.ts +63 -0
- package/dist/src/lib/attachment-download.js +130 -0
- package/dist/src/lib/auto-moved.d.ts +46 -0
- package/dist/src/lib/auto-moved.js +82 -0
- package/dist/src/lib/autodiscovery.d.ts +42 -0
- package/dist/src/lib/autodiscovery.js +320 -0
- package/dist/src/lib/brief-criteria.d.ts +69 -0
- package/dist/src/lib/brief-criteria.js +62 -0
- package/dist/src/lib/brief.d.ts +98 -0
- package/dist/src/lib/brief.js +164 -0
- package/dist/src/lib/bug-report.d.ts +67 -0
- package/dist/src/lib/bug-report.js +212 -0
- package/dist/src/lib/bulk-action-copy.d.ts +67 -0
- package/dist/src/lib/bulk-action-copy.js +106 -0
- package/dist/src/lib/bulk-actions.d.ts +228 -0
- package/dist/src/lib/bulk-actions.js +242 -0
- package/dist/src/lib/calendar-collection-copy.d.ts +7 -0
- package/dist/src/lib/calendar-collection-copy.js +12 -0
- package/dist/src/lib/calendar-density.d.ts +26 -0
- package/dist/src/lib/calendar-density.js +31 -0
- package/dist/src/lib/calendar-feed-copy.d.ts +14 -0
- package/dist/src/lib/calendar-feed-copy.js +16 -0
- package/dist/src/lib/calendar-feed-url.d.ts +9 -0
- package/dist/src/lib/calendar-feed-url.js +11 -0
- package/dist/src/lib/calendar-format.d.ts +25 -0
- package/dist/src/lib/calendar-format.js +57 -0
- package/dist/src/lib/calendar-report.d.ts +4 -0
- package/dist/src/lib/calendar-report.js +15 -0
- package/dist/src/lib/calendar-route.d.ts +93 -0
- package/dist/src/lib/calendar-route.js +145 -0
- package/dist/src/lib/calendar-subscription.d.ts +6 -0
- package/dist/src/lib/calendar-subscription.js +8 -0
- package/dist/src/lib/calendar-suggestion.d.ts +56 -0
- package/dist/src/lib/calendar-suggestion.js +165 -0
- package/dist/src/lib/client.d.ts +2 -0
- package/dist/src/lib/client.js +30 -0
- package/dist/src/lib/compose-attachment-controller.d.ts +90 -0
- package/dist/src/lib/compose-attachment-controller.js +359 -0
- package/dist/src/lib/config-import.d.ts +136 -0
- package/dist/src/lib/config-import.js +371 -0
- package/dist/src/lib/console-errors.d.ts +16 -0
- package/dist/src/lib/console-errors.js +80 -0
- package/dist/src/lib/conversation-target.d.ts +16 -0
- package/dist/src/lib/conversation-target.js +1 -0
- package/dist/src/lib/dedupe-thread-messages.d.ts +14 -0
- package/dist/src/lib/dedupe-thread-messages.js +23 -0
- package/dist/src/lib/delete-folder.d.ts +66 -0
- package/dist/src/lib/delete-folder.js +110 -0
- package/dist/src/lib/display-category.d.ts +18 -0
- package/dist/src/lib/display-category.js +20 -0
- package/dist/src/lib/drafts.d.ts +50 -0
- package/dist/src/lib/drafts.js +91 -0
- package/dist/src/lib/error-classifier.d.ts +155 -0
- package/dist/src/lib/error-classifier.js +213 -0
- package/dist/src/lib/escalation-label.d.ts +18 -0
- package/dist/src/lib/escalation-label.js +20 -0
- package/dist/src/lib/fatal-error.d.ts +68 -0
- package/dist/src/lib/fatal-error.js +88 -0
- package/dist/src/lib/filter-report.d.ts +2 -0
- package/dist/src/lib/filter-report.js +13 -0
- package/dist/src/lib/flagged-criteria.d.ts +36 -0
- package/dist/src/lib/flagged-criteria.js +22 -0
- package/dist/src/lib/folder-failure.d.ts +2 -0
- package/dist/src/lib/folder-failure.js +8 -0
- package/dist/src/lib/folder-roles.d.ts +33 -0
- package/dist/src/lib/folder-roles.js +83 -0
- package/dist/src/lib/format.d.ts +156 -0
- package/dist/src/lib/format.js +269 -0
- package/dist/src/lib/fresh-mailbox-count.d.ts +76 -0
- package/dist/src/lib/fresh-mailbox-count.js +37 -0
- package/dist/src/lib/hot-sync-window.d.ts +28 -0
- package/dist/src/lib/hot-sync-window.js +41 -0
- package/dist/src/lib/i18n.d.ts +2 -0
- package/dist/src/lib/i18n.js +29 -0
- package/dist/src/lib/inbox-filters.d.ts +76 -0
- package/dist/src/lib/inbox-filters.js +95 -0
- package/dist/src/lib/intelligence-pref.d.ts +43 -0
- package/dist/src/lib/intelligence-pref.js +41 -0
- package/dist/src/lib/json.d.ts +8 -0
- package/dist/src/lib/json.js +10 -0
- package/dist/src/lib/junk-destination.d.ts +15 -0
- package/dist/src/lib/junk-destination.js +24 -0
- package/dist/src/lib/list-focus.d.ts +14 -0
- package/dist/src/lib/list-focus.js +21 -0
- package/dist/src/lib/list-header-chrome.d.ts +40 -0
- package/dist/src/lib/list-header-chrome.js +12 -0
- package/dist/src/lib/list-narrowing.d.ts +35 -0
- package/dist/src/lib/list-narrowing.js +133 -0
- package/dist/src/lib/list-verb-request.d.ts +43 -0
- package/dist/src/lib/list-verb-request.js +24 -0
- package/dist/src/lib/mail-context.d.ts +61 -0
- package/dist/src/lib/mail-context.js +24 -0
- package/dist/src/lib/mail-freshness.d.ts +57 -0
- package/dist/src/lib/mail-freshness.js +158 -0
- package/dist/src/lib/mail-route.d.ts +103 -0
- package/dist/src/lib/mail-route.js +115 -0
- package/dist/src/lib/mail-search.d.ts +141 -0
- package/dist/src/lib/mail-search.js +55 -0
- package/dist/src/lib/mailbox-sync-wait.d.ts +54 -0
- package/dist/src/lib/mailbox-sync-wait.js +44 -0
- package/dist/src/lib/message-attachments.d.ts +20 -0
- package/dist/src/lib/message-attachments.js +37 -0
- package/dist/src/lib/message-body-source.d.ts +30 -0
- package/dist/src/lib/message-body-source.js +30 -0
- package/dist/src/lib/move-options.d.ts +30 -0
- package/dist/src/lib/move-options.js +33 -0
- package/dist/src/lib/move-targets.d.ts +16 -0
- package/dist/src/lib/move-targets.js +61 -0
- package/dist/src/lib/network-error.d.ts +31 -0
- package/dist/src/lib/network-error.js +68 -0
- package/dist/src/lib/new-folder.d.ts +23 -0
- package/dist/src/lib/new-folder.js +41 -0
- package/dist/src/lib/onboarding-completion.d.ts +15 -0
- package/dist/src/lib/onboarding-completion.js +17 -0
- package/dist/src/lib/organize/clause-suggestions.d.ts +40 -0
- package/dist/src/lib/organize/clause-suggestions.js +61 -0
- package/dist/src/lib/organize/filter-edit-model.d.ts +47 -0
- package/dist/src/lib/organize/filter-edit-model.js +104 -0
- package/dist/src/lib/organize/filter-run.d.ts +27 -0
- package/dist/src/lib/organize/filter-run.js +27 -0
- package/dist/src/lib/organize/filter-status.d.ts +30 -0
- package/dist/src/lib/organize/filter-status.js +84 -0
- package/dist/src/lib/organize/label-delete-copy.d.ts +11 -0
- package/dist/src/lib/organize/label-delete-copy.js +17 -0
- package/dist/src/lib/organize/organize-model.d.ts +110 -0
- package/dist/src/lib/organize/organize-model.js +81 -0
- package/dist/src/lib/organize/organize-poll.d.ts +11 -0
- package/dist/src/lib/organize/organize-poll.js +21 -0
- package/dist/src/lib/organize/rule-model.d.ts +69 -0
- package/dist/src/lib/organize/rule-model.js +98 -0
- package/dist/src/lib/organize/search-to-rule.d.ts +19 -0
- package/dist/src/lib/organize/search-to-rule.js +65 -0
- package/dist/src/lib/outbox-search.d.ts +34 -0
- package/dist/src/lib/outbox-search.js +26 -0
- package/dist/src/lib/outbox-status.d.ts +47 -0
- package/dist/src/lib/outbox-status.js +45 -0
- package/dist/src/lib/provider-presets.d.ts +16 -0
- package/dist/src/lib/provider-presets.js +82 -0
- package/dist/src/lib/quarantine-entries.d.ts +15 -0
- package/dist/src/lib/quarantine-entries.js +40 -0
- package/dist/src/lib/query-error-handler.d.ts +21 -0
- package/dist/src/lib/query-error-handler.js +30 -0
- package/dist/src/lib/recent-searches.d.ts +2 -0
- package/dist/src/lib/recent-searches.js +37 -0
- package/dist/src/lib/recipient-suggestions.d.ts +2 -0
- package/dist/src/lib/recipient-suggestions.js +11 -0
- package/dist/src/lib/request-breadcrumbs.d.ts +59 -0
- package/dist/src/lib/request-breadcrumbs.js +114 -0
- package/dist/src/lib/rescue-candidates.d.ts +17 -0
- package/dist/src/lib/rescue-candidates.js +27 -0
- package/dist/src/lib/rescue-telemetry.d.ts +26 -0
- package/dist/src/lib/rescue-telemetry.js +32 -0
- package/dist/src/lib/result-count.d.ts +43 -0
- package/dist/src/lib/result-count.js +37 -0
- package/dist/src/lib/result-folder.d.ts +57 -0
- package/dist/src/lib/result-folder.js +67 -0
- package/dist/src/lib/route-breadcrumbs.d.ts +27 -0
- package/dist/src/lib/route-breadcrumbs.js +36 -0
- package/dist/src/lib/row-settlement.d.ts +11 -0
- package/dist/src/lib/row-settlement.js +20 -0
- package/dist/src/lib/rum-adapter.d.ts +4 -0
- package/dist/src/lib/rum-adapter.js +84 -0
- package/dist/src/lib/search-conversion.d.ts +17 -0
- package/dist/src/lib/search-conversion.js +17 -0
- package/dist/src/lib/search-params.d.ts +23 -0
- package/dist/src/lib/search-params.js +58 -0
- package/dist/src/lib/search-query.d.ts +1 -0
- package/dist/src/lib/search-query.js +10 -0
- package/dist/src/lib/search-result.d.ts +10 -0
- package/dist/src/lib/search-result.js +34 -0
- package/dist/src/lib/search-scope.d.ts +94 -0
- package/dist/src/lib/search-scope.js +86 -0
- package/dist/src/lib/search-suggestions.d.ts +98 -0
- package/dist/src/lib/search-suggestions.js +202 -0
- package/dist/src/lib/search-surface.d.ts +30 -0
- package/dist/src/lib/search-surface.js +23 -0
- package/dist/src/lib/search-token-index.d.ts +43 -0
- package/dist/src/lib/search-token-index.js +92 -0
- package/dist/src/lib/search-tokens.d.ts +136 -0
- package/dist/src/lib/search-tokens.js +206 -0
- package/dist/src/lib/search-view.d.ts +53 -0
- package/dist/src/lib/search-view.js +71 -0
- package/dist/src/lib/selection-account-scope.d.ts +18 -0
- package/dist/src/lib/selection-account-scope.js +26 -0
- package/dist/src/lib/selection-mode.d.ts +17 -0
- package/dist/src/lib/selection-mode.js +14 -0
- package/dist/src/lib/self-update-state.d.ts +156 -0
- package/dist/src/lib/self-update-state.js +384 -0
- package/dist/src/lib/sender-address.d.ts +24 -0
- package/dist/src/lib/sender-address.js +28 -0
- package/dist/src/lib/session-storage.d.ts +1 -0
- package/dist/src/lib/session-storage.js +8 -0
- package/dist/src/lib/spam-offer.d.ts +69 -0
- package/dist/src/lib/spam-offer.js +90 -0
- package/dist/src/lib/stale-build.d.ts +10 -0
- package/dist/src/lib/stale-build.js +24 -0
- package/dist/src/lib/starred-rows.d.ts +24 -0
- package/dist/src/lib/starred-rows.js +32 -0
- package/dist/src/lib/sync-warning-entries.d.ts +4 -0
- package/dist/src/lib/sync-warning-entries.js +22 -0
- package/dist/src/lib/telemetry-context.d.ts +3 -0
- package/dist/src/lib/telemetry-context.js +6 -0
- package/dist/src/lib/telemetry.d.ts +7 -0
- package/dist/src/lib/telemetry.js +6 -0
- package/dist/src/lib/theme-preference.d.ts +16 -0
- package/dist/src/lib/theme-preference.js +40 -0
- package/dist/src/lib/theme.d.ts +11 -0
- package/dist/src/lib/theme.js +31 -0
- package/dist/src/lib/thread-cache.d.ts +41 -0
- package/dist/src/lib/thread-cache.js +34 -0
- package/dist/src/lib/thread-list-cache.d.ts +51 -0
- package/dist/src/lib/thread-list-cache.js +51 -0
- package/dist/src/lib/thread-search-tokens.d.ts +61 -0
- package/dist/src/lib/thread-search-tokens.js +116 -0
- package/dist/src/lib/wizard-selection.d.ts +27 -0
- package/dist/src/lib/wizard-selection.js +17 -0
- package/dist/src/main.d.ts +1 -0
- package/dist/src/main.js +9 -0
- package/dist/src/routeTree.gen.d.ts +1596 -0
- package/dist/src/routeTree.gen.js +414 -0
- package/dist/src/router.d.ts +12 -0
- package/dist/src/router.js +40 -0
- package/dist/src/routes/__root.d.ts +2 -0
- package/dist/src/routes/__root.js +46 -0
- package/dist/src/routes/calendar/$view.$date/$calendarObjectId/$recurrenceId.d.ts +13 -0
- package/dist/src/routes/calendar/$view.$date/$calendarObjectId/$recurrenceId.js +18 -0
- package/dist/src/routes/calendar/$view.$date/$calendarObjectId/index.d.ts +13 -0
- package/dist/src/routes/calendar/$view.$date/$calendarObjectId/index.js +15 -0
- package/dist/src/routes/calendar/$view.$date/$calendarObjectId.d.ts +13 -0
- package/dist/src/routes/calendar/$view.$date/$calendarObjectId.js +12 -0
- package/dist/src/routes/calendar/$view.$date/index.d.ts +18 -0
- package/dist/src/routes/calendar/$view.$date/index.js +16 -0
- package/dist/src/routes/calendar/$view.$date/new.d.ts +13 -0
- package/dist/src/routes/calendar/$view.$date/new.js +19 -0
- package/dist/src/routes/calendar/$view.$date/suggestion.$suggestionId.d.ts +13 -0
- package/dist/src/routes/calendar/$view.$date/suggestion.$suggestionId.js +15 -0
- package/dist/src/routes/calendar/$view.$date.d.ts +13 -0
- package/dist/src/routes/calendar/$view.$date.js +69 -0
- package/dist/src/routes/calendar/index.d.ts +13 -0
- package/dist/src/routes/calendar/index.js +22 -0
- package/dist/src/routes/calendar.d.ts +14 -0
- package/dist/src/routes/calendar.js +68 -0
- package/dist/src/routes/import.d.ts +1 -0
- package/dist/src/routes/import.js +45 -0
- package/dist/src/routes/index.d.ts +1 -0
- package/dist/src/routes/index.js +6 -0
- package/dist/src/routes/mail/$mailboxId/$threadId/$messageId/$mode.{-$outboxMessageId}.d.ts +29 -0
- package/dist/src/routes/mail/$mailboxId/$threadId/$messageId/$mode.{-$outboxMessageId}.js +12 -0
- package/dist/src/routes/mail/$mailboxId/$threadId/$messageId.d.ts +19 -0
- package/dist/src/routes/mail/$mailboxId/$threadId/$messageId.js +22 -0
- package/dist/src/routes/mail/$mailboxId/$threadId/index.d.ts +19 -0
- package/dist/src/routes/mail/$mailboxId/$threadId/index.js +13 -0
- package/dist/src/routes/mail/$mailboxId/$threadId.d.ts +19 -0
- package/dist/src/routes/mail/$mailboxId/$threadId.js +11 -0
- package/dist/src/routes/mail/$mailboxId/compose.{-$outboxMessageId}.d.ts +19 -0
- package/dist/src/routes/mail/$mailboxId/compose.{-$outboxMessageId}.js +11 -0
- package/dist/src/routes/mail/$mailboxId/index.d.ts +19 -0
- package/dist/src/routes/mail/$mailboxId/index.js +9 -0
- package/dist/src/routes/mail/$mailboxId.d.ts +19 -0
- package/dist/src/routes/mail/$mailboxId.js +26 -0
- package/dist/src/routes/mail/brief/$threadId/$messageId/$mode.{-$outboxMessageId}.d.ts +29 -0
- package/dist/src/routes/mail/brief/$threadId/$messageId/$mode.{-$outboxMessageId}.js +24 -0
- package/dist/src/routes/mail/brief/$threadId/$messageId.d.ts +19 -0
- package/dist/src/routes/mail/brief/$threadId/$messageId.js +22 -0
- package/dist/src/routes/mail/brief/$threadId/index.d.ts +19 -0
- package/dist/src/routes/mail/brief/$threadId/index.js +13 -0
- package/dist/src/routes/mail/brief/$threadId.d.ts +19 -0
- package/dist/src/routes/mail/brief/$threadId.js +15 -0
- package/dist/src/routes/mail/brief/compose.{-$outboxMessageId}.d.ts +19 -0
- package/dist/src/routes/mail/brief/compose.{-$outboxMessageId}.js +19 -0
- package/dist/src/routes/mail/brief/index.d.ts +19 -0
- package/dist/src/routes/mail/brief/index.js +13 -0
- package/dist/src/routes/mail/brief.d.ts +19 -0
- package/dist/src/routes/mail/brief.js +27 -0
- package/dist/src/routes/mail/flagged/$threadId/$messageId/$mode.{-$outboxMessageId}.d.ts +29 -0
- package/dist/src/routes/mail/flagged/$threadId/$messageId/$mode.{-$outboxMessageId}.js +12 -0
- package/dist/src/routes/mail/flagged/$threadId/$messageId.d.ts +19 -0
- package/dist/src/routes/mail/flagged/$threadId/$messageId.js +22 -0
- package/dist/src/routes/mail/flagged/$threadId/index.d.ts +19 -0
- package/dist/src/routes/mail/flagged/$threadId/index.js +13 -0
- package/dist/src/routes/mail/flagged/$threadId.d.ts +19 -0
- package/dist/src/routes/mail/flagged/$threadId.js +15 -0
- package/dist/src/routes/mail/flagged/compose.{-$outboxMessageId}.d.ts +19 -0
- package/dist/src/routes/mail/flagged/compose.{-$outboxMessageId}.js +10 -0
- package/dist/src/routes/mail/flagged/index.d.ts +19 -0
- package/dist/src/routes/mail/flagged/index.js +9 -0
- package/dist/src/routes/mail/flagged.d.ts +19 -0
- package/dist/src/routes/mail/flagged.js +26 -0
- package/dist/src/routes/mail/index.d.ts +37 -0
- package/dist/src/routes/mail/index.js +13 -0
- package/dist/src/routes/mail/outbox/compose.{-$outboxMessageId}.d.ts +19 -0
- package/dist/src/routes/mail/outbox/compose.{-$outboxMessageId}.js +14 -0
- package/dist/src/routes/mail/outbox/draft/$outboxMessageId.d.ts +19 -0
- package/dist/src/routes/mail/outbox/draft/$outboxMessageId.js +18 -0
- package/dist/src/routes/mail/outbox/index.d.ts +19 -0
- package/dist/src/routes/mail/outbox/index.js +9 -0
- package/dist/src/routes/mail/outbox.d.ts +19 -0
- package/dist/src/routes/mail/outbox.js +22 -0
- package/dist/src/routes/mail.d.ts +16 -0
- package/dist/src/routes/mail.js +187 -0
- package/dist/src/routes/onboarding.d.ts +7 -0
- package/dist/src/routes/onboarding.js +35 -0
- package/dist/src/routes/settings/-shared/help-copy.d.ts +5 -0
- package/dist/src/routes/settings/-shared/help-copy.js +7 -0
- package/dist/src/routes/settings/accounts.d.ts +38 -0
- package/dist/src/routes/settings/accounts.js +396 -0
- package/dist/src/routes/settings/advanced.d.ts +1 -0
- package/dist/src/routes/settings/advanced.js +28 -0
- package/dist/src/routes/settings/appearance.d.ts +1 -0
- package/dist/src/routes/settings/appearance.js +61 -0
- package/dist/src/routes/settings/calendars.d.ts +1 -0
- package/dist/src/routes/settings/calendars.js +44 -0
- package/dist/src/routes/settings/filters.d.ts +5 -0
- package/dist/src/routes/settings/filters.js +88 -0
- package/dist/src/routes/settings/folders.d.ts +1 -0
- package/dist/src/routes/settings/folders.js +142 -0
- package/dist/src/routes/settings/index.d.ts +1 -0
- package/dist/src/routes/settings/index.js +5 -0
- package/dist/src/routes/settings/labels.d.ts +1 -0
- package/dist/src/routes/settings/labels.js +71 -0
- package/dist/src/routes/settings/senders.d.ts +6 -0
- package/dist/src/routes/settings/senders.js +202 -0
- package/dist/src/routes/settings/suggested-vips.d.ts +1 -0
- package/dist/src/routes/settings/suggested-vips.js +10 -0
- package/dist/src/routes/settings/warnings.d.ts +1 -0
- package/dist/src/routes/settings/warnings.js +20 -0
- package/dist/src/routes/settings.d.ts +14 -0
- package/dist/src/routes/settings.js +64 -0
- package/dist/src/routing/browsed-list.d.ts +28 -0
- package/dist/src/routing/browsed-list.js +61 -0
- package/dist/src/routing/calendar.d.ts +69 -0
- package/dist/src/routing/calendar.js +152 -0
- package/dist/src/routing/compose.d.ts +52 -0
- package/dist/src/routing/compose.js +139 -0
- package/dist/src/routing/fragment.d.ts +64 -0
- package/dist/src/routing/fragment.js +112 -0
- package/dist/src/routing/index.d.ts +14 -0
- package/dist/src/routing/index.js +14 -0
- package/dist/src/routing/nav-link.d.ts +28 -0
- package/dist/src/routing/nav-link.js +9 -0
- package/dist/src/routing/nav-selection.d.ts +13 -0
- package/dist/src/routing/nav-selection.js +29 -0
- package/dist/src/routing/open-thread.d.ts +65 -0
- package/dist/src/routing/open-thread.js +100 -0
- package/dist/src/routing/outbox-draft.d.ts +13 -0
- package/dist/src/routing/outbox-draft.js +37 -0
- package/dist/src/routing/reply.d.ts +102 -0
- package/dist/src/routing/reply.js +238 -0
- package/dist/src/routing/search-field.d.ts +45 -0
- package/dist/src/routing/search-field.js +67 -0
- package/dist/src/routing/search-mirror.d.ts +63 -0
- package/dist/src/routing/search-mirror.js +120 -0
- package/dist/src/routing/search-navigation.d.ts +16 -0
- package/dist/src/routing/search-navigation.js +32 -0
- package/dist/src/routing/sections.d.ts +16 -0
- package/dist/src/routing/sections.js +33 -0
- package/dist/src/routing/wizard-history.d.ts +83 -0
- package/dist/src/routing/wizard-history.js +153 -0
- package/dist/src/runtime-config.d.ts +59 -0
- package/dist/src/runtime-config.js +42 -0
- package/dist/src/shell/index.d.ts +17 -0
- package/dist/src/shell/index.js +61 -0
- package/package.json +145 -127
- package/harness/build.mjs +0 -121
- package/harness/index.html +0 -52
- package/harness/vite-preset.ts +0 -31
- package/index.html +0 -54
- package/spellcheck/empty-build.test.ts +0 -160
- package/spellcheck/languages.test.ts +0 -80
- package/spellcheck/languages.ts +0 -86
- package/spellcheck/vite-plugin-licence.test.ts +0 -140
- package/spellcheck/vite-plugin.test.ts +0 -230
- package/spellcheck/vite-plugin.ts +0 -385
- package/spellcheck/worker-stub.ts +0 -36
- package/src/auth/AccountMenu.tsx +0 -10
- package/src/auth/AccountSession.tsx +0 -19
- package/src/auth/BetterAuthShell.tsx +0 -233
- package/src/auth/SessionRateLimited.stories.tsx +0 -26
- package/src/auth/SessionRateLimited.tsx +0 -39
- package/src/auth/SignInAgain.tsx +0 -18
- package/src/auth/account-menu-mode.test.ts +0 -64
- package/src/auth/account-menu-mode.ts +0 -28
- package/src/auth/amplify-config.test.ts +0 -50
- package/src/auth/amplify-config.ts +0 -59
- package/src/auth/auth-error.test.ts +0 -129
- package/src/auth/auth-error.ts +0 -120
- package/src/auth/auth-interceptor.test.ts +0 -104
- package/src/auth/auth-interceptor.ts +0 -28
- package/src/auth/better-auth/BetterAuthAccount.tsx +0 -25
- package/src/auth/better-auth-config.ts +0 -253
- package/src/auth/better-auth-provider.tsx +0 -20
- package/src/auth/better-auth-token.test.ts +0 -349
- package/src/auth/cognito/CognitoAccount.tsx +0 -48
- package/src/auth/cognito/CognitoShell.tsx +0 -266
- package/src/auth/cognito/cognito-token.test.ts +0 -106
- package/src/auth/cognito/cognito-token.ts +0 -47
- package/src/auth/cognito-provider.tsx +0 -22
- package/src/auth/cognito-sign-in.stories.tsx +0 -90
- package/src/auth/combined-provider.tsx +0 -42
- package/src/auth/composition.test.ts +0 -59
- package/src/auth/email-sign-in.stories.tsx +0 -128
- package/src/auth/provider.tsx +0 -68
- package/src/auth/session-gate.render.test.ts +0 -77
- package/src/auth/session-state.test.ts +0 -66
- package/src/auth/session-state.ts +0 -41
- package/src/auth/sign-out-visibility.test.ts +0 -40
- package/src/auth/sign-out-visibility.ts +0 -10
- package/src/auth/sign-up-disabled.test.ts +0 -23
- package/src/components/calendar/AgendaStrip.stories.tsx +0 -291
- package/src/components/calendar/AgendaStrip.tsx +0 -162
- package/src/components/calendar/AgendaView.stories.tsx +0 -112
- package/src/components/calendar/AgendaView.tsx +0 -241
- package/src/components/calendar/CalendarComposePane.stories.tsx +0 -151
- package/src/components/calendar/CalendarComposePane.tsx +0 -127
- package/src/components/calendar/CalendarComposeSeed.tsx +0 -35
- package/src/components/calendar/CalendarEventPane.stories.tsx +0 -200
- package/src/components/calendar/CalendarEventPane.tsx +0 -167
- package/src/components/calendar/CalendarShell.stories.tsx +0 -177
- package/src/components/calendar/CalendarShell.tsx +0 -83
- package/src/components/calendar/CalendarUnavailable.tsx +0 -56
- package/src/components/calendar/CalendarViewPlaceholder.stories.tsx +0 -41
- package/src/components/calendar/CalendarViewPlaceholder.tsx +0 -17
- package/src/components/calendar/CalendarWaiting.tsx +0 -102
- package/src/components/calendar/CalendarWorkspace.stories.tsx +0 -374
- package/src/components/calendar/CalendarWorkspace.tsx +0 -258
- package/src/components/calendar/ChangeCalendarSuggestion.stories.tsx +0 -187
- package/src/components/calendar/ChangeCalendarSuggestion.tsx +0 -159
- package/src/components/calendar/OpenCalendarEvent.stories.tsx +0 -273
- package/src/components/calendar/OpenCalendarEvent.tsx +0 -353
- package/src/components/calendar/PendingSuggestions.tsx +0 -100
- package/src/components/calendar/WriteCalendarEvent.stories.tsx +0 -90
- package/src/components/calendar/WriteCalendarEvent.tsx +0 -104
- package/src/components/calendar/agenda-address.render.test.ts +0 -493
- package/src/components/calendar/agenda-strip.render.test.ts +0 -241
- package/src/components/calendar/calendar-app.stories.tsx +0 -122
- package/src/components/calendar/calendar-story-fixtures.ts +0 -118
- package/src/components/calendar/calendar-story-server.tsx +0 -157
- package/src/components/calendar/calendar-workspace.render.test.ts +0 -221
- package/src/components/calendar/calendar-write-flow.render.test.ts +0 -373
- package/src/components/calendar/change-suggestion-first.render.test.ts +0 -304
- package/src/components/calendar/pending-suggestions.render.test.ts +0 -206
- package/src/components/compose/AddressField.tsx +0 -64
- package/src/components/compose/ComposeForm.tsx +0 -1427
- package/src/components/compose/ComposeProvider.tsx +0 -174
- package/src/components/compose/ComposeSmtpMissingBanner.tsx +0 -25
- package/src/components/compose/ConversationCompose.tsx +0 -88
- package/src/components/compose/FromSelector.render.test.ts +0 -99
- package/src/components/compose/FromSelector.stories.tsx +0 -61
- package/src/components/compose/FromSelector.tsx +0 -74
- package/src/components/compose/FullCompose.tsx +0 -93
- package/src/components/compose/MobileComposeSheet.tsx +0 -134
- package/src/components/compose/attachment-only-source.render.test.ts +0 -234
- package/src/components/compose/compose-inline-image.render.test.ts +0 -542
- package/src/components/compose/compose-send-stops-autosave.render.test.ts +0 -328
- package/src/components/compose/compose-spellcheck-failure.render.test.ts +0 -114
- package/src/components/compose/compose-spellcheck.test.ts +0 -157
- package/src/components/compose/compose-spellcheck.ts +0 -56
- package/src/components/compose/compose-starts-a-second-message.render.test.ts +0 -171
- package/src/components/compose/compose-title.ts +0 -10
- package/src/components/compose/compose.stories.tsx +0 -405
- package/src/components/compose/draft-discard-failure.render.test.ts +0 -138
- package/src/components/compose/forward-autosave-is-not-fatal.render.test.ts +0 -358
- package/src/components/compose/mail-sync-off-refusal.ts +0 -7
- package/src/components/compose/mobile-header-stays-expanded.render.test.ts +0 -229
- package/src/components/compose/quote-leaves-with-the-send.render.test.ts +0 -235
- package/src/components/compose/quoted-message.test.ts +0 -158
- package/src/components/compose/quoted-message.ts +0 -216
- package/src/components/compose/reopened-draft-writes-nothing.render.test.ts +0 -148
- package/src/components/compose/reply-all-on-resumed-draft.render.test.ts +0 -250
- package/src/components/compose/reply-with-times.ts +0 -22
- package/src/components/compose/send-from-mail-off-account.render.test.ts +0 -173
- package/src/components/compose/send-poll-server-error.render.test.ts +0 -120
- package/src/components/compose/send-watch-outlives-sent.render.test.ts +0 -121
- package/src/components/config-import/ConfigImportWizard.flow.test.ts +0 -326
- package/src/components/config-import/ConfigImportWizard.tsx +0 -721
- package/src/components/config-import/config-import.fixtures.ts +0 -254
- package/src/components/config-import/config-import.stories.tsx +0 -486
- package/src/components/config-import/steps.import-failure.test.ts +0 -91
- package/src/components/config-import/steps.tsx +0 -784
- package/src/components/config-import/steps.viewport.test.ts +0 -216
- package/src/components/layout/AppShellSkeleton.tsx +0 -53
- package/src/components/layout/ComposeFab.tsx +0 -22
- package/src/components/layout/Drawer.focus.test.ts +0 -253
- package/src/components/layout/Drawer.tsx +0 -108
- package/src/components/layout/MailShell.tsx +0 -106
- package/src/components/layout/MailTopBar.tsx +0 -99
- package/src/components/layout/mail-shell.stories.tsx +0 -142
- package/src/components/mail/AuthenticityBanner.tsx +0 -45
- package/src/components/mail/AutoMovedIndicator.tsx +0 -53
- package/src/components/mail/BlockedImagesNotice.render.test.ts +0 -114
- package/src/components/mail/BlockedImagesNotice.tsx +0 -63
- package/src/components/mail/BriefPane.tsx +0 -477
- package/src/components/mail/BulkRunProvider.tsx +0 -344
- package/src/components/mail/ConversationView.tsx +0 -519
- package/src/components/mail/DailyBrief.scope.test.ts +0 -76
- package/src/components/mail/DailyBrief.tsx +0 -1094
- package/src/components/mail/DeleteConfirmDialog.render.test.ts +0 -412
- package/src/components/mail/DeleteConfirmDialog.tsx +0 -143
- package/src/components/mail/DraftsView.tsx +0 -255
- package/src/components/mail/EmptyTrashBar.render.test.ts +0 -133
- package/src/components/mail/EmptyTrashBar.tsx +0 -181
- package/src/components/mail/FlaggedList.tsx +0 -359
- package/src/components/mail/FlaggedPane.tsx +0 -473
- package/src/components/mail/IntelligenceDrawer.tsx +0 -52
- package/src/components/mail/IntelligencePane.render.test.ts +0 -116
- package/src/components/mail/IntelligencePane.test.ts +0 -16
- package/src/components/mail/IntelligencePane.tsx +0 -391
- package/src/components/mail/LabelApplyTrigger.tsx +0 -67
- package/src/components/mail/MailListHeader.chrome-stability.render.test.ts +0 -323
- package/src/components/mail/MailListHeader.tsx +0 -613
- package/src/components/mail/MailNav.tsx +0 -70
- package/src/components/mail/MailSidebarAdapter.tsx +0 -319
- package/src/components/mail/MailViewChrome.tsx +0 -124
- package/src/components/mail/MailboxPane.tsx +0 -1285
- package/src/components/mail/MessageActionMenu.tsx +0 -296
- package/src/components/mail/MessageAttachments.interaction.test.ts +0 -245
- package/src/components/mail/MessageAttachments.tsx +0 -188
- package/src/components/mail/MessageBody.blocked-sender.test.ts +0 -193
- package/src/components/mail/MessageBody.tsx +0 -226
- package/src/components/mail/MessageBodyErrorBanner.render.test.ts +0 -85
- package/src/components/mail/MessageBodyErrorBanner.test.ts +0 -56
- package/src/components/mail/MessageBodyErrorBanner.tsx +0 -90
- package/src/components/mail/MessageCard.blocked-sender.test.ts +0 -246
- package/src/components/mail/MessageCard.tsx +0 -430
- package/src/components/mail/MessageList.move-guard.test.ts +0 -64
- package/src/components/mail/MessageList.run-reporting.test.ts +0 -87
- package/src/components/mail/MessageList.tsx +0 -1383
- package/src/components/mail/MessageListItem.test.ts +0 -153
- package/src/components/mail/MessageListItem.tsx +0 -106
- package/src/components/mail/MessageRow.render.test.ts +0 -54
- package/src/components/mail/MessageRow.tsx +0 -269
- package/src/components/mail/MessageSettlementAlert.render.test.ts +0 -182
- package/src/components/mail/MessageSettlementAlert.tsx +0 -126
- package/src/components/mail/MessageToolbar.interaction.test.ts +0 -250
- package/src/components/mail/MessageToolbar.render.test.ts +0 -124
- package/src/components/mail/MessageToolbar.tsx +0 -215
- package/src/components/mail/MobileMessageBar.tsx +0 -140
- package/src/components/mail/MoveToTrigger.render.test.ts +0 -310
- package/src/components/mail/MoveToTrigger.tsx +0 -298
- package/src/components/mail/NavMenuButton.tsx +0 -25
- package/src/components/mail/OutboxPane.tsx +0 -584
- package/src/components/mail/PullToRefresh.tsx +0 -24
- package/src/components/mail/RawMessageView.tsx +0 -84
- package/src/components/mail/RoleAppointmentPromptProvider.render.test.ts +0 -294
- package/src/components/mail/RoleAppointmentPromptProvider.tsx +0 -251
- package/src/components/mail/SelectionWizardHost.search-entry.test.ts +0 -81
- package/src/components/mail/SelectionWizardHost.tsx +0 -1078
- package/src/components/mail/SpamRescue.tsx +0 -126
- package/src/components/mail/SwipeableMessageRow.modifier-select.test.ts +0 -243
- package/src/components/mail/SwipeableMessageRow.render.test.ts +0 -110
- package/src/components/mail/SwipeableMessageRow.tsx +0 -160
- package/src/components/mail/ThreadListInteraction.test.ts +0 -546
- package/src/components/mail/ThreadListInteraction.tsx +0 -538
- package/src/components/mail/authenticity-warning.stories.tsx +0 -116
- package/src/components/mail/blocked-images-notice.stories.tsx +0 -90
- package/src/components/mail/brief-server-sections.render.test.ts +0 -656
- package/src/components/mail/bulk-run-state.test.ts +0 -101
- package/src/components/mail/bulk-run-state.ts +0 -99
- package/src/components/mail/conversation-reply-identity.render.test.ts +0 -307
- package/src/components/mail/conversation-reply-reach.render.test.ts +0 -414
- package/src/components/mail/daily-brief.stories.tsx +0 -264
- package/src/components/mail/delete-open-message-keeps-the-list.render.test.ts +0 -154
- package/src/components/mail/detail-surface.stories.tsx +0 -171
- package/src/components/mail/drafts.stories.tsx +0 -61
- package/src/components/mail/empty-trash-bar.stories.tsx +0 -121
- package/src/components/mail/enter-cursor-late-open.render.test.ts +0 -197
- package/src/components/mail/filtered-empty-state.render.test.ts +0 -240
- package/src/components/mail/flagged-search-reach.render.test.ts +0 -272
- package/src/components/mail/flagged.stories.tsx +0 -159
- package/src/components/mail/intelligence-auto-open-pref.render.test.ts +0 -412
- package/src/components/mail/intelligence-drawer.stories.tsx +0 -353
- package/src/components/mail/intelligence-shortcut-surface.render.test.ts +0 -373
- package/src/components/mail/intelligence-story-calendar.ts +0 -19
- package/src/components/mail/intelligence-surface-reach.render.test.ts +0 -220
- package/src/components/mail/mail-pickers.stories.tsx +0 -82
- package/src/components/mail/message-body-error-banner-content.ts +0 -87
- package/src/components/mail/message-gone.stories.tsx +0 -44
- package/src/components/mail/offer-times-reply.render.test.ts +0 -557
- package/src/components/mail/organize-run-state.test.ts +0 -115
- package/src/components/mail/organize-run-state.ts +0 -44
- package/src/components/mail/outbox.stories.tsx +0 -59
- package/src/components/mail/reclassify-remove-override.render.test.ts +0 -138
- package/src/components/mail/reply-verbs-reach.render.test.ts +0 -235
- package/src/components/mail/search.stories.tsx +0 -280
- package/src/components/mail/selection-wizard-run-controls.test.ts +0 -231
- package/src/components/mail/selection-wizard-run-controls.ts +0 -101
- package/src/components/mail/selection-wizard.stories.tsx +0 -160
- package/src/components/mail/spam-offer-server-count.render.test.ts +0 -349
- package/src/components/mail/two-window-listeners-one-key.render.test.ts +0 -593
- package/src/components/mail/useModifierSelect.render.test.ts +0 -223
- package/src/components/mail/useModifierSelect.ts +0 -100
- package/src/components/onboarding/OnboardingWizard.flow.test.ts +0 -709
- package/src/components/onboarding/OnboardingWizard.tsx +0 -1599
- package/src/components/onboarding/credential-steps.tsx +0 -441
- package/src/components/onboarding/onboarding-servers.stories.tsx +0 -49
- package/src/components/onboarding/onboarding.stories.tsx +0 -550
- package/src/components/overlay-escape.render.test.ts +0 -155
- package/src/components/self-update/SelfUpdateOverlay.tsx +0 -45
- package/src/components/settings/AccountFormPanel.render.test.ts +0 -269
- package/src/components/settings/AccountFormPanel.test.ts +0 -37
- package/src/components/settings/AccountFormPanel.tsx +0 -949
- package/src/components/settings/AccountServices.render.test.ts +0 -257
- package/src/components/settings/AccountServices.tsx +0 -181
- package/src/components/settings/AccountServicesCard.stories.tsx +0 -71
- package/src/components/settings/AccountServicesCard.tsx +0 -76
- package/src/components/settings/AdvancedNavIcon.tsx +0 -23
- package/src/components/settings/CalendarCreateCard.stories.tsx +0 -33
- package/src/components/settings/CalendarCreateCard.tsx +0 -149
- package/src/components/settings/CalendarDetailsForm.stories.tsx +0 -57
- package/src/components/settings/CalendarDetailsForm.tsx +0 -136
- package/src/components/settings/CalendarFeedCard.render.test.ts +0 -154
- package/src/components/settings/CalendarFeedCard.stories.tsx +0 -152
- package/src/components/settings/CalendarFeedCard.tsx +0 -289
- package/src/components/settings/CalendarFeedPanel.tsx +0 -38
- package/src/components/settings/CalendarSettingsPanel.tsx +0 -60
- package/src/components/settings/CalendarSubscribeCard.stories.tsx +0 -89
- package/src/components/settings/CalendarSubscribeCard.tsx +0 -115
- package/src/components/settings/CalendarSubscriptionStatus.stories.tsx +0 -77
- package/src/components/settings/CalendarSubscriptionStatus.tsx +0 -87
- package/src/components/settings/ConfigExportCard.tsx +0 -114
- package/src/components/settings/ConfigTransferPanel.tsx +0 -72
- package/src/components/settings/DangerZone.tsx +0 -30
- package/src/components/settings/DeleteAccountDialog.render.test.ts +0 -47
- package/src/components/settings/DeleteAccountDialog.tsx +0 -224
- package/src/components/settings/DeleteFolderDialog.render.test.ts +0 -836
- package/src/components/settings/DeleteFolderDialog.tsx +0 -406
- package/src/components/settings/FilterActionError.render.test.ts +0 -46
- package/src/components/settings/FilterActionError.stories.tsx +0 -50
- package/src/components/settings/FilterActionError.tsx +0 -40
- package/src/components/settings/FilterEditor.render.test.ts +0 -307
- package/src/components/settings/FilterEditor.tsx +0 -364
- package/src/components/settings/FilterEditorSurface.tsx +0 -65
- package/src/components/settings/FiltersList.render.test.ts +0 -202
- package/src/components/settings/FiltersList.stories.tsx +0 -113
- package/src/components/settings/FiltersList.tsx +0 -191
- package/src/components/settings/LabelsList.stories.tsx +0 -134
- package/src/components/settings/LabelsList.tsx +0 -112
- package/src/components/settings/SelfUpdatePanel.tsx +0 -47
- package/src/components/settings/TimeZoneSelect.tsx +0 -43
- package/src/components/settings/TlsRootCaDownload.render.test.ts +0 -37
- package/src/components/settings/TlsRootCaDownload.tsx +0 -33
- package/src/components/settings/WarningsNavIcon.tsx +0 -12
- package/src/components/settings/WarningsPanel.dom.test.ts +0 -201
- package/src/components/settings/WarningsPanel.render.test.ts +0 -56
- package/src/components/settings/WarningsPanel.tsx +0 -244
- package/src/components/settings/account-form-helpers.test.ts +0 -172
- package/src/components/settings/account-form-helpers.ts +0 -105
- package/src/components/settings/accounts.stories.tsx +0 -386
- package/src/components/settings/advanced.stories.tsx +0 -40
- package/src/components/settings/appearance.stories.tsx +0 -33
- package/src/components/settings/calendar-collection-cards.render.test.ts +0 -149
- package/src/components/settings/calendar-feed-flow.render.test.ts +0 -449
- package/src/components/settings/folders.stories.tsx +0 -89
- package/src/components/settings/label-delete-confirm.stories.tsx +0 -83
- package/src/components/settings/self-update.stories.tsx +0 -288
- package/src/components/settings/senders.stories.tsx +0 -155
- package/src/components/settings/settings-filter.stories.tsx +0 -145
- package/src/components/settings/warnings.stories.tsx +0 -290
- package/src/components/ui/AppVersion.stories.tsx +0 -31
- package/src/components/ui/AppVersion.tsx +0 -57
- package/src/components/ui/BugReportButton.stories.tsx +0 -19
- package/src/components/ui/BugReportButton.tsx +0 -20
- package/src/components/ui/ErrorBannerProvider.render.test.ts +0 -85
- package/src/components/ui/ErrorBannerProvider.tsx +0 -134
- package/src/components/ui/FatalErrorOverlay.render.test.ts +0 -66
- package/src/components/ui/FatalErrorOverlay.stories.tsx +0 -55
- package/src/components/ui/FatalErrorOverlay.tsx +0 -158
- package/src/components/ui/banner-way-out.test.ts +0 -71
- package/src/components/ui/error-banners.test.ts +0 -186
- package/src/components/ui/error-banners.ts +0 -121
- package/src/components/ui/folder-role-refusal.test.ts +0 -124
- package/src/components/ui/folder-role-refusal.ts +0 -69
- package/src/components/ui/placement-refusal.test.ts +0 -98
- package/src/components/ui/placement-refusal.ts +0 -71
- package/src/hooks/bulk-chunking.render.test.ts +0 -157
- package/src/hooks/calendar/agenda-window.test.ts +0 -392
- package/src/hooks/calendar/agenda-window.ts +0 -210
- package/src/hooks/calendar/calendar-collections.render.test.ts +0 -281
- package/src/hooks/calendar/calendar-reads.render.test.ts +0 -265
- package/src/hooks/calendar/calendar-writes.render.test.ts +0 -326
- package/src/hooks/calendar/draft.test.ts +0 -537
- package/src/hooks/calendar/draft.ts +0 -204
- package/src/hooks/calendar/index.ts +0 -122
- package/src/hooks/calendar/instance.test.ts +0 -206
- package/src/hooks/calendar/instance.ts +0 -224
- package/src/hooks/calendar/recurrence-rule.test.ts +0 -134
- package/src/hooks/calendar/recurrence-rule.ts +0 -177
- package/src/hooks/calendar/resource.test.ts +0 -141
- package/src/hooks/calendar/resource.ts +0 -104
- package/src/hooks/calendar/selection.ts +0 -110
- package/src/hooks/calendar/suggestion-draft.ts +0 -77
- package/src/hooks/calendar/useCalendarCollectionWrites.ts +0 -131
- package/src/hooks/calendar/useCalendarEvent.ts +0 -46
- package/src/hooks/calendar/useCalendarEvents.ts +0 -195
- package/src/hooks/calendar/useCalendarFeed.ts +0 -163
- package/src/hooks/calendar/useCalendarFreeBusy.ts +0 -80
- package/src/hooks/calendar/useCalendarJump.ts +0 -117
- package/src/hooks/calendar/useCalendarSubscriptions.ts +0 -103
- package/src/hooks/calendar/useCalendarSuggestions.ts +0 -279
- package/src/hooks/calendar/useCalendarWrites.ts +0 -177
- package/src/hooks/calendar/useCalendars.ts +0 -59
- package/src/hooks/calendar/useDraftClashes.ts +0 -93
- package/src/hooks/calendar/window.test.ts +0 -189
- package/src/hooks/calendar/window.ts +0 -188
- package/src/hooks/cross-account-bulk.render.test.ts +0 -164
- package/src/hooks/escalated-run-lifetime.render.test.ts +0 -349
- package/src/hooks/escalated-run-refusal.render.test.ts +0 -373
- package/src/hooks/escalated-run-survives-navigation.render.test.ts +0 -524
- package/src/hooks/intelligence-calendar.render.test.ts +0 -497
- package/src/hooks/intelligence-drawer.render.test.ts +0 -99
- package/src/hooks/mutation-optimism.test.ts +0 -278
- package/src/hooks/queries/keys.ts +0 -9
- package/src/hooks/refusal-escalation.render.test.ts +0 -243
- package/src/hooks/signed-out-poll-is-not-fatal.render.test.ts +0 -126
- package/src/hooks/stale-account-sync-visibility.test.ts +0 -166
- package/src/hooks/update-restart-escalation.render.test.ts +0 -340
- package/src/hooks/use-system-update.test.ts +0 -686
- package/src/hooks/use-system-update.ts +0 -341
- package/src/hooks/useApplyLabel.ts +0 -71
- package/src/hooks/useArchiveMailbox.ts +0 -162
- package/src/hooks/useAutoMovedBadge.ts +0 -145
- package/src/hooks/useBriefSections.ts +0 -320
- package/src/hooks/useCalendarData.ts +0 -94
- package/src/hooks/useClauseSuggestions.ts +0 -57
- package/src/hooks/useComposeAttachments.ts +0 -108
- package/src/hooks/useComposeLanguages.ts +0 -69
- package/src/hooks/useCreateMailbox.render.test.ts +0 -233
- package/src/hooks/useCreateMailbox.ts +0 -153
- package/src/hooks/useCurrentMailboxName.ts +0 -128
- package/src/hooks/useDebouncedValue.ts +0 -12
- package/src/hooks/useDeleteFolder.ts +0 -380
- package/src/hooks/useDeleteMessages.test.ts +0 -62
- package/src/hooks/useDeleteMessages.ts +0 -260
- package/src/hooks/useDeleteOutcome.ts +0 -70
- package/src/hooks/useEmptyTrash.render.test.ts +0 -194
- package/src/hooks/useEmptyTrash.ts +0 -191
- package/src/hooks/useEscalatedActions.test.ts +0 -36
- package/src/hooks/useEscalatedActions.ts +0 -334
- package/src/hooks/useFilters.test.ts +0 -106
- package/src/hooks/useFilters.ts +0 -188
- package/src/hooks/useFolderLabelTranslator.ts +0 -19
- package/src/hooks/useFollowFocusOpen.render.test.ts +0 -145
- package/src/hooks/useFollowFocusOpen.ts +0 -81
- package/src/hooks/useInitialSyncProgress.render.test.ts +0 -314
- package/src/hooks/useInitialSyncProgress.ts +0 -134
- package/src/hooks/useInlineImages.ts +0 -93
- package/src/hooks/useIntelligenceCalendar.ts +0 -394
- package/src/hooks/useIntelligenceData.test.ts +0 -403
- package/src/hooks/useIntelligenceData.ts +0 -325
- package/src/hooks/useIntelligenceDrawer.ts +0 -54
- package/src/hooks/useIntelligenceSurface.ts +0 -103
- package/src/hooks/useIsDark.ts +0 -27
- package/src/hooks/useKeyboardNavigation.ts +0 -130
- package/src/hooks/useLabels.ts +0 -124
- package/src/hooks/useLayoutTier.test.ts +0 -96
- package/src/hooks/useLayoutTier.ts +0 -60
- package/src/hooks/useMailboxAccount.ts +0 -67
- package/src/hooks/useMailboxNameIndex.ts +0 -32
- package/src/hooks/useMarkAsRead.test.ts +0 -307
- package/src/hooks/useMarkAsRead.ts +0 -333
- package/src/hooks/useMatchSample.ts +0 -104
- package/src/hooks/useMediaQuery.ts +0 -13
- package/src/hooks/useMessageBodyContent.test.ts +0 -370
- package/src/hooks/useMessageBodyContent.ts +0 -388
- package/src/hooks/useMoveMessages.ts +0 -193
- package/src/hooks/useOrganizeJob.render.test.ts +0 -190
- package/src/hooks/useOrganizeJob.ts +0 -146
- package/src/hooks/useRailPanels.ts +0 -128
- package/src/hooks/useRedirectEnded.ts +0 -116
- package/src/hooks/useRefreshControl.test.ts +0 -287
- package/src/hooks/useRefreshControl.ts +0 -347
- package/src/hooks/useReportSpam.escalation.test.ts +0 -135
- package/src/hooks/useReportSpam.render.test.ts +0 -113
- package/src/hooks/useReportSpam.test.ts +0 -115
- package/src/hooks/useReportSpam.ts +0 -244
- package/src/hooks/useRescueCandidates.test.ts +0 -194
- package/src/hooks/useRescueCandidates.ts +0 -48
- package/src/hooks/useResultCount.render.test.ts +0 -161
- package/src/hooks/useResultCount.ts +0 -68
- package/src/hooks/useResultFolderIndex.ts +0 -88
- package/src/hooks/useReturnFromRedirect.ts +0 -41
- package/src/hooks/useRulePreview.ts +0 -122
- package/src/hooks/useSaveDraft.ts +0 -244
- package/src/hooks/useSearchScope.ts +0 -46
- package/src/hooks/useSearchSuggestions.ts +0 -126
- package/src/hooks/useSearchTokenContext.ts +0 -28
- package/src/hooks/useSelectedSubjects.ts +0 -79
- package/src/hooks/useSignature.ts +0 -69
- package/src/hooks/useSpamMatchCounts.ts +0 -102
- package/src/hooks/useStaleAccountSync.test.ts +0 -300
- package/src/hooks/useStaleAccountSync.ts +0 -325
- package/src/hooks/useStarredThreads.test.ts +0 -209
- package/src/hooks/useStarredThreads.ts +0 -146
- package/src/hooks/useThreadActions.star.test.ts +0 -200
- package/src/hooks/useThreadActions.ts +0 -127
- package/src/hooks/useThreadMessageIds.ts +0 -33
- package/src/hooks/useThreadRow.ts +0 -49
- package/src/hooks/useToggleStar.test.ts +0 -131
- package/src/hooks/useToggleStar.ts +0 -164
- package/src/hooks/useToggleTrusted.test.ts +0 -106
- package/src/hooks/useToggleTrusted.ts +0 -157
- package/src/hooks/useTriageLayer.ts +0 -167
- package/src/hooks/useTriggerSync.test.ts +0 -18
- package/src/hooks/useTriggerSync.ts +0 -64
- package/src/hooks/useUpdateAddressFlags.ts +0 -152
- package/src/hooks/useUpdateFilter.ts +0 -56
- package/src/hooks/useVisualViewport.render.test.ts +0 -63
- package/src/hooks/useVisualViewport.ts +0 -51
- package/src/hooks/useWarningsAttention.ts +0 -37
- package/src/index.css +0 -28
- package/src/index.css.test.ts +0 -97
- package/src/kit-stylesheets.test.ts +0 -64
- package/src/lib/account-order.test.ts +0 -74
- package/src/lib/account-order.ts +0 -13
- package/src/lib/adjacent-message.test.ts +0 -34
- package/src/lib/adjacent-message.ts +0 -20
- package/src/lib/api.ts +0 -121
- package/src/lib/app-info.ts +0 -32
- package/src/lib/attachment-download.test.ts +0 -207
- package/src/lib/attachment-download.ts +0 -195
- package/src/lib/auto-moved.test.ts +0 -234
- package/src/lib/auto-moved.ts +0 -103
- package/src/lib/autodiscovery.test.ts +0 -47
- package/src/lib/autodiscovery.ts +0 -354
- package/src/lib/brief-chip-query.test.ts +0 -85
- package/src/lib/brief-criteria.test.ts +0 -168
- package/src/lib/brief-criteria.ts +0 -129
- package/src/lib/brief.test.ts +0 -493
- package/src/lib/brief.ts +0 -205
- package/src/lib/bug-report.test.ts +0 -487
- package/src/lib/bug-report.ts +0 -320
- package/src/lib/bulk-action-copy.test.ts +0 -123
- package/src/lib/bulk-action-copy.ts +0 -182
- package/src/lib/bulk-actions.test.ts +0 -612
- package/src/lib/bulk-actions.ts +0 -400
- package/src/lib/calendar-collection-copy.test.ts +0 -23
- package/src/lib/calendar-collection-copy.ts +0 -21
- package/src/lib/calendar-density.ts +0 -46
- package/src/lib/calendar-feed-copy.ts +0 -29
- package/src/lib/calendar-feed-url.ts +0 -14
- package/src/lib/calendar-format.ts +0 -74
- package/src/lib/calendar-report.ts +0 -21
- package/src/lib/calendar-route.test.ts +0 -224
- package/src/lib/calendar-route.ts +0 -197
- package/src/lib/calendar-subscription.ts +0 -11
- package/src/lib/calendar-suggestion.test.ts +0 -189
- package/src/lib/calendar-suggestion.ts +0 -263
- package/src/lib/calendar-suggestion.west.test.ts +0 -61
- package/src/lib/client.test.ts +0 -114
- package/src/lib/client.ts +0 -33
- package/src/lib/compose-attachment-controller.test.ts +0 -352
- package/src/lib/compose-attachment-controller.ts +0 -519
- package/src/lib/config-import.test.ts +0 -339
- package/src/lib/config-import.ts +0 -512
- package/src/lib/console-errors.test.ts +0 -64
- package/src/lib/console-errors.ts +0 -92
- package/src/lib/conversation-target.ts +0 -17
- package/src/lib/dedupe-thread-messages.test.ts +0 -79
- package/src/lib/dedupe-thread-messages.ts +0 -26
- package/src/lib/delete-folder.test.ts +0 -304
- package/src/lib/delete-folder.ts +0 -188
- package/src/lib/desktop-breakpoint.test.ts +0 -76
- package/src/lib/display-category.test.ts +0 -32
- package/src/lib/display-category.ts +0 -24
- package/src/lib/drafts.test.ts +0 -218
- package/src/lib/drafts.ts +0 -122
- package/src/lib/error-classifier.test.ts +0 -434
- package/src/lib/error-classifier.ts +0 -260
- package/src/lib/escalation-label.test.ts +0 -49
- package/src/lib/escalation-label.ts +0 -32
- package/src/lib/fatal-error.test.ts +0 -78
- package/src/lib/fatal-error.ts +0 -165
- package/src/lib/filter-report.ts +0 -19
- package/src/lib/flagged-criteria.test.ts +0 -114
- package/src/lib/flagged-criteria.ts +0 -62
- package/src/lib/folder-failure.test.ts +0 -29
- package/src/lib/folder-failure.ts +0 -10
- package/src/lib/folder-roles.test.ts +0 -152
- package/src/lib/folder-roles.ts +0 -110
- package/src/lib/format.test.ts +0 -470
- package/src/lib/format.ts +0 -397
- package/src/lib/fresh-mailbox-count.test.ts +0 -145
- package/src/lib/fresh-mailbox-count.ts +0 -114
- package/src/lib/hot-sync-window.test.ts +0 -59
- package/src/lib/hot-sync-window.ts +0 -48
- package/src/lib/i18n.ts +0 -36
- package/src/lib/inbox-filters.test.ts +0 -134
- package/src/lib/inbox-filters.ts +0 -154
- package/src/lib/intelligence-pref.test.ts +0 -201
- package/src/lib/intelligence-pref.ts +0 -71
- package/src/lib/json.ts +0 -11
- package/src/lib/junk-destination.test.ts +0 -40
- package/src/lib/junk-destination.ts +0 -37
- package/src/lib/list-focus.test.ts +0 -25
- package/src/lib/list-focus.ts +0 -24
- package/src/lib/list-header-chrome.ts +0 -55
- package/src/lib/list-narrowing.test.ts +0 -88
- package/src/lib/list-narrowing.ts +0 -172
- package/src/lib/list-verb-request.test.ts +0 -124
- package/src/lib/list-verb-request.ts +0 -62
- package/src/lib/mail-context.ts +0 -91
- package/src/lib/mail-freshness.test.ts +0 -165
- package/src/lib/mail-freshness.tsx +0 -244
- package/src/lib/mail-route.test.ts +0 -261
- package/src/lib/mail-route.ts +0 -140
- package/src/lib/mail-search.ts +0 -69
- package/src/lib/mailbox-sync-wait.test.ts +0 -186
- package/src/lib/mailbox-sync-wait.ts +0 -102
- package/src/lib/message-attachments.test.ts +0 -163
- package/src/lib/message-attachments.ts +0 -70
- package/src/lib/message-body-source.test.ts +0 -115
- package/src/lib/message-body-source.ts +0 -51
- package/src/lib/move-options.test.ts +0 -154
- package/src/lib/move-options.ts +0 -60
- package/src/lib/move-targets.test.ts +0 -235
- package/src/lib/move-targets.ts +0 -70
- package/src/lib/network-error.ts +0 -74
- package/src/lib/new-folder.test.ts +0 -127
- package/src/lib/new-folder.ts +0 -59
- package/src/lib/onboarding-completion.test.ts +0 -48
- package/src/lib/onboarding-completion.ts +0 -23
- package/src/lib/organize/clause-suggestions.test.ts +0 -114
- package/src/lib/organize/clause-suggestions.ts +0 -89
- package/src/lib/organize/filter-edit-model.test.ts +0 -271
- package/src/lib/organize/filter-edit-model.ts +0 -129
- package/src/lib/organize/filter-run.test.ts +0 -79
- package/src/lib/organize/filter-run.ts +0 -48
- package/src/lib/organize/filter-status.test.ts +0 -120
- package/src/lib/organize/filter-status.ts +0 -115
- package/src/lib/organize/label-delete-copy.test.ts +0 -21
- package/src/lib/organize/label-delete-copy.ts +0 -22
- package/src/lib/organize/organize-model.test.ts +0 -209
- package/src/lib/organize/organize-model.ts +0 -198
- package/src/lib/organize/organize-poll.test.ts +0 -37
- package/src/lib/organize/organize-poll.ts +0 -28
- package/src/lib/organize/rule-model.test.ts +0 -211
- package/src/lib/organize/rule-model.ts +0 -140
- package/src/lib/organize/search-to-rule.test.ts +0 -142
- package/src/lib/organize/search-to-rule.ts +0 -105
- package/src/lib/outbox-search.test.ts +0 -75
- package/src/lib/outbox-search.ts +0 -58
- package/src/lib/outbox-status.test.ts +0 -79
- package/src/lib/outbox-status.ts +0 -79
- package/src/lib/provider-presets.test.ts +0 -51
- package/src/lib/provider-presets.ts +0 -94
- package/src/lib/quarantine-entries.test.ts +0 -77
- package/src/lib/quarantine-entries.ts +0 -46
- package/src/lib/query-error-handler.test.ts +0 -87
- package/src/lib/query-error-handler.ts +0 -41
- package/src/lib/query-escalation.integration.test.ts +0 -139
- package/src/lib/recent-searches.test.ts +0 -53
- package/src/lib/recent-searches.ts +0 -34
- package/src/lib/recipient-suggestions.test.ts +0 -109
- package/src/lib/recipient-suggestions.ts +0 -15
- package/src/lib/request-breadcrumbs.test.ts +0 -162
- package/src/lib/request-breadcrumbs.ts +0 -138
- package/src/lib/rescue-candidates.test.ts +0 -94
- package/src/lib/rescue-candidates.ts +0 -35
- package/src/lib/rescue-telemetry.ts +0 -55
- package/src/lib/result-count.test.ts +0 -97
- package/src/lib/result-count.ts +0 -57
- package/src/lib/result-folder.test.ts +0 -133
- package/src/lib/result-folder.ts +0 -111
- package/src/lib/route-breadcrumbs.test.ts +0 -41
- package/src/lib/route-breadcrumbs.ts +0 -45
- package/src/lib/route-search-query.test.ts +0 -70
- package/src/lib/row-settlement.ts +0 -28
- package/src/lib/rum-adapter.test.ts +0 -195
- package/src/lib/rum-adapter.ts +0 -107
- package/src/lib/search-conversion.ts +0 -23
- package/src/lib/search-params.test.ts +0 -77
- package/src/lib/search-params.ts +0 -59
- package/src/lib/search-query.test.ts +0 -24
- package/src/lib/search-query.ts +0 -11
- package/src/lib/search-result.test.ts +0 -20
- package/src/lib/search-result.ts +0 -55
- package/src/lib/search-scope.test.ts +0 -174
- package/src/lib/search-scope.ts +0 -140
- package/src/lib/search-suggestions.test.ts +0 -249
- package/src/lib/search-suggestions.ts +0 -296
- package/src/lib/search-surface.test.ts +0 -74
- package/src/lib/search-surface.ts +0 -34
- package/src/lib/search-token-index.test.ts +0 -232
- package/src/lib/search-token-index.ts +0 -120
- package/src/lib/search-tokens.test.ts +0 -454
- package/src/lib/search-tokens.ts +0 -319
- package/src/lib/search-view.test.ts +0 -320
- package/src/lib/search-view.ts +0 -97
- package/src/lib/selection-account-scope.ts +0 -40
- package/src/lib/selection-mode.test.ts +0 -34
- package/src/lib/selection-mode.ts +0 -24
- package/src/lib/self-update-state.test.ts +0 -552
- package/src/lib/self-update-state.ts +0 -658
- package/src/lib/sender-address.test.ts +0 -60
- package/src/lib/sender-address.ts +0 -36
- package/src/lib/session-storage.ts +0 -7
- package/src/lib/spam-offer.test.ts +0 -192
- package/src/lib/spam-offer.ts +0 -163
- package/src/lib/stale-build.test.ts +0 -52
- package/src/lib/stale-build.ts +0 -36
- package/src/lib/starred-rows.test.ts +0 -67
- package/src/lib/starred-rows.ts +0 -32
- package/src/lib/sync-warning-entries.ts +0 -33
- package/src/lib/telemetry-context.tsx +0 -9
- package/src/lib/telemetry.ts +0 -17
- package/src/lib/theme-preference.ts +0 -46
- package/src/lib/theme.ts +0 -33
- package/src/lib/thread-cache.test.ts +0 -65
- package/src/lib/thread-cache.ts +0 -76
- package/src/lib/thread-list-cache.test.ts +0 -147
- package/src/lib/thread-list-cache.ts +0 -119
- package/src/lib/thread-search-tokens.test.ts +0 -196
- package/src/lib/thread-search-tokens.ts +0 -177
- package/src/lib/wizard-selection.test.ts +0 -50
- package/src/lib/wizard-selection.ts +0 -43
- package/src/main.tsx +0 -10
- package/src/mocks/story-frame/AppStory.tsx +0 -62
- package/src/mocks/story-frame/calendar-window.ts +0 -21
- package/src/mocks/story-frame/compose-world.ts +0 -191
- package/src/mocks/story-frame/mail-handlers.ts +0 -556
- package/src/mocks/story-frame/mail-world.ts +0 -447
- package/src/mocks/story-frame/onboarding-handlers.ts +0 -97
- package/src/mocks/story-frame/session.tsx +0 -19
- package/src/mocks/story-frame/touch.ts +0 -22
- package/src/routeTree.gen.ts +0 -1279
- package/src/router.tsx +0 -59
- package/src/routes/__root.tsx +0 -92
- package/src/routes/calendar/$view.$date/$calendarObjectId/$recurrenceId.tsx +0 -26
- package/src/routes/calendar/$view.$date/$calendarObjectId/index.tsx +0 -18
- package/src/routes/calendar/$view.$date/$calendarObjectId.tsx +0 -15
- package/src/routes/calendar/$view.$date/index.tsx +0 -25
- package/src/routes/calendar/$view.$date/new.tsx +0 -20
- package/src/routes/calendar/$view.$date/suggestion.$suggestionId.tsx +0 -22
- package/src/routes/calendar/$view.$date.tsx +0 -170
- package/src/routes/calendar/-calendar-tree.test.ts +0 -285
- package/src/routes/calendar/index.tsx +0 -27
- package/src/routes/calendar.tsx +0 -99
- package/src/routes/import.tsx +0 -51
- package/src/routes/index.tsx +0 -7
- package/src/routes/mail/$mailboxId/$threadId/$messageId/$mode.{-$outboxMessageId}.tsx +0 -15
- package/src/routes/mail/$mailboxId/$threadId/$messageId.tsx +0 -23
- package/src/routes/mail/$mailboxId/$threadId/index.tsx +0 -14
- package/src/routes/mail/$mailboxId/$threadId.tsx +0 -12
- package/src/routes/mail/$mailboxId/compose.{-$outboxMessageId}.tsx +0 -14
- package/src/routes/mail/$mailboxId/index.tsx +0 -10
- package/src/routes/mail/$mailboxId.tsx +0 -38
- package/src/routes/mail/brief/$threadId/$messageId/$mode.{-$outboxMessageId}.tsx +0 -27
- package/src/routes/mail/brief/$threadId/$messageId.tsx +0 -23
- package/src/routes/mail/brief/$threadId/index.tsx +0 -14
- package/src/routes/mail/brief/$threadId.tsx +0 -16
- package/src/routes/mail/brief/compose.{-$outboxMessageId}.tsx +0 -22
- package/src/routes/mail/brief/index.tsx +0 -14
- package/src/routes/mail/brief.tsx +0 -52
- package/src/routes/mail/flagged/$threadId/$messageId/$mode.{-$outboxMessageId}.tsx +0 -15
- package/src/routes/mail/flagged/$threadId/$messageId.tsx +0 -23
- package/src/routes/mail/flagged/$threadId/index.tsx +0 -14
- package/src/routes/mail/flagged/$threadId.tsx +0 -16
- package/src/routes/mail/flagged/compose.{-$outboxMessageId}.tsx +0 -13
- package/src/routes/mail/flagged/index.tsx +0 -10
- package/src/routes/mail/flagged.tsx +0 -51
- package/src/routes/mail/index.tsx +0 -14
- package/src/routes/mail/outbox/compose.{-$outboxMessageId}.tsx +0 -17
- package/src/routes/mail/outbox/draft/$outboxMessageId.tsx +0 -19
- package/src/routes/mail/outbox/index.tsx +0 -10
- package/src/routes/mail/outbox.tsx +0 -32
- package/src/routes/mail.tsx +0 -262
- package/src/routes/onboarding.tsx +0 -47
- package/src/routes/settings/-accounts.test.ts +0 -340
- package/src/routes/settings/-filters.test.ts +0 -209
- package/src/routes/settings/-senders-remove-flag.render.test.ts +0 -105
- package/src/routes/settings/-shared/help-copy.tsx +0 -91
- package/src/routes/settings/accounts.tsx +0 -692
- package/src/routes/settings/advanced.tsx +0 -57
- package/src/routes/settings/appearance.tsx +0 -118
- package/src/routes/settings/calendars.tsx +0 -134
- package/src/routes/settings/filters.tsx +0 -259
- package/src/routes/settings/folders.tsx +0 -330
- package/src/routes/settings/index.tsx +0 -5
- package/src/routes/settings/labels.tsx +0 -242
- package/src/routes/settings/senders.tsx +0 -444
- package/src/routes/settings/suggested-vips.tsx +0 -10
- package/src/routes/settings/warnings.tsx +0 -36
- package/src/routes/settings.tsx +0 -87
- package/src/routing/browsed-list.ts +0 -76
- package/src/routing/calendar-fragment.test.ts +0 -66
- package/src/routing/calendar.ts +0 -250
- package/src/routing/compose-press-opens.render.test.ts +0 -179
- package/src/routing/compose.ts +0 -181
- package/src/routing/fragment.render.test.ts +0 -98
- package/src/routing/fragment.test.ts +0 -113
- package/src/routing/fragment.ts +0 -145
- package/src/routing/index.ts +0 -93
- package/src/routing/nav-link.tsx +0 -64
- package/src/routing/nav-selection.ts +0 -26
- package/src/routing/open-thread.ts +0 -157
- package/src/routing/outbox-draft.ts +0 -44
- package/src/routing/reply.ts +0 -335
- package/src/routing/search-field.render.test.ts +0 -216
- package/src/routing/search-field.ts +0 -85
- package/src/routing/search-mirror-convergence.render.test.ts +0 -198
- package/src/routing/search-mirror-detail.render.test.ts +0 -226
- package/src/routing/search-mirror.ts +0 -130
- package/src/routing/search-navigation.ts +0 -43
- package/src/routing/sections.ts +0 -55
- package/src/routing/wizard-history.test.ts +0 -163
- package/src/routing/wizard-history.ts +0 -219
- package/src/runtime-config.test.ts +0 -43
- package/src/runtime-config.ts +0 -104
- package/src/shell/index.tsx +0 -101
- package/src/test-support/bulk-run.ts +0 -13
- package/src/test-support/dom.ts +0 -232
- package/src/test-support/fixtures.ts +0 -109
- package/src/test-support/http.ts +0 -82
- package/src/test-support/intelligence-surface.ts +0 -42
- package/src/test-support/list-search-binding.ts +0 -34
- package/src/test-support/test-bundle-app.ts +0 -102
- package/src/test-support/thread-router.ts +0 -54
- package/vite.base.ts +0 -61
- /package/{src → dist/src}/auth/auth.css +0 -0
- /package/{src → dist/src}/auth/cognito/cognito.css +0 -0
- /package/{src → dist/src}/vite-env.d.ts +0 -0
|
@@ -1,1383 +0,0 @@
|
|
|
1
|
-
import type { RemitImapThreadMessageResponse } from "@remit/api-http-client/types.gen.ts";
|
|
2
|
-
import {
|
|
3
|
-
Banner,
|
|
4
|
-
cn,
|
|
5
|
-
type Density,
|
|
6
|
-
deriveIsMultiSelectMode,
|
|
7
|
-
formatErrorMessage,
|
|
8
|
-
ListResultHeader,
|
|
9
|
-
type MessageListFilter,
|
|
10
|
-
MessageListLoadingMore,
|
|
11
|
-
MessageListPane,
|
|
12
|
-
nextFocusId,
|
|
13
|
-
type ResultCount,
|
|
14
|
-
type SelectionModifiers,
|
|
15
|
-
SelectionTopBar,
|
|
16
|
-
useSelection,
|
|
17
|
-
type Verb,
|
|
18
|
-
} from "@remit/ui";
|
|
19
|
-
import { useBlocker } from "@tanstack/react-router";
|
|
20
|
-
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
21
|
-
import type { RefObject } from "react";
|
|
22
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
23
|
-
import { useErrorBanners } from "@/components/ui/ErrorBannerProvider";
|
|
24
|
-
import { useJunkMailbox } from "@/hooks/useArchiveMailbox";
|
|
25
|
-
import { useDeleteOutcome } from "@/hooks/useDeleteOutcome";
|
|
26
|
-
import {
|
|
27
|
-
type EscalationSearchQuery,
|
|
28
|
-
useEscalatedActions,
|
|
29
|
-
} from "@/hooks/useEscalatedActions";
|
|
30
|
-
import { useFollowFocusOpen } from "@/hooks/useFollowFocusOpen";
|
|
31
|
-
import { useLabelList } from "@/hooks/useLabels";
|
|
32
|
-
import { useToggleReadFor } from "@/hooks/useMarkAsRead";
|
|
33
|
-
import { useIsDesktop } from "@/hooks/useMediaQuery";
|
|
34
|
-
import { buildBugReportContext, buildGitHubIssueUrl } from "@/lib/bug-report";
|
|
35
|
-
import {
|
|
36
|
-
type BulkActionKind,
|
|
37
|
-
bulkActionCompletionText,
|
|
38
|
-
bulkActionProgressLabel,
|
|
39
|
-
bulkActionProgressTone,
|
|
40
|
-
runEndingBanner,
|
|
41
|
-
} from "@/lib/bulk-action-copy";
|
|
42
|
-
import type { BulkRunOutcome } from "@/lib/bulk-actions";
|
|
43
|
-
import {
|
|
44
|
-
describeSearchScope,
|
|
45
|
-
escalatedStatusLabel,
|
|
46
|
-
escalationActionLabel,
|
|
47
|
-
} from "@/lib/escalation-label";
|
|
48
|
-
import { formatEmailDate } from "@/lib/format";
|
|
49
|
-
import { junkDestination } from "@/lib/junk-destination";
|
|
50
|
-
import { tabStopId } from "@/lib/list-focus";
|
|
51
|
-
import { useListHeaderChrome } from "@/lib/list-header-chrome";
|
|
52
|
-
import { listVerbRequest } from "@/lib/list-verb-request";
|
|
53
|
-
import { resolveSelectionAccountScope } from "@/lib/selection-account-scope";
|
|
54
|
-
import { shouldExitSelectionOnNavigate } from "@/lib/selection-mode";
|
|
55
|
-
import type { WizardSelectionMessage } from "@/lib/wizard-selection";
|
|
56
|
-
import {
|
|
57
|
-
useOpenThread,
|
|
58
|
-
useSelectionWizard,
|
|
59
|
-
useWizardStepValue,
|
|
60
|
-
} from "@/routing";
|
|
61
|
-
import { DeleteConfirmDialog } from "./DeleteConfirmDialog";
|
|
62
|
-
import { LabelApplyTrigger } from "./LabelApplyTrigger";
|
|
63
|
-
import {
|
|
64
|
-
type EscalatedSelection,
|
|
65
|
-
SelectionWizardHost,
|
|
66
|
-
} from "./SelectionWizardHost";
|
|
67
|
-
import { SwipeableMessageRow } from "./SwipeableMessageRow";
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* The list operations the global keyboard layer drives. The list publishes an
|
|
71
|
-
* implementation into a ref the route owns, so navigation and selection keys
|
|
72
|
-
* are routed by the one dispatcher in `useTriageKeyboard` instead of a second
|
|
73
|
-
* window listener of the list's own (#43).
|
|
74
|
-
*/
|
|
75
|
-
export interface MessageListCommands {
|
|
76
|
-
focusNext: () => void;
|
|
77
|
-
focusPrevious: () => void;
|
|
78
|
-
focusFirst: () => void;
|
|
79
|
-
focusLast: () => void;
|
|
80
|
-
openFocused: () => void;
|
|
81
|
-
toggleSelect: () => void;
|
|
82
|
-
extendSelectDown: () => void;
|
|
83
|
-
extendSelectUp: () => void;
|
|
84
|
-
selectAll: () => void;
|
|
85
|
-
/** Returns true when there was a selection to clear — Esc consumes it. */
|
|
86
|
-
clearSelection: () => boolean;
|
|
87
|
-
/**
|
|
88
|
-
* Runs a verb over the list's selection by opening the wizard on it, which is
|
|
89
|
-
* where every selection action is reviewed before it reaches the mail server
|
|
90
|
-
* (#477 1.4, #508). Returns false when the list did not take the press, so
|
|
91
|
-
* the pane's own verb can act on the focused row instead — a verb aimed at
|
|
92
|
-
* one row is not a bulk action and does not walk the wizard. Delete is the
|
|
93
|
-
* exception with nothing ticked: the list still claims it, to confirm the
|
|
94
|
-
* move to Trash and then place the cursor on a surviving row.
|
|
95
|
-
*/
|
|
96
|
-
requestVerb: (verb: Verb) => boolean;
|
|
97
|
-
toggleDensity: () => void;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface MessageListProps {
|
|
101
|
-
mailboxId: string;
|
|
102
|
-
threads: RemitImapThreadMessageResponse[];
|
|
103
|
-
selectedMessageId?: string;
|
|
104
|
-
isLoading: boolean;
|
|
105
|
-
isError?: boolean;
|
|
106
|
-
error?: unknown;
|
|
107
|
-
onRetry?: () => void;
|
|
108
|
-
searchQuery?: string;
|
|
109
|
-
/**
|
|
110
|
-
* The active search predicate (undefined when not searching). Re-issued
|
|
111
|
-
* with fresh continuation tokens to page past what's loaded — the
|
|
112
|
-
* escalated select-all flow (issue #92) — since `searchQuery` above is
|
|
113
|
-
* only the display string.
|
|
114
|
-
*/
|
|
115
|
-
searchPredicate?: EscalationSearchQuery;
|
|
116
|
-
/**
|
|
117
|
-
* How many messages the search matches, as the server counted them — the
|
|
118
|
-
* whole match set, not the pages loaded. Omitted where the count was never
|
|
119
|
-
* asked for, which renders the header without a number.
|
|
120
|
-
*/
|
|
121
|
-
resultCount?: ResultCount;
|
|
122
|
-
onDeleteMessages?: (messageIds: string[]) => void;
|
|
123
|
-
isDeleting?: boolean;
|
|
124
|
-
isMoving?: boolean;
|
|
125
|
-
onLoadMore?: () => void;
|
|
126
|
-
hasMore?: boolean;
|
|
127
|
-
isLoadingMore?: boolean;
|
|
128
|
-
/**
|
|
129
|
-
* Owning account for the current mailbox view. Required for the Move
|
|
130
|
-
* action — when missing or when the selection spans multiple accounts
|
|
131
|
-
* the toolbar disables Move and surfaces an inline hint.
|
|
132
|
-
*/
|
|
133
|
-
accountId?: string;
|
|
134
|
-
/**
|
|
135
|
-
* Mailbox display title shown in the list pane header.
|
|
136
|
-
* The parent route owns the title; the list pane renders it.
|
|
137
|
-
*/
|
|
138
|
-
listTitle: string;
|
|
139
|
-
/**
|
|
140
|
-
* Optional subtitle (e.g. "3 unread") shown alongside the title.
|
|
141
|
-
*/
|
|
142
|
-
listMeta?: string;
|
|
143
|
-
/**
|
|
144
|
-
* What narrows the list, when anything does. The empty state needs it to say
|
|
145
|
-
* it is filtered and how much of the collection the request reached; without
|
|
146
|
-
* it a narrowed list renders as an empty mailbox, which is the shape #315's
|
|
147
|
-
* bug hid behind.
|
|
148
|
-
*/
|
|
149
|
-
listFilter?: MessageListFilter;
|
|
150
|
-
/**
|
|
151
|
-
* The free text the empty state names, which is `searchQuery` with the typed
|
|
152
|
-
* filter tokens taken out: `listFilter` already names those, and a headline
|
|
153
|
-
* saying one narrowing twice reads as two.
|
|
154
|
-
*/
|
|
155
|
-
listSearchText?: string;
|
|
156
|
-
/** Name of the collection being listed, e.g. "Inbox", for the empty state. */
|
|
157
|
-
listScopeLabel?: string;
|
|
158
|
-
/**
|
|
159
|
-
* Triage-layer context bridge (#429). The roving focus cursor and the
|
|
160
|
-
* multi-selection live here; the parent route's global keyboard dispatcher
|
|
161
|
-
* needs them to target the action verbs (reply/star/…) at the
|
|
162
|
-
* focused row, or the selection when one exists. Called whenever either
|
|
163
|
-
* changes. `focusedMessageId` is the keyboard cursor (distinct from the
|
|
164
|
-
* open/selected thread in the URL); `selectedIds` is the checkbox set.
|
|
165
|
-
*/
|
|
166
|
-
onTriageContextChange?: (context: {
|
|
167
|
-
focusedMessageId: string | undefined;
|
|
168
|
-
selectedIds: string[];
|
|
169
|
-
/**
|
|
170
|
-
* Whether a list is mounted with commands published. The route registers
|
|
171
|
-
* its list-driven key handlers only while this holds, so keys the list
|
|
172
|
-
* owns (Enter, Space, ⌘A) are left to the browser everywhere else.
|
|
173
|
-
*/
|
|
174
|
-
hasList: boolean;
|
|
175
|
-
}) => void;
|
|
176
|
-
/**
|
|
177
|
-
* Ref the list publishes its {@link MessageListCommands} into, so the route's
|
|
178
|
-
* keyboard dispatcher can drive navigation and selection. Cleared on unmount.
|
|
179
|
-
*/
|
|
180
|
-
commandsRef?: RefObject<MessageListCommands | null>;
|
|
181
|
-
/**
|
|
182
|
-
* Suppress the pane's built-in title header — the shared `MailHeader` above
|
|
183
|
-
* the list owns it (the inbox renders inside `MailViewChrome`).
|
|
184
|
-
*/
|
|
185
|
-
hideHeader?: boolean;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const COMFORTABLE_ITEM_HEIGHT = 72;
|
|
189
|
-
const COMPACT_ITEM_HEIGHT = 32;
|
|
190
|
-
const OVERSCAN_COUNT = 5;
|
|
191
|
-
const DENSITY_STORAGE_KEY = "remit:list-density";
|
|
192
|
-
|
|
193
|
-
const readStoredDensity = (): Density => {
|
|
194
|
-
try {
|
|
195
|
-
const stored = localStorage.getItem(DENSITY_STORAGE_KEY);
|
|
196
|
-
if (stored === "compact" || stored === "comfortable") return stored;
|
|
197
|
-
} catch {
|
|
198
|
-
// localStorage unavailable (SSR, privacy mode) — fall through
|
|
199
|
-
}
|
|
200
|
-
return "comfortable";
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Why Move is withheld from a selection, in the toolbar's own words. Rows from
|
|
205
|
-
* a per-mailbox endpoint carry no account of their own, so the list's own
|
|
206
|
-
* account stands in for them and a row that does carry one is still compared
|
|
207
|
-
* against it. Pure, so it tests without a DOM.
|
|
208
|
-
*/
|
|
209
|
-
export const resolveMoveDisabledHint = (
|
|
210
|
-
threads: readonly RemitImapThreadMessageResponse[],
|
|
211
|
-
selectedIds: ReadonlySet<string>,
|
|
212
|
-
listAccountId: string | undefined,
|
|
213
|
-
): string | undefined =>
|
|
214
|
-
resolveSelectionAccountScope(
|
|
215
|
-
threads
|
|
216
|
-
.filter((thread) => selectedIds.has(thread.messageId))
|
|
217
|
-
.map((thread) => thread.accountId ?? listAccountId),
|
|
218
|
-
).moveDisabledHint;
|
|
219
|
-
|
|
220
|
-
export const MessageList = ({
|
|
221
|
-
mailboxId,
|
|
222
|
-
threads,
|
|
223
|
-
selectedMessageId,
|
|
224
|
-
isLoading,
|
|
225
|
-
isError = false,
|
|
226
|
-
error,
|
|
227
|
-
onRetry,
|
|
228
|
-
searchQuery,
|
|
229
|
-
searchPredicate,
|
|
230
|
-
resultCount = { kind: "unknown" },
|
|
231
|
-
onDeleteMessages,
|
|
232
|
-
isDeleting = false,
|
|
233
|
-
isMoving = false,
|
|
234
|
-
onLoadMore,
|
|
235
|
-
hasMore = false,
|
|
236
|
-
isLoadingMore = false,
|
|
237
|
-
accountId,
|
|
238
|
-
listTitle,
|
|
239
|
-
listMeta,
|
|
240
|
-
listFilter,
|
|
241
|
-
listSearchText,
|
|
242
|
-
listScopeLabel,
|
|
243
|
-
onTriageContextChange,
|
|
244
|
-
commandsRef,
|
|
245
|
-
hideHeader = false,
|
|
246
|
-
}: MessageListProps) => {
|
|
247
|
-
const parentRef = useRef<HTMLDivElement>(null);
|
|
248
|
-
const openThread = useOpenThread();
|
|
249
|
-
const isDesktop = useIsDesktop();
|
|
250
|
-
const wizard = useSelectionWizard();
|
|
251
|
-
const { verb: wizardVerb, start: startWizard, startFromSearch } = wizard;
|
|
252
|
-
const wizardStep = useWizardStepValue();
|
|
253
|
-
const isSearching = !!searchQuery?.trim();
|
|
254
|
-
const listHeaderChrome = useListHeaderChrome();
|
|
255
|
-
const { labels } = useLabelList(accountId);
|
|
256
|
-
const { pushError } = useErrorBanners();
|
|
257
|
-
|
|
258
|
-
// Roving focus cursor (#429): the keyboard "where am I" pointer, distinct
|
|
259
|
-
// from the open thread (the message segment in the path). j/k move this
|
|
260
|
-
// cursor; Enter opens the focused row → sets selected, and on desktop the
|
|
261
|
-
// reading pane follows the cursor of its own accord (see the follow-focus
|
|
262
|
-
// wiring below). It seeds from the open thread so opening a message also
|
|
263
|
-
// focuses its row, and click-to-open keeps working unchanged (the route
|
|
264
|
-
// still navigates).
|
|
265
|
-
const [focusedMessageId, setFocusedId] = useState<string | undefined>(
|
|
266
|
-
selectedMessageId,
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
// Which of those moves came from a keyboard command, so the reading pane can
|
|
270
|
-
// follow the cursor without following a click that already opened its own row.
|
|
271
|
-
const [keyboardFocusedMessageId, setKeyboardFocusedMessageId] = useState<
|
|
272
|
-
string | undefined
|
|
273
|
-
>();
|
|
274
|
-
|
|
275
|
-
// Every non-keyboard move — a click, Tab, a thread opening, a refetch snapping
|
|
276
|
-
// the cursor to a survivor — drops the keyboard mark, so nothing follows it.
|
|
277
|
-
// A row taking DOM focus as the *consequence* of a keyboard move arrives here
|
|
278
|
-
// with the id that move just set; keeping the mark in that case is what stops
|
|
279
|
-
// the browser's own focus event from cancelling the load the move started.
|
|
280
|
-
const setFocusedMessageId = useCallback((id: string | undefined) => {
|
|
281
|
-
setKeyboardFocusedMessageId((current) =>
|
|
282
|
-
current === id ? current : undefined,
|
|
283
|
-
);
|
|
284
|
-
setFocusedId(id);
|
|
285
|
-
}, []);
|
|
286
|
-
|
|
287
|
-
// Density toggle: comfortable (default) or compact (mutt mode).
|
|
288
|
-
// Persisted to localStorage so the choice survives reloads.
|
|
289
|
-
const [density, setDensity] = useState<Density>(readStoredDensity);
|
|
290
|
-
const toggleDensity = useCallback(() => {
|
|
291
|
-
setDensity((prev) => {
|
|
292
|
-
const next: Density = prev === "comfortable" ? "compact" : "comfortable";
|
|
293
|
-
try {
|
|
294
|
-
localStorage.setItem(DENSITY_STORAGE_KEY, next);
|
|
295
|
-
} catch {
|
|
296
|
-
// ignore
|
|
297
|
-
}
|
|
298
|
-
return next;
|
|
299
|
-
});
|
|
300
|
-
}, []);
|
|
301
|
-
|
|
302
|
-
// Swipe-to-read toggle hook
|
|
303
|
-
const { toggleReadFor } = useToggleReadFor({ mailboxId });
|
|
304
|
-
|
|
305
|
-
// The Junk quick action moves the selection to the account's appointed Junk
|
|
306
|
-
// mailbox — the message-flags API has no `$Junk` field, so "junk" is a move.
|
|
307
|
-
const { junkMailboxId } = useJunkMailbox(accountId);
|
|
308
|
-
const junkDestinationId = junkDestination(junkMailboxId, mailboxId);
|
|
309
|
-
|
|
310
|
-
// Deleting inside Trash is an expunge on the mail server, not a move, so the
|
|
311
|
-
// confirmation has to ask that question instead of "move to Trash?" (#845).
|
|
312
|
-
// Every row here is filed in the open mailbox, so that one folder is the
|
|
313
|
-
// whole set the delete acts on.
|
|
314
|
-
const deleteScope = useMemo(
|
|
315
|
-
() => [{ accountId, mailboxId }],
|
|
316
|
-
[accountId, mailboxId],
|
|
317
|
-
);
|
|
318
|
-
const {
|
|
319
|
-
outcome: deleteOutcome,
|
|
320
|
-
staleFolderLabel,
|
|
321
|
-
guessedMailboxId,
|
|
322
|
-
} = useDeleteOutcome(deleteScope);
|
|
323
|
-
|
|
324
|
-
// Selection state
|
|
325
|
-
const {
|
|
326
|
-
selectedIds,
|
|
327
|
-
selectedCount,
|
|
328
|
-
hasSelection,
|
|
329
|
-
isSelected: isChecked,
|
|
330
|
-
toggle: toggleCheck,
|
|
331
|
-
select,
|
|
332
|
-
clearSelection,
|
|
333
|
-
selectRange,
|
|
334
|
-
setAnchor,
|
|
335
|
-
selectAll,
|
|
336
|
-
toggleAll,
|
|
337
|
-
intersectWith,
|
|
338
|
-
} = useSelection();
|
|
339
|
-
|
|
340
|
-
// The selection count is the only source of truth for whether the list is
|
|
341
|
-
// in multi-select mode (#115). A separate flag needs an effect to reconcile
|
|
342
|
-
// it back to the count, and across that render the two disagree.
|
|
343
|
-
const isMultiSelectMode = deriveIsMultiSelectMode(selectedCount, isDesktop);
|
|
344
|
-
|
|
345
|
-
// The one delete that does not walk the wizard: the Delete key with nothing
|
|
346
|
-
// ticked, which acts on the row under the cursor. The ids are snapshotted at
|
|
347
|
-
// request time so a cursor move behind the dialog cannot retarget it. Every
|
|
348
|
-
// delete over a selection — ticked or escalated — goes through the wizard's
|
|
349
|
-
// review screen instead.
|
|
350
|
-
const [pendingDelete, setPendingDelete] = useState<string[] | null>(null);
|
|
351
|
-
|
|
352
|
-
// Search-scoped escalated selection + chunked bulk actions (issues #92, #212):
|
|
353
|
-
// available on both surfaces, and only while search has more matches than
|
|
354
|
-
// are loaded. `orderedIds` below feeds `allLoadedSelected`; declared after
|
|
355
|
-
// this hook so its callback deps stay simple — see the
|
|
356
|
-
// `orderedIds`/`handleRowSelect` block.
|
|
357
|
-
// How a run ended, for the user who is no longer looking at any screen that
|
|
358
|
-
// could show it. Closing the wizard mid-run is a movement the screen invites,
|
|
359
|
-
// and leaving the mailbox on top of that is one nothing prevents — the run
|
|
360
|
-
// keeps going past both, so this states the ending, whether the run covered
|
|
361
|
-
// everything or stopped short of it. The run's owner calls it only once no
|
|
362
|
-
// screen is left reporting in place, so an ending is never said twice.
|
|
363
|
-
const reportRunOutcome = useCallback(
|
|
364
|
-
(kind: BulkActionKind, matched: number, outcome: BulkRunOutcome) => {
|
|
365
|
-
const banner = runEndingBanner(kind, matched, outcome, deleteOutcome);
|
|
366
|
-
// A run stopped by a thrown batch is already banner-ed where it threw.
|
|
367
|
-
if (!banner) return;
|
|
368
|
-
pushError(banner);
|
|
369
|
-
},
|
|
370
|
-
[pushError, deleteOutcome],
|
|
371
|
-
);
|
|
372
|
-
|
|
373
|
-
const escalationEnabled = isSearching && !!searchPredicate;
|
|
374
|
-
const predicateKey = `${mailboxId}|${JSON.stringify(searchPredicate ?? {})}`;
|
|
375
|
-
const escalation = useEscalatedActions({
|
|
376
|
-
mailboxId,
|
|
377
|
-
mailboxLabel: listTitle,
|
|
378
|
-
accountId,
|
|
379
|
-
enabled: escalationEnabled,
|
|
380
|
-
predicateKey,
|
|
381
|
-
searchQuery: searchPredicate ?? {},
|
|
382
|
-
reportEnding: reportRunOutcome,
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
// The one way selection mode ends (#115): cancel, a completed delete or
|
|
386
|
-
// move, a plain click that collapses a range, switching mailboxes, the back
|
|
387
|
-
// gesture. Nothing calls the selection hook's `clearSelection` directly, so
|
|
388
|
-
// an escalated selection can never survive the exit as a stale phase.
|
|
389
|
-
const escalationPhaseKind = escalation.phase.kind;
|
|
390
|
-
const clearEscalation = escalation.clear;
|
|
391
|
-
const exitSelection = useCallback(() => {
|
|
392
|
-
if (escalationPhaseKind === "escalated") clearEscalation();
|
|
393
|
-
clearSelection();
|
|
394
|
-
}, [clearSelection, clearEscalation, escalationPhaseKind]);
|
|
395
|
-
|
|
396
|
-
// Transient, manually-dismissed success banner shown in place of the
|
|
397
|
-
// selection bar once a single-row delete lands on mobile, where the list
|
|
398
|
-
// stays up and nothing else says it happened (#202). Honest about IMAP's
|
|
399
|
-
// async catch-up rather than claiming a finality the bulk endpoint's
|
|
400
|
-
// response doesn't have.
|
|
401
|
-
const [completionBanner, setCompletionBanner] = useState<string | null>(null);
|
|
402
|
-
|
|
403
|
-
// Set when a keyboard command moves the roving cursor. Real DOM focus then
|
|
404
|
-
// follows the cursor onto the row once the virtualizer has rendered it, so
|
|
405
|
-
// the browser's own focus — and therefore Tab, Shift+Tab and the focus ring
|
|
406
|
-
// — agree with what the list highlights (#43). Mouse-driven focus changes
|
|
407
|
-
// leave this null, so the list never yanks focus out of the reading pane.
|
|
408
|
-
const pendingDomFocusRef = useRef<string | null>(null);
|
|
409
|
-
|
|
410
|
-
// Whether the cursor's last move came from a row taking DOM focus — a click,
|
|
411
|
-
// or the browser restoring focus — rather than from a command this list ran.
|
|
412
|
-
// The list scrolls the cursor into view only for its own moves. Scrolling for
|
|
413
|
-
// a click moves the row out from under the pointer between mousedown and the
|
|
414
|
-
// click event, so the click lands on the empty space the row left behind and
|
|
415
|
-
// nothing opens (#85). Only rows below the fold could hit it: the pointer has
|
|
416
|
-
// to have scrolled to reach them, and the list then scrolled again on top of
|
|
417
|
-
// that. Every command below resets this to false before moving the cursor.
|
|
418
|
-
const cursorMovedByPointerRef = useRef(false);
|
|
419
|
-
|
|
420
|
-
// The row the cursor was on when the delete confirmation opened. The dialog
|
|
421
|
-
// takes DOM focus for as long as it is up, so dismissing it has to give that
|
|
422
|
-
// focus back or the list is left with no cursor and the next shortcut acts on
|
|
423
|
-
// nothing (#80).
|
|
424
|
-
const focusBeforeConfirmRef = useRef<string | null>(null);
|
|
425
|
-
|
|
426
|
-
// Whether the list can serve keyboard commands at all. It stays true while
|
|
427
|
-
// the delete confirmation is open — withdrawing the commands there would let
|
|
428
|
-
// the route fall through to its own unconfirmed delete on a second Delete
|
|
429
|
-
// press. The dialog is on the overlay stack, which suspends every layer.
|
|
430
|
-
const commandsAvailable = !isLoading && threads.length > 0;
|
|
431
|
-
|
|
432
|
-
const virtualizer = useVirtualizer({
|
|
433
|
-
count: threads.length,
|
|
434
|
-
getScrollElement: () => parentRef.current,
|
|
435
|
-
estimateSize: () =>
|
|
436
|
-
density === "compact" ? COMPACT_ITEM_HEIGHT : COMFORTABLE_ITEM_HEIGHT,
|
|
437
|
-
overscan: OVERSCAN_COUNT,
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
// Index of the open thread (for scroll-into-view of the reading pane target).
|
|
441
|
-
const currentIndex = selectedMessageId
|
|
442
|
-
? threads.findIndex((t) => t.messageId === selectedMessageId)
|
|
443
|
-
: -1;
|
|
444
|
-
|
|
445
|
-
// Index of the roving focus cursor — what j/k move.
|
|
446
|
-
const focusIndex = focusedMessageId
|
|
447
|
-
? threads.findIndex((t) => t.messageId === focusedMessageId)
|
|
448
|
-
: -1;
|
|
449
|
-
|
|
450
|
-
// Move the focus cursor by index. In multi-select mode (mobile) j/k still
|
|
451
|
-
// toggle selection rather than moving a cursor, preserving prior behavior.
|
|
452
|
-
const moveFocusToIndex = useCallback(
|
|
453
|
-
(index: number) => {
|
|
454
|
-
if (index < 0 || index >= threads.length) return;
|
|
455
|
-
const thread = threads[index];
|
|
456
|
-
if (isMultiSelectMode) {
|
|
457
|
-
toggleCheck(thread.messageId);
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
pendingDomFocusRef.current = thread.messageId;
|
|
461
|
-
cursorMovedByPointerRef.current = false;
|
|
462
|
-
setKeyboardFocusedMessageId(thread.messageId);
|
|
463
|
-
setFocusedId(thread.messageId);
|
|
464
|
-
},
|
|
465
|
-
[threads, isMultiSelectMode, toggleCheck],
|
|
466
|
-
);
|
|
467
|
-
|
|
468
|
-
// j / ArrowDown: move focus to the next row (no open). Starts at the top
|
|
469
|
-
// when nothing is focused yet.
|
|
470
|
-
const focusNext = useCallback(() => {
|
|
471
|
-
if (threads.length === 0) return;
|
|
472
|
-
const nextIndex =
|
|
473
|
-
focusIndex < 0 ? 0 : Math.min(focusIndex + 1, threads.length - 1);
|
|
474
|
-
moveFocusToIndex(nextIndex);
|
|
475
|
-
}, [threads.length, focusIndex, moveFocusToIndex]);
|
|
476
|
-
|
|
477
|
-
// k / ArrowUp: move focus to the previous row.
|
|
478
|
-
const focusPrevious = useCallback(() => {
|
|
479
|
-
if (threads.length === 0) return;
|
|
480
|
-
const prevIndex = focusIndex <= 0 ? 0 : focusIndex - 1;
|
|
481
|
-
moveFocusToIndex(prevIndex);
|
|
482
|
-
}, [threads.length, focusIndex, moveFocusToIndex]);
|
|
483
|
-
|
|
484
|
-
const focusFirst = useCallback(() => moveFocusToIndex(0), [moveFocusToIndex]);
|
|
485
|
-
const focusLast = useCallback(
|
|
486
|
-
() => moveFocusToIndex(threads.length - 1),
|
|
487
|
-
[moveFocusToIndex, threads.length],
|
|
488
|
-
);
|
|
489
|
-
|
|
490
|
-
// Toggle selection on the focused row with x.
|
|
491
|
-
const toggleFocusedSelection = useCallback(() => {
|
|
492
|
-
if (focusedMessageId) {
|
|
493
|
-
toggleCheck(focusedMessageId);
|
|
494
|
-
}
|
|
495
|
-
}, [focusedMessageId, toggleCheck]);
|
|
496
|
-
|
|
497
|
-
// Desktop mouse selection semantics (Apple Mail / Gmail model). Called by a
|
|
498
|
-
// row's onClick with the click modifiers. Returns true when selection
|
|
499
|
-
// handled the click (caller should preventDefault and skip navigation);
|
|
500
|
-
// false for a plain click (caller lets the Link navigate).
|
|
501
|
-
const orderedIds = useMemo(() => threads.map((t) => t.messageId), [threads]);
|
|
502
|
-
|
|
503
|
-
// The checked rows as the wizard reads them: the sample it shows under every
|
|
504
|
-
// screen that names a match, and the senders its properties prefill reads.
|
|
505
|
-
// Read off the already-loaded thread rows, so no extra round-trip.
|
|
506
|
-
const wizardSelection = useMemo<WizardSelectionMessage[]>(() => {
|
|
507
|
-
const rows: WizardSelectionMessage[] = [];
|
|
508
|
-
for (const thread of threads) {
|
|
509
|
-
if (!selectedIds.has(thread.messageId)) continue;
|
|
510
|
-
rows.push({
|
|
511
|
-
id: thread.messageId,
|
|
512
|
-
sender: thread.fromName ?? thread.fromEmail ?? "Unknown",
|
|
513
|
-
email: thread.fromEmail ?? "",
|
|
514
|
-
subject: thread.subject ?? "(No subject)",
|
|
515
|
-
date: formatEmailDate(thread.sentDate),
|
|
516
|
-
accountId,
|
|
517
|
-
mailboxId: thread.mailboxId,
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
return rows;
|
|
521
|
-
}, [threads, selectedIds, accountId]);
|
|
522
|
-
const handleRowSelect = useCallback(
|
|
523
|
-
(messageId: string, modifiers: SelectionModifiers): boolean => {
|
|
524
|
-
if (modifiers.shiftKey) {
|
|
525
|
-
// The open/focused row is the fallback origin when the stored anchor
|
|
526
|
-
// has been filtered or searched out of the visible list, so the first
|
|
527
|
-
// shift-click still ranges from where the user is (#142, #144).
|
|
528
|
-
selectRange(orderedIds, messageId, focusedMessageId);
|
|
529
|
-
return true;
|
|
530
|
-
}
|
|
531
|
-
if (modifiers.metaKey || modifiers.ctrlKey) {
|
|
532
|
-
// Toggle membership and re-anchor on the clicked row.
|
|
533
|
-
toggleCheck(messageId);
|
|
534
|
-
return true;
|
|
535
|
-
}
|
|
536
|
-
// Plain click: collapse any multi-selection and let navigation proceed.
|
|
537
|
-
// The clicked row becomes the next anchor for a subsequent shift-click,
|
|
538
|
-
// but is NOT added to the checkbox set (no toolbar on a plain open).
|
|
539
|
-
exitSelection();
|
|
540
|
-
setAnchor(messageId);
|
|
541
|
-
return false;
|
|
542
|
-
},
|
|
543
|
-
[
|
|
544
|
-
orderedIds,
|
|
545
|
-
focusedMessageId,
|
|
546
|
-
selectRange,
|
|
547
|
-
toggleCheck,
|
|
548
|
-
exitSelection,
|
|
549
|
-
setAnchor,
|
|
550
|
-
],
|
|
551
|
-
);
|
|
552
|
-
|
|
553
|
-
// Open the delete confirmation for the row under the cursor. A delete over a
|
|
554
|
-
// selection is a bulk action and walks the wizard instead, so this is the one
|
|
555
|
-
// delete the dialog still covers.
|
|
556
|
-
const requestDelete = useCallback(
|
|
557
|
-
(ids: string[]) => {
|
|
558
|
-
if (!onDeleteMessages || ids.length === 0) return;
|
|
559
|
-
focusBeforeConfirmRef.current = focusedMessageId ?? null;
|
|
560
|
-
setPendingDelete(ids);
|
|
561
|
-
},
|
|
562
|
-
[onDeleteMessages, focusedMessageId],
|
|
563
|
-
);
|
|
564
|
-
|
|
565
|
-
// Keyboard shift-arrow range extend: move focus one row in `direction` and
|
|
566
|
-
// extend the selection range from the existing anchor to the new focus —
|
|
567
|
-
// the keyboard equivalent of shift-click. The anchor stays fixed across
|
|
568
|
-
// consecutive shift-arrows (selectRange seeds it only when unset), so
|
|
569
|
-
// moving back toward the anchor shrinks the range.
|
|
570
|
-
const extendRange = useCallback(
|
|
571
|
-
(direction: -1 | 1) => {
|
|
572
|
-
const target = nextFocusId(orderedIds, focusedMessageId, direction);
|
|
573
|
-
if (target === undefined) return;
|
|
574
|
-
selectRange(orderedIds, target);
|
|
575
|
-
// Shift+arrow moves the focus cursor (not the open thread) and grows
|
|
576
|
-
// the selection from the anchor — the keyboard equivalent of
|
|
577
|
-
// shift-click. It is building a range, not reading, so the reading pane
|
|
578
|
-
// stays on whatever is open rather than chasing the range's edge.
|
|
579
|
-
pendingDomFocusRef.current = target;
|
|
580
|
-
cursorMovedByPointerRef.current = false;
|
|
581
|
-
setKeyboardFocusedMessageId(undefined);
|
|
582
|
-
setFocusedId(target);
|
|
583
|
-
},
|
|
584
|
-
[orderedIds, focusedMessageId, selectRange],
|
|
585
|
-
);
|
|
586
|
-
|
|
587
|
-
const extendRangeUp = useCallback(() => extendRange(-1), [extendRange]);
|
|
588
|
-
const extendRangeDown = useCallback(() => extendRange(1), [extendRange]);
|
|
589
|
-
|
|
590
|
-
// Cmd/Ctrl+A: select every currently loaded row.
|
|
591
|
-
const handleSelectAll = useCallback(() => {
|
|
592
|
-
if (orderedIds.length > 0) {
|
|
593
|
-
selectAll(orderedIds);
|
|
594
|
-
}
|
|
595
|
-
}, [orderedIds, selectAll]);
|
|
596
|
-
|
|
597
|
-
// A keyboard verb, routed by `listVerbRequest` — the same routing the bar
|
|
598
|
-
// renders from, so a verb the bar withholds is not still reachable by
|
|
599
|
-
// shortcut. Over a selection every verb opens the wizard (#477 1.4), whatever
|
|
600
|
-
// the selection is: the ticked rows, a selection spanning accounts — the
|
|
601
|
-
// wizard is where that restriction is stated, on the step that needs one
|
|
602
|
-
// account (#477 5.5) — or the predicate the list escalated to, which the
|
|
603
|
-
// wizard names on its match step and counts on its review screen before
|
|
604
|
-
// anything is sent (#508).
|
|
605
|
-
const requestVerb = useCallback(
|
|
606
|
-
(verb: Verb): boolean => {
|
|
607
|
-
const request = listVerbRequest({
|
|
608
|
-
verb,
|
|
609
|
-
confirmingDelete: pendingDelete !== null,
|
|
610
|
-
hasSelection,
|
|
611
|
-
junkMailboxId,
|
|
612
|
-
currentMailboxId: mailboxId,
|
|
613
|
-
deletableMessageId: onDeleteMessages ? focusedMessageId : undefined,
|
|
614
|
-
});
|
|
615
|
-
if (request.kind === "openWizard") {
|
|
616
|
-
startWizard(verb);
|
|
617
|
-
return true;
|
|
618
|
-
}
|
|
619
|
-
if (request.kind === "confirmDelete") {
|
|
620
|
-
requestDelete([request.messageId]);
|
|
621
|
-
return true;
|
|
622
|
-
}
|
|
623
|
-
// A shortcut that does nothing at all is indistinguishable from one that
|
|
624
|
-
// is broken, so a verb this mailbox cannot take says why on the press.
|
|
625
|
-
if (request.kind === "unavailable") {
|
|
626
|
-
pushError({ severity: "warning", title: request.reason });
|
|
627
|
-
return true;
|
|
628
|
-
}
|
|
629
|
-
return request.kind === "withheld";
|
|
630
|
-
},
|
|
631
|
-
[
|
|
632
|
-
pendingDelete,
|
|
633
|
-
onDeleteMessages,
|
|
634
|
-
hasSelection,
|
|
635
|
-
junkMailboxId,
|
|
636
|
-
mailboxId,
|
|
637
|
-
startWizard,
|
|
638
|
-
focusedMessageId,
|
|
639
|
-
requestDelete,
|
|
640
|
-
pushError,
|
|
641
|
-
],
|
|
642
|
-
);
|
|
643
|
-
|
|
644
|
-
// Opening a row is a navigation to the conversation under this folder. Every
|
|
645
|
-
// row the list renders names its thread, which is what the reading pane
|
|
646
|
-
// fetches by — a row the list no longer holds cannot be opened from here.
|
|
647
|
-
const openRow = useCallback(
|
|
648
|
-
(messageId: string, options?: { replace?: boolean }) => {
|
|
649
|
-
const threadId = threads.find(
|
|
650
|
-
(thread) => thread.messageId === messageId,
|
|
651
|
-
)?.threadId;
|
|
652
|
-
if (!threadId) return;
|
|
653
|
-
openThread({ threadId, messageId }, { replace: options?.replace });
|
|
654
|
-
},
|
|
655
|
-
[openThread, threads],
|
|
656
|
-
);
|
|
657
|
-
|
|
658
|
-
// Enter: open the focused row in the reading pane. This is the focus→open
|
|
659
|
-
// transition of the 2-state model.
|
|
660
|
-
const handleOpenFocused = useCallback(() => {
|
|
661
|
-
if (!focusedMessageId) return;
|
|
662
|
-
openRow(focusedMessageId);
|
|
663
|
-
}, [focusedMessageId, openRow]);
|
|
664
|
-
|
|
665
|
-
// The reading pane follows the cursor on desktop: j/k load the row they land
|
|
666
|
-
// on, without the user having to press Enter for every message. It replaces
|
|
667
|
-
// the history entry rather than pushing one — a preview the cursor produced
|
|
668
|
-
// is not a navigation the user asked for, and Back should still leave the
|
|
669
|
-
// mailbox instead of walking the cursor's path back up the list.
|
|
670
|
-
//
|
|
671
|
-
// Suspended while rows are selected: the cursor is then picking out a set,
|
|
672
|
-
// and the selection toolbar — not a message — is what the user is looking at.
|
|
673
|
-
// Suspended off desktop too, where the reading pane replaces the list
|
|
674
|
-
// entirely, so following the cursor would throw the user off the list.
|
|
675
|
-
//
|
|
676
|
-
// The open lands a navigation later, and the cursor may have moved on by
|
|
677
|
-
// then. The open records which row it was for, so its arrival does not drag
|
|
678
|
-
// the cursor back off the row the user has since moved to.
|
|
679
|
-
const followOpenedRef = useRef<string | undefined>(undefined);
|
|
680
|
-
const followFocusOpen = useCallback(
|
|
681
|
-
(messageId: string) => {
|
|
682
|
-
followOpenedRef.current = messageId;
|
|
683
|
-
openRow(messageId, { replace: true });
|
|
684
|
-
},
|
|
685
|
-
[openRow],
|
|
686
|
-
);
|
|
687
|
-
useFollowFocusOpen({
|
|
688
|
-
keyboardFocusedMessageId,
|
|
689
|
-
openMessageId: selectedMessageId,
|
|
690
|
-
enabled: isDesktop && selectedCount === 0,
|
|
691
|
-
open: followFocusOpen,
|
|
692
|
-
});
|
|
693
|
-
|
|
694
|
-
// The escalated selection as the wizard walks it (#508): the words the bar
|
|
695
|
-
// already names the predicate with, the count it was escalated to, and the
|
|
696
|
-
// chunked runner that re-resolves it.
|
|
697
|
-
const escalatedSelection: EscalatedSelection | undefined =
|
|
698
|
-
escalation.phase.kind === "escalated"
|
|
699
|
-
? {
|
|
700
|
-
scope: describeSearchScope(searchPredicate ?? {}),
|
|
701
|
-
total: escalation.phase.total,
|
|
702
|
-
searchQuery: searchPredicate ?? {},
|
|
703
|
-
run: (action, claimEnding) =>
|
|
704
|
-
escalation.runAction(action, undefined, claimEnding),
|
|
705
|
-
stop: escalation.stop,
|
|
706
|
-
}
|
|
707
|
-
: undefined;
|
|
708
|
-
|
|
709
|
-
// Confirm handler: run the actual delete, then clear selection and move
|
|
710
|
-
// focus to a sensible neighbor (the row after the first deleted one).
|
|
711
|
-
const handleConfirmDelete = useCallback(
|
|
712
|
-
(ids: string[]) => {
|
|
713
|
-
if (ids.length === 0) {
|
|
714
|
-
setPendingDelete(null);
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
const deletedSet = new Set(ids);
|
|
719
|
-
const firstDeletedIndex = threads.findIndex((t) =>
|
|
720
|
-
deletedSet.has(t.messageId),
|
|
721
|
-
);
|
|
722
|
-
// Next surviving row at or after the first deleted row, else the one
|
|
723
|
-
// before it. Computed against the pre-delete order.
|
|
724
|
-
let nextFocus: string | undefined;
|
|
725
|
-
for (let i = firstDeletedIndex + 1; i < threads.length; i++) {
|
|
726
|
-
if (!deletedSet.has(threads[i].messageId)) {
|
|
727
|
-
nextFocus = threads[i].messageId;
|
|
728
|
-
break;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
if (nextFocus === undefined) {
|
|
732
|
-
for (let i = firstDeletedIndex - 1; i >= 0; i--) {
|
|
733
|
-
if (!deletedSet.has(threads[i].messageId)) {
|
|
734
|
-
nextFocus = threads[i].messageId;
|
|
735
|
-
break;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
onDeleteMessages?.(ids);
|
|
741
|
-
exitSelection();
|
|
742
|
-
focusBeforeConfirmRef.current = null;
|
|
743
|
-
setPendingDelete(null);
|
|
744
|
-
|
|
745
|
-
if (nextFocus !== undefined) {
|
|
746
|
-
// Same hand-back as cancelling, aimed at the surviving neighbour
|
|
747
|
-
// instead: confirming also closes a dialog that held DOM focus.
|
|
748
|
-
pendingDomFocusRef.current = nextFocus;
|
|
749
|
-
cursorMovedByPointerRef.current = false;
|
|
750
|
-
setFocusedMessageId(nextFocus);
|
|
751
|
-
// Desktop is two-pane: opening the neighbour fills the reading pane
|
|
752
|
-
// beside the list. On a single-pane mobile layout the same navigation
|
|
753
|
-
// replaces the list with a full-screen message, so a bulk delete looks
|
|
754
|
-
// like it opened a random neighbour instead of removing the rows (#202).
|
|
755
|
-
// Mobile keeps the cursor move but stays on the list.
|
|
756
|
-
if (isDesktop) {
|
|
757
|
-
openRow(nextFocus, { replace: true });
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
// Mobile keeps the list up, so it needs its own signal the delete landed
|
|
762
|
-
// (#202). On desktop the rows leaving the list beside the reading pane is
|
|
763
|
-
// signal enough.
|
|
764
|
-
if (!isDesktop) {
|
|
765
|
-
setCompletionBanner(
|
|
766
|
-
bulkActionCompletionText("delete", ids.length, deleteOutcome),
|
|
767
|
-
);
|
|
768
|
-
}
|
|
769
|
-
},
|
|
770
|
-
[
|
|
771
|
-
threads,
|
|
772
|
-
onDeleteMessages,
|
|
773
|
-
exitSelection,
|
|
774
|
-
openRow,
|
|
775
|
-
isDesktop,
|
|
776
|
-
setFocusedMessageId,
|
|
777
|
-
deleteOutcome,
|
|
778
|
-
],
|
|
779
|
-
);
|
|
780
|
-
|
|
781
|
-
// Every way out of the confirmation that isn't the delete — Escape, Cancel,
|
|
782
|
-
// the backdrop — arrives here, so this is the one place the keyboard has to
|
|
783
|
-
// be handed back. Restoring the cursor also puts DOM focus back on that row,
|
|
784
|
-
// via the same pending-focus channel j/k use.
|
|
785
|
-
const handleCancelDelete = useCallback(() => {
|
|
786
|
-
const restoreTo = focusBeforeConfirmRef.current;
|
|
787
|
-
focusBeforeConfirmRef.current = null;
|
|
788
|
-
setPendingDelete(null);
|
|
789
|
-
if (restoreTo === null) return;
|
|
790
|
-
pendingDomFocusRef.current = restoreTo;
|
|
791
|
-
cursorMovedByPointerRef.current = false;
|
|
792
|
-
setFocusedMessageId(restoreTo);
|
|
793
|
-
}, [setFocusedMessageId]);
|
|
794
|
-
|
|
795
|
-
// `MessageList` re-renders on every virtualizer scroll tick. Memoize the
|
|
796
|
-
// guard so we only walk the selected slice when selection or thread
|
|
797
|
-
// identity actually changes.
|
|
798
|
-
const moveDisabledHint = useMemo(
|
|
799
|
-
() => resolveMoveDisabledHint(threads, selectedIds, accountId),
|
|
800
|
-
[accountId, selectedIds, threads],
|
|
801
|
-
);
|
|
802
|
-
|
|
803
|
-
// Organize builds a rule out of clauses, and a search predicate is not a set
|
|
804
|
-
// of clauses — its facets have no `ClauseField`. Over an escalated selection
|
|
805
|
-
// the verb therefore opens the wizard through the search entry instead, on the
|
|
806
|
-
// property step with the query already converted (#477 1.8): the same door the
|
|
807
|
-
// make-filter affordance opens, which the bar hides while rows are ticked. The
|
|
808
|
-
// control stays pressable and lands somewhere that works (#477 1.7) rather
|
|
809
|
-
// than disappearing the moment a selection escalates.
|
|
810
|
-
const organizeSelection = useCallback(() => {
|
|
811
|
-
if (escalatedSelection) {
|
|
812
|
-
startFromSearch();
|
|
813
|
-
return;
|
|
814
|
-
}
|
|
815
|
-
startWizard("organize");
|
|
816
|
-
}, [escalatedSelection, startFromSearch, startWizard]);
|
|
817
|
-
|
|
818
|
-
// Swipe-to-delete single message
|
|
819
|
-
const handleSwipeDelete = useCallback(
|
|
820
|
-
(messageId: string) => {
|
|
821
|
-
onDeleteMessages?.([messageId]);
|
|
822
|
-
},
|
|
823
|
-
[onDeleteMessages],
|
|
824
|
-
);
|
|
825
|
-
|
|
826
|
-
// Swipe-to-toggle-read single message
|
|
827
|
-
const handleSwipeToggleRead = useCallback(
|
|
828
|
-
(messageId: string, currentIsRead: boolean) => {
|
|
829
|
-
toggleReadFor([messageId], !currentIsRead);
|
|
830
|
-
},
|
|
831
|
-
[toggleReadFor],
|
|
832
|
-
);
|
|
833
|
-
|
|
834
|
-
// Mobile: a long press enters multi-select mode by starting a selection —
|
|
835
|
-
// the mode follows from the count, there is no flag to set.
|
|
836
|
-
const handleLongPress = useCallback(
|
|
837
|
-
(messageId: string) => {
|
|
838
|
-
if (!isDesktop) {
|
|
839
|
-
select(messageId);
|
|
840
|
-
}
|
|
841
|
-
},
|
|
842
|
-
[isDesktop, select],
|
|
843
|
-
);
|
|
844
|
-
|
|
845
|
-
// The selection bar's X (both surfaces): means "stop what's happening"
|
|
846
|
-
// throughout, not just "cancel selection" (issue #92 — the review flagged
|
|
847
|
-
// the X reading as ambiguous once a run is going). Counting and a chunked
|
|
848
|
-
// run both stop at the next page boundary; an escalated-but-idle selection
|
|
849
|
-
// drops back to bounded on the way out, same as tapping "Clear selection".
|
|
850
|
-
const handleSelectionCancel = useCallback(() => {
|
|
851
|
-
if (escalation.isRunning || escalation.phase.kind === "counting") {
|
|
852
|
-
escalation.stop();
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
exitSelection();
|
|
856
|
-
}, [escalation, exitSelection]);
|
|
857
|
-
|
|
858
|
-
// The escalation notice's "Clear selection" action: drop back to the
|
|
859
|
-
// bounded (all-loaded) selection without touching selection mode itself.
|
|
860
|
-
const handleClearEscalation = useCallback(() => {
|
|
861
|
-
escalation.clear();
|
|
862
|
-
}, [escalation]);
|
|
863
|
-
|
|
864
|
-
// Scroll the roving focus cursor into view as it moves (j/k). Falls back to
|
|
865
|
-
// the open thread when nothing is focused yet.
|
|
866
|
-
useEffect(() => {
|
|
867
|
-
// A row that took focus from the pointer is already where the user aimed,
|
|
868
|
-
// and scrolling it now would move it out from under the click still in
|
|
869
|
-
// flight (#85).
|
|
870
|
-
if (cursorMovedByPointerRef.current) return;
|
|
871
|
-
// On single-pane tiers, opening a thread swaps this list out for the
|
|
872
|
-
// conversation. Scrolling the list as it unmounts is both pointless (it's
|
|
873
|
-
// no longer visible) and unsafe: @tanstack/react-virtual's scrollToIndex
|
|
874
|
-
// schedules a requestAnimationFrame retry chain on the scroll element's
|
|
875
|
-
// window, which throws once that element (and its window) are gone. Only
|
|
876
|
-
// auto-scroll while the list stays mounted alongside the reading pane.
|
|
877
|
-
if (!isDesktop && selectedMessageId) return;
|
|
878
|
-
const target = focusIndex >= 0 ? focusIndex : currentIndex;
|
|
879
|
-
if (target >= 0) {
|
|
880
|
-
virtualizer.scrollToIndex(target, { align: "auto" });
|
|
881
|
-
}
|
|
882
|
-
}, [focusIndex, currentIndex, virtualizer, isDesktop, selectedMessageId]);
|
|
883
|
-
|
|
884
|
-
// Opening a thread (click or Enter, anywhere) seeds the focus cursor onto it
|
|
885
|
-
// so subsequent j/k continue from the open row — focus and open stay in
|
|
886
|
-
// sync on open while remaining independent during scanning.
|
|
887
|
-
// A row the cursor itself opened is the exception: the cursor was already on
|
|
888
|
-
// it, and if the user has pressed j again since, Enter must act on the row
|
|
889
|
-
// they are on now rather than the one the reading pane caught up to.
|
|
890
|
-
useEffect(() => {
|
|
891
|
-
if (!selectedMessageId) return;
|
|
892
|
-
const openedByCursor = followOpenedRef.current === selectedMessageId;
|
|
893
|
-
followOpenedRef.current = undefined;
|
|
894
|
-
if (openedByCursor) return;
|
|
895
|
-
// A thread going open is the list's own move, whatever opened it — a
|
|
896
|
-
// deep link arrives with the row far down and has to be scrolled to.
|
|
897
|
-
cursorMovedByPointerRef.current = false;
|
|
898
|
-
setFocusedMessageId(selectedMessageId);
|
|
899
|
-
}, [selectedMessageId, setFocusedMessageId]);
|
|
900
|
-
|
|
901
|
-
// Keep the focus cursor valid as the thread list changes (after delete /
|
|
902
|
-
// move / refetch). If the focused row vanished, snap to the nearest
|
|
903
|
-
// surviving row so j/k never dead-ends.
|
|
904
|
-
useEffect(() => {
|
|
905
|
-
if (!focusedMessageId) return;
|
|
906
|
-
if (threads.some((t) => t.messageId === focusedMessageId)) return;
|
|
907
|
-
setFocusedMessageId(threads[0]?.messageId);
|
|
908
|
-
}, [threads, focusedMessageId, setFocusedMessageId]);
|
|
909
|
-
|
|
910
|
-
// Bridge the roving cursor + selection up to the route's global keyboard
|
|
911
|
-
// dispatcher (#429) so the action verbs can target the focused row, or the
|
|
912
|
-
// selection when one exists.
|
|
913
|
-
useEffect(() => {
|
|
914
|
-
onTriageContextChange?.({
|
|
915
|
-
focusedMessageId,
|
|
916
|
-
selectedIds: Array.from(selectedIds),
|
|
917
|
-
hasList: commandsAvailable,
|
|
918
|
-
});
|
|
919
|
-
}, [focusedMessageId, selectedIds, commandsAvailable, onTriageContextChange]);
|
|
920
|
-
|
|
921
|
-
// Retract the context when the list goes away (drafts view, phone reading
|
|
922
|
-
// view). Without this the route keeps its list key handlers registered
|
|
923
|
-
// against a list that no longer exists, and goes on swallowing Enter, Space
|
|
924
|
-
// and ⌘A on a screen that has no rows.
|
|
925
|
-
const bridgeRef = useRef(onTriageContextChange);
|
|
926
|
-
bridgeRef.current = onTriageContextChange;
|
|
927
|
-
useEffect(
|
|
928
|
-
() => () =>
|
|
929
|
-
bridgeRef.current?.({
|
|
930
|
-
focusedMessageId: undefined,
|
|
931
|
-
selectedIds: [],
|
|
932
|
-
hasList: false,
|
|
933
|
-
}),
|
|
934
|
-
[],
|
|
935
|
-
);
|
|
936
|
-
|
|
937
|
-
// Narrow the selection when threads change (e.g., after delete), dropping
|
|
938
|
-
// only the ids that left and keeping every survivor — K-9's
|
|
939
|
-
// `selected.intersect(uniqueIds)`, the reference behavior #92's D2 cites.
|
|
940
|
-
// Wiping the whole selection because one id left (#111) cost the other 49
|
|
941
|
-
// rows on an ordinary refresh.
|
|
942
|
-
// Skipped while an escalated run is active: `selectedIds` there is a stale
|
|
943
|
-
// loaded-rows snapshot from the moment escalation started (the real
|
|
944
|
-
// selection is the predicate, D2), not something a background refetch
|
|
945
|
-
// reshuffling `threads` should be allowed to narrow out from under a count
|
|
946
|
-
// or a run in progress — that would silently exit selection mode mid-run.
|
|
947
|
-
useEffect(() => {
|
|
948
|
-
if (escalation.phase.kind !== "idle" || escalation.isRunning) return;
|
|
949
|
-
intersectWith(threads.map((t) => t.messageId));
|
|
950
|
-
}, [threads, intersectWith, escalation.phase, escalation.isRunning]);
|
|
951
|
-
|
|
952
|
-
// Switching mailboxes exits selection outright, instead of leaving it to the
|
|
953
|
-
// intersect effect above to empty the set by coincidence — a different
|
|
954
|
-
// mailbox's threads happen to share none of the old ids.
|
|
955
|
-
const previousMailboxIdRef = useRef(mailboxId);
|
|
956
|
-
useEffect(() => {
|
|
957
|
-
if (previousMailboxIdRef.current === mailboxId) return;
|
|
958
|
-
previousMailboxIdRef.current = mailboxId;
|
|
959
|
-
exitSelection();
|
|
960
|
-
}, [mailboxId, exitSelection]);
|
|
961
|
-
|
|
962
|
-
// The back gesture (Android's back button, the browser's back) leaves
|
|
963
|
-
// selection mode rather than the route. Only `BACK` is intercepted, so a
|
|
964
|
-
// navigation the app itself starts — opening a message, switching mailboxes
|
|
965
|
-
// — is never blocked, and the blocker is off entirely with nothing selected.
|
|
966
|
-
useBlocker({
|
|
967
|
-
shouldBlockFn: ({ action }) => {
|
|
968
|
-
if (!shouldExitSelectionOnNavigate(action, hasSelection, wizardStep)) {
|
|
969
|
-
return false;
|
|
970
|
-
}
|
|
971
|
-
exitSelection();
|
|
972
|
-
return true;
|
|
973
|
-
},
|
|
974
|
-
enableBeforeUnload: false,
|
|
975
|
-
disabled: !hasSelection || wizardStep !== undefined,
|
|
976
|
-
});
|
|
977
|
-
|
|
978
|
-
// Load more when scrolling near the bottom
|
|
979
|
-
useEffect(() => {
|
|
980
|
-
const scrollElement = parentRef.current;
|
|
981
|
-
if (!scrollElement || !hasMore || !onLoadMore) return;
|
|
982
|
-
|
|
983
|
-
const handleScroll = () => {
|
|
984
|
-
if (isLoadingMore) return;
|
|
985
|
-
|
|
986
|
-
const { scrollTop, scrollHeight, clientHeight } = scrollElement;
|
|
987
|
-
// Trigger when within 200px of the bottom
|
|
988
|
-
const nearBottom = scrollTop + clientHeight >= scrollHeight - 200;
|
|
989
|
-
|
|
990
|
-
if (nearBottom) {
|
|
991
|
-
onLoadMore();
|
|
992
|
-
}
|
|
993
|
-
};
|
|
994
|
-
|
|
995
|
-
scrollElement.addEventListener("scroll", handleScroll, { passive: true });
|
|
996
|
-
// Also check immediately in case we're already at the bottom
|
|
997
|
-
handleScroll();
|
|
998
|
-
|
|
999
|
-
return () => scrollElement.removeEventListener("scroll", handleScroll);
|
|
1000
|
-
}, [hasMore, isLoadingMore, onLoadMore]);
|
|
1001
|
-
|
|
1002
|
-
// Move real DOM focus onto the roving cursor after a keyboard move. The
|
|
1003
|
-
// virtualizer may not have rendered the row yet on the commit that moved the
|
|
1004
|
-
// cursor; the scroll effect above brings it in and this runs again on the
|
|
1005
|
-
// next commit, so the lookup retries until the row exists.
|
|
1006
|
-
useEffect(() => {
|
|
1007
|
-
const messageId = pendingDomFocusRef.current;
|
|
1008
|
-
if (!messageId) return;
|
|
1009
|
-
const row = parentRef.current?.querySelector<HTMLElement>(
|
|
1010
|
-
`[data-message-id="${messageId}"]`,
|
|
1011
|
-
);
|
|
1012
|
-
if (!row) return;
|
|
1013
|
-
pendingDomFocusRef.current = null;
|
|
1014
|
-
row.focus({ preventScroll: true });
|
|
1015
|
-
});
|
|
1016
|
-
|
|
1017
|
-
useEffect(() => {
|
|
1018
|
-
if (!commandsRef) return;
|
|
1019
|
-
if (!commandsAvailable) {
|
|
1020
|
-
commandsRef.current = null;
|
|
1021
|
-
return;
|
|
1022
|
-
}
|
|
1023
|
-
commandsRef.current = {
|
|
1024
|
-
focusNext,
|
|
1025
|
-
focusPrevious,
|
|
1026
|
-
focusFirst,
|
|
1027
|
-
focusLast,
|
|
1028
|
-
openFocused: handleOpenFocused,
|
|
1029
|
-
toggleSelect: toggleFocusedSelection,
|
|
1030
|
-
extendSelectDown: extendRangeDown,
|
|
1031
|
-
extendSelectUp: extendRangeUp,
|
|
1032
|
-
selectAll: handleSelectAll,
|
|
1033
|
-
clearSelection: () => {
|
|
1034
|
-
if (!hasSelection) return false;
|
|
1035
|
-
exitSelection();
|
|
1036
|
-
return true;
|
|
1037
|
-
},
|
|
1038
|
-
requestVerb,
|
|
1039
|
-
toggleDensity,
|
|
1040
|
-
};
|
|
1041
|
-
return () => {
|
|
1042
|
-
commandsRef.current = null;
|
|
1043
|
-
};
|
|
1044
|
-
}, [
|
|
1045
|
-
commandsRef,
|
|
1046
|
-
commandsAvailable,
|
|
1047
|
-
focusNext,
|
|
1048
|
-
focusPrevious,
|
|
1049
|
-
focusFirst,
|
|
1050
|
-
focusLast,
|
|
1051
|
-
handleOpenFocused,
|
|
1052
|
-
toggleFocusedSelection,
|
|
1053
|
-
extendRangeDown,
|
|
1054
|
-
extendRangeUp,
|
|
1055
|
-
handleSelectAll,
|
|
1056
|
-
hasSelection,
|
|
1057
|
-
exitSelection,
|
|
1058
|
-
requestVerb,
|
|
1059
|
-
toggleDensity,
|
|
1060
|
-
]);
|
|
1061
|
-
|
|
1062
|
-
// Derive the MessageListPane listState from the loading/error/empty signals.
|
|
1063
|
-
const listState = isLoading
|
|
1064
|
-
? "loading"
|
|
1065
|
-
: isError
|
|
1066
|
-
? "error"
|
|
1067
|
-
: threads.length === 0
|
|
1068
|
-
? "empty"
|
|
1069
|
-
: "ready";
|
|
1070
|
-
|
|
1071
|
-
// Fail-loud (ux.md): surface the real failure under the error headline, and
|
|
1072
|
-
// give it a place to go — the same GitHub-issue path the bug-report button
|
|
1073
|
-
// uses, so the report carries app version, console errors and the URL.
|
|
1074
|
-
const errorMessage = isError ? formatErrorMessage(error) : undefined;
|
|
1075
|
-
const handleReportError = useCallback(() => {
|
|
1076
|
-
const url = buildGitHubIssueUrl(buildBugReportContext());
|
|
1077
|
-
window.open(url, "_blank", "noopener,noreferrer");
|
|
1078
|
-
}, []);
|
|
1079
|
-
|
|
1080
|
-
// Single flat section — the mailbox view doesn't group by date.
|
|
1081
|
-
const sections = [{ id: "inbox", threads: [] }];
|
|
1082
|
-
|
|
1083
|
-
// Tier one of the two-tier select-all (issue #92, following Gmail web):
|
|
1084
|
-
// every loaded row is checked. Computed against actual membership, not a
|
|
1085
|
-
// count comparison, so a transient mismatch (mid-render, before the
|
|
1086
|
-
// orphaned-selection effect settles) can't read as "all loaded" by
|
|
1087
|
-
// coincidence.
|
|
1088
|
-
const allLoadedSelected =
|
|
1089
|
-
orderedIds.length > 0 && orderedIds.every((id) => selectedIds.has(id));
|
|
1090
|
-
|
|
1091
|
-
// Tier two: offered only once tier one is complete and search has more
|
|
1092
|
-
// matches than are loaded — never a bare "Select all" (requirement 4).
|
|
1093
|
-
const escalationAvailable =
|
|
1094
|
-
escalationEnabled &&
|
|
1095
|
-
hasMore &&
|
|
1096
|
-
allLoadedSelected &&
|
|
1097
|
-
!isDeleting &&
|
|
1098
|
-
!isMoving &&
|
|
1099
|
-
escalation.phase.kind === "idle" &&
|
|
1100
|
-
!escalation.isRunning;
|
|
1101
|
-
|
|
1102
|
-
// The escalation-derived surface state — viewport-independent, fed to both
|
|
1103
|
-
// the mobile sheet and the desktop toolbar so the two never diverge (#212).
|
|
1104
|
-
const selectionIsBusy = isDeleting || isMoving || escalation.isRunning;
|
|
1105
|
-
// A run outlives the selection it came from, and leaving the mailbox and
|
|
1106
|
-
// coming back leaves no selection at all — so while one is in flight the run's
|
|
1107
|
-
// own count is what the bar is about, or the bar would be an empty header over
|
|
1108
|
-
// mail that is still being deleted (#112).
|
|
1109
|
-
const selectionCount =
|
|
1110
|
-
escalation.phase.kind === "escalated"
|
|
1111
|
-
? escalation.phase.total
|
|
1112
|
-
: escalation.progress
|
|
1113
|
-
? escalation.progress.total
|
|
1114
|
-
: selectedCount;
|
|
1115
|
-
|
|
1116
|
-
// A run reports on the bar from the moment it starts, not from its first
|
|
1117
|
-
// finished batch: the wizard invites the user back here mid-run, and a run
|
|
1118
|
-
// with no reading yet is still a run — it is counted against what it was
|
|
1119
|
-
// started with until it has covered something of its own.
|
|
1120
|
-
const selectionStatusLabel = escalation.runningAction
|
|
1121
|
-
? bulkActionProgressLabel(
|
|
1122
|
-
escalation.runningAction.kind,
|
|
1123
|
-
escalation.progress?.done ?? 0,
|
|
1124
|
-
escalation.progress?.total ?? selectionCount,
|
|
1125
|
-
)
|
|
1126
|
-
: escalation.phase.kind === "counting"
|
|
1127
|
-
? "Counting matches…"
|
|
1128
|
-
: escalation.phase.kind === "escalated"
|
|
1129
|
-
? escalatedStatusLabel(searchPredicate ?? {}, escalation.phase.total)
|
|
1130
|
-
: undefined;
|
|
1131
|
-
|
|
1132
|
-
// The select-all-loaded control. The mobile sheet carries it for any bounded
|
|
1133
|
-
// selection; the desktop toolbar only wires it while searching (below), where
|
|
1134
|
-
// escalating past the loaded page is possible.
|
|
1135
|
-
const selectionSelectAll =
|
|
1136
|
-
escalation.phase.kind !== "escalated" && orderedIds.length > 0
|
|
1137
|
-
? {
|
|
1138
|
-
checked: allLoadedSelected,
|
|
1139
|
-
indeterminate: selectedCount > 0 && !allLoadedSelected,
|
|
1140
|
-
onChange: () => toggleAll(orderedIds),
|
|
1141
|
-
}
|
|
1142
|
-
: undefined;
|
|
1143
|
-
|
|
1144
|
-
const selectionProgress = escalation.runningAction
|
|
1145
|
-
? {
|
|
1146
|
-
value: escalation.progress?.done ?? 0,
|
|
1147
|
-
max: escalation.progress?.total ?? selectionCount,
|
|
1148
|
-
tone: bulkActionProgressTone(escalation.runningAction.kind),
|
|
1149
|
-
}
|
|
1150
|
-
: undefined;
|
|
1151
|
-
|
|
1152
|
-
// At most one escalation notice at a time, ranked by how actionable it is:
|
|
1153
|
-
// a run in flight and a count both carry Stop, and that always wins; then an
|
|
1154
|
-
// escalated selection's way out; otherwise a fresh escalation offer. The
|
|
1155
|
-
// (rare) cross-account move hint is layered on behind them below.
|
|
1156
|
-
//
|
|
1157
|
-
// Stop rides on the bar rather than only on the wizard's run screen because
|
|
1158
|
-
// the run outlives both the wizard and the route: a user who comes back to
|
|
1159
|
-
// the mailbox mid-run finds the progress there, and has to be able to end it
|
|
1160
|
-
// from the same place (#112).
|
|
1161
|
-
const escalationNotice =
|
|
1162
|
-
escalation.isRunning || escalation.phase.kind === "counting"
|
|
1163
|
-
? {
|
|
1164
|
-
tone: "info" as const,
|
|
1165
|
-
text: "",
|
|
1166
|
-
action: { label: "Stop", onClick: escalation.stop },
|
|
1167
|
-
}
|
|
1168
|
-
: escalation.phase.kind === "escalated"
|
|
1169
|
-
? {
|
|
1170
|
-
tone: "info" as const,
|
|
1171
|
-
text: "",
|
|
1172
|
-
action: {
|
|
1173
|
-
label: "Clear selection",
|
|
1174
|
-
onClick: handleClearEscalation,
|
|
1175
|
-
},
|
|
1176
|
-
}
|
|
1177
|
-
: escalationAvailable
|
|
1178
|
-
? {
|
|
1179
|
-
tone: "info" as const,
|
|
1180
|
-
text: "",
|
|
1181
|
-
action: {
|
|
1182
|
-
label: escalationActionLabel(searchPredicate ?? {}),
|
|
1183
|
-
onClick: escalation.escalate,
|
|
1184
|
-
},
|
|
1185
|
-
}
|
|
1186
|
-
: undefined;
|
|
1187
|
-
|
|
1188
|
-
// The bar shows one notice at a time, so the cross-account move restriction
|
|
1189
|
-
// rides in behind the escalation states.
|
|
1190
|
-
const selectionNotice =
|
|
1191
|
-
escalationNotice ??
|
|
1192
|
-
(moveDisabledHint
|
|
1193
|
-
? { tone: "warning" as const, text: moveDisabledHint }
|
|
1194
|
-
: undefined);
|
|
1195
|
-
|
|
1196
|
-
// One selection surface at every width, always mounted: it is the list
|
|
1197
|
-
// header. With nothing ticked it names the mailbox and carries the header's
|
|
1198
|
-
// own chrome; from the first ticked row the count and the verbs take that
|
|
1199
|
-
// title's place, and the escalation states (issue #212) — the offer,
|
|
1200
|
-
// counting, the escalated predicate, a chunked run's progress — ride on the
|
|
1201
|
-
// same bar rather than a second one.
|
|
1202
|
-
const activeSelectionBar = (
|
|
1203
|
-
<SelectionTopBar
|
|
1204
|
-
title={listHeaderChrome.title || listTitle}
|
|
1205
|
-
navSlot={listHeaderChrome.navSlot}
|
|
1206
|
-
titleMeta={listHeaderChrome.titleMeta}
|
|
1207
|
-
searchSlot={listHeaderChrome.searchSlot}
|
|
1208
|
-
searchField={listHeaderChrome.searchField}
|
|
1209
|
-
idleSlot={listHeaderChrome.makeFilterSlot}
|
|
1210
|
-
count={selectionCount}
|
|
1211
|
-
onCancel={handleSelectionCancel}
|
|
1212
|
-
onDelete={() => startWizard("delete")}
|
|
1213
|
-
onMove={() => startWizard("move")}
|
|
1214
|
-
onOrganize={organizeSelection}
|
|
1215
|
-
onJunk={junkDestinationId ? () => startWizard("junk") : undefined}
|
|
1216
|
-
onMarkRead={() => startWizard("markRead")}
|
|
1217
|
-
overflowSlot={
|
|
1218
|
-
accountId && mailboxId && selectedCount > 0 && labels.length > 0 ? (
|
|
1219
|
-
<LabelApplyTrigger
|
|
1220
|
-
accountId={accountId}
|
|
1221
|
-
mailboxId={mailboxId}
|
|
1222
|
-
messageIds={Array.from(selectedIds)}
|
|
1223
|
-
/>
|
|
1224
|
-
) : undefined
|
|
1225
|
-
}
|
|
1226
|
-
isBusy={selectionIsBusy}
|
|
1227
|
-
isCounting={escalation.phase.kind === "counting"}
|
|
1228
|
-
selectAll={selectionSelectAll}
|
|
1229
|
-
statusLabel={selectionStatusLabel}
|
|
1230
|
-
progress={selectionProgress}
|
|
1231
|
-
notice={selectionNotice}
|
|
1232
|
-
/>
|
|
1233
|
-
);
|
|
1234
|
-
|
|
1235
|
-
// Roving tabindex: exactly one row is in the tab order, so Tab moves focus
|
|
1236
|
-
// into the list at the cursor and Shift+Tab moves back out to the side panel
|
|
1237
|
-
// instead of walking every row (#43).
|
|
1238
|
-
const tabStopMessageId = tabStopId(orderedIds, focusedMessageId);
|
|
1239
|
-
|
|
1240
|
-
// A row focused by Tab or click becomes the cursor, so the keys act on what
|
|
1241
|
-
// the browser says is focused.
|
|
1242
|
-
const handleRowFocus = useCallback(
|
|
1243
|
-
(messageId: string) => {
|
|
1244
|
-
cursorMovedByPointerRef.current = true;
|
|
1245
|
-
setFocusedMessageId(messageId);
|
|
1246
|
-
},
|
|
1247
|
-
[setFocusedMessageId],
|
|
1248
|
-
);
|
|
1249
|
-
|
|
1250
|
-
// The virtualized list body: rows + search header + load-more indicator.
|
|
1251
|
-
// Passed to MessageListPane as `listBody` so the kit provides the chrome
|
|
1252
|
-
// (pane header, loading / empty / error states, keyboard hints) while we
|
|
1253
|
-
// keep the @tanstack/react-virtual row recycling.
|
|
1254
|
-
const virtualBody = (
|
|
1255
|
-
<>
|
|
1256
|
-
{isSearching && searchQuery && (
|
|
1257
|
-
<ListResultHeader query={searchQuery} count={resultCount} />
|
|
1258
|
-
)}
|
|
1259
|
-
<div
|
|
1260
|
-
ref={parentRef}
|
|
1261
|
-
role="listbox"
|
|
1262
|
-
aria-multiselectable
|
|
1263
|
-
aria-label={listTitle}
|
|
1264
|
-
className="flex-1 overflow-y-auto"
|
|
1265
|
-
>
|
|
1266
|
-
{/* Virtualizer scaffolding — presentational so the listbox sees the
|
|
1267
|
-
rows as its options rather than these positioning wrappers. */}
|
|
1268
|
-
<div
|
|
1269
|
-
role="presentation"
|
|
1270
|
-
className="relative w-full"
|
|
1271
|
-
style={{ height: `${virtualizer.getTotalSize()}px` }}
|
|
1272
|
-
>
|
|
1273
|
-
{virtualizer.getVirtualItems().map((virtualRow) => {
|
|
1274
|
-
const thread = threads[virtualRow.index];
|
|
1275
|
-
return (
|
|
1276
|
-
<div
|
|
1277
|
-
key={virtualRow.key}
|
|
1278
|
-
role="presentation"
|
|
1279
|
-
data-index={virtualRow.index}
|
|
1280
|
-
ref={virtualizer.measureElement}
|
|
1281
|
-
className={cn(
|
|
1282
|
-
"absolute left-0 top-0 w-full border-b border-line",
|
|
1283
|
-
// A chunked/escalated delete keeps every targeted row
|
|
1284
|
-
// checked, dimmed and untappable for the whole run (issue
|
|
1285
|
-
// #92) — the number in the bar and the rows underneath
|
|
1286
|
-
// have to agree something is happening, and a row mid
|
|
1287
|
-
// -delete must not be openable.
|
|
1288
|
-
escalation.isRunning && "pointer-events-none opacity-50",
|
|
1289
|
-
)}
|
|
1290
|
-
style={{ transform: `translateY(${virtualRow.start}px)` }}
|
|
1291
|
-
>
|
|
1292
|
-
<SwipeableMessageRow
|
|
1293
|
-
thread={thread}
|
|
1294
|
-
mailboxId={mailboxId}
|
|
1295
|
-
isSelected={selectedMessageId === thread.messageId}
|
|
1296
|
-
isFocused={focusedMessageId === thread.messageId}
|
|
1297
|
-
isTabStop={tabStopMessageId === thread.messageId}
|
|
1298
|
-
onFocusRow={handleRowFocus}
|
|
1299
|
-
isChecked={isChecked(thread.messageId)}
|
|
1300
|
-
onToggleCheck={toggleCheck}
|
|
1301
|
-
onRowSelect={handleRowSelect}
|
|
1302
|
-
isMultiSelectMode={isMultiSelectMode}
|
|
1303
|
-
onLongPress={handleLongPress}
|
|
1304
|
-
isDesktop={isDesktop}
|
|
1305
|
-
onDelete={handleSwipeDelete}
|
|
1306
|
-
onToggleRead={handleSwipeToggleRead}
|
|
1307
|
-
density={density}
|
|
1308
|
-
/>
|
|
1309
|
-
</div>
|
|
1310
|
-
);
|
|
1311
|
-
})}
|
|
1312
|
-
</div>
|
|
1313
|
-
{isLoadingMore && <MessageListLoadingMore />}
|
|
1314
|
-
</div>
|
|
1315
|
-
</>
|
|
1316
|
-
);
|
|
1317
|
-
|
|
1318
|
-
return (
|
|
1319
|
-
<>
|
|
1320
|
-
{completionBanner && !isDesktop && (
|
|
1321
|
-
<Banner
|
|
1322
|
-
tone="success"
|
|
1323
|
-
variant="soft"
|
|
1324
|
-
className="m-2 rounded-md"
|
|
1325
|
-
onDismiss={() => setCompletionBanner(null)}
|
|
1326
|
-
>
|
|
1327
|
-
{completionBanner}
|
|
1328
|
-
</Banner>
|
|
1329
|
-
)}
|
|
1330
|
-
<MessageListPane
|
|
1331
|
-
listTitle={listTitle}
|
|
1332
|
-
listMeta={listMeta}
|
|
1333
|
-
sections={sections}
|
|
1334
|
-
flatList
|
|
1335
|
-
// The results panel is a body, not a list state: it stands in for the
|
|
1336
|
-
// rows and must not fall behind a skeleton while the query re-keys.
|
|
1337
|
-
listState={listHeaderChrome.searchResults ? "ready" : listState}
|
|
1338
|
-
searchQuery={listSearchText}
|
|
1339
|
-
listFilter={listFilter}
|
|
1340
|
-
listScopeLabel={listScopeLabel}
|
|
1341
|
-
errorMessage={errorMessage}
|
|
1342
|
-
onRetry={onRetry}
|
|
1343
|
-
onReportError={handleReportError}
|
|
1344
|
-
density={density}
|
|
1345
|
-
selectedThreadId={selectedMessageId}
|
|
1346
|
-
onSelectThread={(id) => openRow(id)}
|
|
1347
|
-
isDesktop={isDesktop}
|
|
1348
|
-
hideHeader={hideHeader}
|
|
1349
|
-
selectionBar={activeSelectionBar}
|
|
1350
|
-
listBody={
|
|
1351
|
-
listHeaderChrome.searchResults ??
|
|
1352
|
-
(listState === "ready" ? virtualBody : undefined)
|
|
1353
|
-
}
|
|
1354
|
-
/>
|
|
1355
|
-
<DeleteConfirmDialog
|
|
1356
|
-
isOpen={pendingDelete !== null}
|
|
1357
|
-
messageIds={pendingDelete ?? []}
|
|
1358
|
-
outcome={deleteOutcome}
|
|
1359
|
-
accountId={accountId}
|
|
1360
|
-
// Every row here is filed in the open mailbox, so on an expunge that
|
|
1361
|
-
// mailbox is the Trash the copy has to name.
|
|
1362
|
-
trashFolderLabel={listTitle}
|
|
1363
|
-
staleFolderLabel={staleFolderLabel}
|
|
1364
|
-
guessedMailboxId={guessedMailboxId}
|
|
1365
|
-
isDeleting={isDeleting}
|
|
1366
|
-
onConfirm={handleConfirmDelete}
|
|
1367
|
-
onCancel={handleCancelDelete}
|
|
1368
|
-
/>
|
|
1369
|
-
<SelectionWizardHost
|
|
1370
|
-
verb={wizardVerb}
|
|
1371
|
-
accountId={accountId}
|
|
1372
|
-
mailboxId={mailboxId}
|
|
1373
|
-
mailboxLabel={listTitle}
|
|
1374
|
-
selection={wizardSelection}
|
|
1375
|
-
selectionRestriction={moveDisabledHint ? "spansAccounts" : undefined}
|
|
1376
|
-
escalated={escalatedSelection}
|
|
1377
|
-
escalatedProgress={escalation.progress}
|
|
1378
|
-
onFinished={exitSelection}
|
|
1379
|
-
onRunEnded={reportRunOutcome}
|
|
1380
|
-
/>
|
|
1381
|
-
</>
|
|
1382
|
-
);
|
|
1383
|
-
};
|