@nocobase/app-plugin-mail 1.0.0-beta.11 → 1.0.0-beta.13

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.
Files changed (122) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +35 -2
  3. package/dist/client/components/mail-account-connector.d.ts +1 -0
  4. package/dist/client/components/mail-account-connector.d.ts.map +1 -1
  5. package/dist/client/components/mail-account-connector.js +4 -3
  6. package/dist/client/components/mail-account-connector.js.map +1 -1
  7. package/dist/client/components/mail-navigation-icon.d.ts.map +1 -1
  8. package/dist/client/components/mail-navigation-icon.js +3 -50
  9. package/dist/client/components/mail-navigation-icon.js.map +1 -1
  10. package/dist/client/components/public.d.ts +1 -1
  11. package/dist/client/components/public.d.ts.map +1 -1
  12. package/dist/client/components/public.js.map +1 -1
  13. package/dist/client/components/ui/field.d.ts +7 -0
  14. package/dist/client/components/ui/field.d.ts.map +1 -0
  15. package/dist/client/components/ui/field.js +20 -0
  16. package/dist/client/components/ui/field.js.map +1 -0
  17. package/dist/client/contracts/composer.d.ts +29 -2
  18. package/dist/client/contracts/composer.d.ts.map +1 -1
  19. package/dist/client/contracts/composer.js.map +1 -1
  20. package/dist/client/hooks/use-mail-composer.d.ts +1 -1
  21. package/dist/client/hooks/use-mail-composer.d.ts.map +1 -1
  22. package/dist/client/hooks/use-mail-composer.js +54 -10
  23. package/dist/client/hooks/use-mail-composer.js.map +1 -1
  24. package/dist/client/hooks/use-mail-unread-count.d.ts +13 -0
  25. package/dist/client/hooks/use-mail-unread-count.d.ts.map +1 -0
  26. package/dist/client/hooks/use-mail-unread-count.js +106 -0
  27. package/dist/client/hooks/use-mail-unread-count.js.map +1 -0
  28. package/dist/client/hooks/use-mail-workspace-data.d.ts +3 -1
  29. package/dist/client/hooks/use-mail-workspace-data.d.ts.map +1 -1
  30. package/dist/client/hooks/use-mail-workspace-data.js +14 -2
  31. package/dist/client/hooks/use-mail-workspace-data.js.map +1 -1
  32. package/dist/client/index.d.ts +3 -0
  33. package/dist/client/index.d.ts.map +1 -1
  34. package/dist/client/index.js +2 -0
  35. package/dist/client/index.js.map +1 -1
  36. package/dist/client/lib/mail-composer-completion.d.ts +5 -0
  37. package/dist/client/lib/mail-composer-completion.d.ts.map +1 -0
  38. package/dist/client/lib/mail-composer-completion.js +28 -0
  39. package/dist/client/lib/mail-composer-completion.js.map +1 -0
  40. package/dist/client/locales/en-US.d.ts +4 -0
  41. package/dist/client/locales/en-US.d.ts.map +1 -1
  42. package/dist/client/locales/en-US.js +7 -3
  43. package/dist/client/locales/en-US.js.map +1 -1
  44. package/dist/client/locales/zh-CN.d.ts.map +1 -1
  45. package/dist/client/locales/zh-CN.js +6 -2
  46. package/dist/client/locales/zh-CN.js.map +1 -1
  47. package/dist/client/mail-client.d.ts +5 -1
  48. package/dist/client/mail-client.d.ts.map +1 -1
  49. package/dist/client/mail-client.js.map +1 -1
  50. package/dist/client/pages/mail-accounts-page.d.ts.map +1 -1
  51. package/dist/client/pages/mail-accounts-page.js +4 -1
  52. package/dist/client/pages/mail-accounts-page.js.map +1 -1
  53. package/dist/client/pages/mail-workspace-page.d.ts +4 -2
  54. package/dist/client/pages/mail-workspace-page.d.ts.map +1 -1
  55. package/dist/client/pages/mail-workspace-page.js +253 -173
  56. package/dist/client/pages/mail-workspace-page.js.map +1 -1
  57. package/dist/client/prepare-mail-reply.d.ts +9 -0
  58. package/dist/client/prepare-mail-reply.d.ts.map +1 -0
  59. package/dist/client/prepare-mail-reply.js +28 -0
  60. package/dist/client/prepare-mail-reply.js.map +1 -0
  61. package/dist/database/migrations/.manifest.json +6 -2
  62. package/dist/database/migrations/202609030001_create_mail_tables.d.ts.map +1 -1
  63. package/dist/database/migrations/202609030001_create_mail_tables.js +8 -4
  64. package/dist/database/migrations/202609030001_create_mail_tables.js.map +1 -1
  65. package/dist/database/migrations/202610090001_mail_create_message_participants.d.ts +4 -0
  66. package/dist/database/migrations/202610090001_mail_create_message_participants.d.ts.map +1 -0
  67. package/dist/database/migrations/202610090001_mail_create_message_participants.js +167 -0
  68. package/dist/database/migrations/202610090001_mail_create_message_participants.js.map +1 -0
  69. package/dist/server/config.d.ts +1 -1
  70. package/dist/server/config.d.ts.map +1 -1
  71. package/dist/server/config.js +17 -9
  72. package/dist/server/config.js.map +1 -1
  73. package/dist/server/locales/en-US.d.ts +1 -0
  74. package/dist/server/locales/en-US.d.ts.map +1 -1
  75. package/dist/server/locales/en-US.js +1 -0
  76. package/dist/server/locales/en-US.js.map +1 -1
  77. package/dist/server/locales/zh-CN.d.ts.map +1 -1
  78. package/dist/server/locales/zh-CN.js +1 -0
  79. package/dist/server/locales/zh-CN.js.map +1 -1
  80. package/dist/server/providers/mail-core.d.ts +2 -0
  81. package/dist/server/providers/mail-core.d.ts.map +1 -1
  82. package/dist/server/providers/mail-core.js +39 -1
  83. package/dist/server/providers/mail-core.js.map +1 -1
  84. package/dist/server/routes/api.d.ts.map +1 -1
  85. package/dist/server/routes/api.js +6 -2
  86. package/dist/server/routes/api.js.map +1 -1
  87. package/dist/server/routes/schemas.d.ts +2 -0
  88. package/dist/server/routes/schemas.d.ts.map +1 -1
  89. package/dist/server/routes/schemas.js +13 -0
  90. package/dist/server/routes/schemas.js.map +1 -1
  91. package/dist/server/services/authorization.js +1 -1
  92. package/dist/server/services/authorization.js.map +1 -1
  93. package/dist/server/store/account-removals.d.ts.map +1 -1
  94. package/dist/server/store/account-removals.js +6 -0
  95. package/dist/server/store/account-removals.js.map +1 -1
  96. package/dist/server/store/draft-states.d.ts.map +1 -1
  97. package/dist/server/store/draft-states.js +2 -0
  98. package/dist/server/store/draft-states.js.map +1 -1
  99. package/dist/server/store/message-participants.d.ts +25 -0
  100. package/dist/server/store/message-participants.d.ts.map +1 -0
  101. package/dist/server/store/message-participants.js +109 -0
  102. package/dist/server/store/message-participants.js.map +1 -0
  103. package/dist/server/store/message-writes.d.ts.map +1 -1
  104. package/dist/server/store/message-writes.js +3 -0
  105. package/dist/server/store/message-writes.js.map +1 -1
  106. package/dist/server/store/messages.d.ts.map +1 -1
  107. package/dist/server/store/messages.js +15 -0
  108. package/dist/server/store/messages.js.map +1 -1
  109. package/dist/shared/mail.d.ts +3 -1
  110. package/dist/shared/mail.d.ts.map +1 -1
  111. package/dist/shared/mail.js.map +1 -1
  112. package/dist/shared/participant.d.ts +14 -0
  113. package/dist/shared/participant.d.ts.map +1 -0
  114. package/dist/shared/participant.js +45 -0
  115. package/dist/shared/participant.js.map +1 -0
  116. package/package.json +10 -7
  117. package/skills/nocobase-app-plugin-mail/SKILL.md +9 -7
  118. package/skills/nocobase-app-plugin-mail/references/client-integration.md +125 -1
  119. package/skills/nocobase-app-plugin-mail/references/configuration-and-accounts.md +10 -4
  120. package/skills/nocobase-app-plugin-mail/references/http-api.md +32 -24
  121. package/skills/nocobase-app-plugin-mail/references/public-api.md +27 -20
  122. package/skills/nocobase-app-plugin-mail/references/synchronization-and-diagnostics.md +14 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @nocobase/app-plugin-mail
2
2
 
3
+ ## 1.0.0-beta.13
4
+
5
+ ### Minor Changes
6
+
7
+ - f675e8d: Add an optional participant filter to personal and managed message lists, public client query types and the Mail workspace. Full email addresses and @domain values match exact trimmed, lowercased From/To/Cc addresses; Bcc, Reply-To, display names and message content are excluded. Existing q keyword search, ownership boundaries, full conversation details and thread counts remain unchanged.
8
+
9
+ Add the internal mailMessageParticipants schema and backfill historical addresses from stored sender/recipient JSON. Existing installations must use a maintenance window: back up the database, stop application writes and Mail synchronization/background workers, deploy and apply the migration, verify the complete historical backfill, then restart. Bounded reads and inserts limit memory and SQL parameters, not transaction duration or locks; this is not an online backfill. Measure mailbox size, migration time, lock/log impact and additional participant-row/index storage and write cost before upgrading. Invalid or unsupported historical addresses are skipped without truncating or rewriting original mail data.
10
+
11
+ This release also corrects the released `202609030001_create_mail_tables` migration, which could never install on MySQL with utf8mb4 because two full unique indexes exceeded the 3072-byte key limit, or on SQL Server because signatures and message-folder links had duplicate account cascade paths. Fresh installations retain account foreign-key checks without a second direct cascade for those descendants; their identity/message parents still own cascading deletion. Fresh installs use an outbound storage-key limit of 667 characters (generated keys are 50 characters) and a provider subscription-ID limit of 412 characters, keeping each composite key within the limit. Existing successfully migrated databases are not resized or truncated. Operators of those installations should expect a checksum warning on the next `nocobase db apply`; review this correction and acknowledge it with `nocobase db repair` before proceeding.
12
+
13
+ Cross-database regression fixtures now use valid local UUIDs without changing provider identifiers or search behavior.
14
+
15
+ ## 1.0.0-beta.12
16
+
17
+ ### Patch Changes
18
+
19
+ - 2a54505: Add optional fourth-argument completion details to MailComposer and MailWorkspaceComposer, preserving existing callback arguments. Details include every submission returned by that operation and a detached snapshot of the actual client request, or a separate saved-draft reference. Preserve pending, scheduled, failed and unknown statuses; a transport failure without a response has no submission IDs. Support asynchronous completion callbacks and isolate integration errors through optional onCompletionError without delaying closing, changing the send outcome or retrying mail. Business integrations should associate and deduplicate by submission ID rather than querying the latest sending record; this client callback is not a durable delivery event.
20
+ - 2a54505: Align the email address and optional login name inputs in the IMAP/SMTP account connection form. Keep helper text beneath the login name without stretching neighboring field grids, while preserving the stacked narrow-screen layout.
21
+
22
+ Use consistent Chinese optional-field wording for the login name and sender name in the account connection form.
23
+
24
+ - 2a54505: Show specific English and Chinese guidance when a mail provider rejects account credentials, including checking the login name, password or authorization code, IMAP/SMTP access, and app-password requirements. Preserve the existing error reason and field violations without changing the connection form.
25
+ - 2a54505: Clarify the IMAP/SMTP Username as an optional login name with persistent help text in English and Chinese. Default omitted or blank login names to the mailbox address on the server, and trim explicit names without changing their case.
26
+ - 2a54505: Expose the application's resolved `NODE_ENV` to server providers without inheriting an embedded application's host process environment. Mail now warns once during production startup when its effective OAuth return URL still points to the legacy `/dev/mail/accounts` destination. The current root (`/`) default does not trigger the warning or register an account route: applications must register their own authenticated personal account page and configure `mail.oauthReturnUrl` to that page. This warning does not block startup, change configuration, or verify arbitrary client routes.
27
+ - 2a54505: Expose `prepareMailReply` and `MailComposerRequest` from the public client entry so custom pages can share the workspace's complete reply preparation, including incomplete-content loading and referenced inline-image uploads. Preserve existing recipient, subject, reply association and draft behavior. The browser-only helper does not open, save or send mail; callers retain loading, error and composer-session guards.
28
+ - 2a54505: Expose `useMailUnreadCount` and `MailUnreadCountState` from the public client entry for custom menus, and reuse the Hook in the navigation icon. Preserve current-user count semantics, local/realtime/reconnect/focus refresh, polling, debounce and serialized requests. The Hook distinguishes an unknown initial count from zero, retains the last successful count on refresh failure, and exposes loading/error state. Consumers must remount with session changes; separate Hook instances fetch independently without a global cache.
29
+ - 2a54505: Adapt the mail workspace to its available width: retain the three-column desktop view, show the message list or conversation on narrow screens, and provide mailbox navigation in a keyboard-accessible drawer. Returning to the list preserves its page and scroll position and ignores stale conversation responses.
30
+ - 2a54505: Compose all seven MAIL_* environment mappings with the Mail configuration section and preserve them in the examples application. Keep the legacy fully prefixed application-level mappings compatible. Deployment environment values now override configuration files and code defaults automatically: review existing OAuth, sync, webhook and jobs variables before upgrading, including empty or invalid integers. Applications with custom parsers must retain or override the section rules explicitly; calling the defaults factory alone does not inherit them. Mail server configuration and webhook secrets remain outside public browser configuration.
31
+ - 2a54505: Add optional accountsHref and headerActions to MailWorkspacePage. Applications can link the empty and populated workspace to their own personal account page and append actions without replacing Compose or Sync. The public MailAccountsPage remains available for application-owned personal account routes; the plugin registers no built-in Dev, settings or management pages or routes. Applications must register and authorize their account page and configure mail.oauthReturnUrl separately to their account page; the current default returns to the application's root.
32
+ - Updated dependencies [2a54505]
33
+ - @nocobase/app-server@2.0.0-beta.5
34
+ - @nocobase/app-plugin-authentication@2.0.0-beta.7
35
+
3
36
  ## 1.0.0-beta.11
4
37
 
5
38
  ### Patch Changes
package/README.md CHANGED
@@ -24,22 +24,55 @@ import mail from './mail.js';
24
24
  // Add `mail: ReturnType<typeof mail>;` to the default config type and `mail,` to defaultAppConfigs({ ... }).
25
25
  ```
26
26
 
27
- The plugin can start with built-in defaults when this namespace is absent, but no external Mail provider is available until the application configures one. Keep provider credentials in private server configuration. If the application uses Mail environment overrides, merge the exported `mailEnvironmentMappings` into the application's environment mappings in `server/environment.ts`. The package metadata lists the supported variables, but applications must explicitly map them for the overrides to take effect.
27
+ Register that factory under the `mail` key in the application's `defaultAppConfigs()` composition. The plugin uses built-in defaults when the namespace is absent, but no external Mail provider is available until the application configures one. Keep provider credentials in private server configuration. `mailConfig` declares all seven `MAIL_*` overrides as section-relative environment rules; composing it makes them effective and discoverable with `pnpm nocobase config env`. The legacy `mailEnvironmentMappings` export retains fully prefixed paths for application-level environment providers; do not pass it as a section's `env`.
28
28
 
29
29
  For Gmail, `mail.providers.<name>.quota` can override per-user and per-project quota pacing using the allocation shown in Google Cloud; otherwise the plugin uses conservative defaults with headroom. Account creation requires an initial-sync date, and the account screen defaults it to one calendar month ago. Direct initial-sync requests must also provide a date boundary. See the Mail Skill references for configuration and quota details.
30
30
 
31
31
  ## Supported integration surface
32
32
 
33
- Import the server plugin and service contracts from `@nocobase/app-plugin-mail/server`, the client plugin and `MailWorkspacePage` from `@nocobase/app-plugin-mail/client`, and reusable UI from `@nocobase/app-plugin-mail/client/components`. The package root is a Server alias; new application code should use the explicit `/server` path. `MailClient` and `mailClientToken` are the supported Client data access layer; `mailServiceToken` is the supported in-process Server facade. Do not import implementation files, persistence contracts, internal service tokens, or route contribution modules. See the [public API inventory](skills/nocobase-app-plugin-mail/references/public-api.md) for the exported names and responsibility of each entry.
33
+ Import the server plugin and service contracts from `@nocobase/app-plugin-mail/server`, the client plugin, `MailWorkspacePage` and `MailAccountsPage` from `@nocobase/app-plugin-mail/client`, and reusable UI from `@nocobase/app-plugin-mail/client/components`. The package root is a Server alias; new application code should use the explicit `/server` path. `MailClient` and `mailClientToken` are the supported Client data access layer; `mailServiceToken` is the supported in-process Server facade. Do not import implementation files, persistence contracts, internal service tokens, or route contribution modules. See the [public API inventory](skills/nocobase-app-plugin-mail/references/public-api.md) for the exported names and responsibility of each entry.
34
34
 
35
35
  The supported reusable UI exports `MailAccountCard`, `MailAccountConnector`, `MailConversationView`, `MailMessageList`, `MailProviderCard`, `MailRichTextEditor`, `MailNavigationIcon`, `MailLabelManager`, `MailLabelTag`, `MailLabelColorDot`, `MailSignatureManager`, `MailStatusBadge`, `MailSyncPolicyFields`, `MailTemplateManager`, `MailboxSidebar`, `MailComposer`, and `MailWorkspaceComposer`, together with their exported props and state types. `MailComposer` renders one supplied compose request; `MailWorkspaceComposer` additionally coordinates sendable identities across accounts. Register the Mail Client plugin before rendering components that use `useMailClient()`.
36
36
 
37
+ Custom menus can use `useMailUnreadCount()` and `MailUnreadCountState` from `/client` to share the navigation icon's current-user fetching, invalidation and polling logic. Unknown counts stay `undefined`, background failures retain the last successful count, and the Hook exposes loading/error state without changing the built-in badge appearance. Mount consumers in a session-owned scope that remounts on user changes; instances fetch independently rather than using a global cache. See [custom unread menus](skills/nocobase-app-plugin-mail/references/client-integration.md#unread-counts-on-custom-menus) for host-context prerequisites, refresh semantics and lifecycle boundaries.
38
+
39
+ Composer completion preserves its existing three arguments and adds optional `MailComposerCompletionDetails` as the fourth: exact per-operation submissions and a detached client-request snapshot, or a separate draft reference. Associate business activity by submission ID, not the latest history row, and preserve each record's real status. Async completion errors are isolated and may be handled with `onCompletionError`; the composer does not wait for business persistence to close. See [client integration](skills/nocobase-app-plugin-mail/references/client-integration.md#associate-composer-completion-with-business-records) for unknown outcomes, drafts, bulk sends and reliability limits.
40
+
41
+ For a production workspace, register an application-owned personal account route rendering the public `MailAccountsPage`, pass its path (without the deployment prefix) as `MailWorkspacePage.accountsHref`, and configure `mail.oauthReturnUrl` separately to the same page. The empty workspace shows a connection link and the populated workspace keeps an account-management link; without `accountsHref` it invents no route. Optional `headerActions` append application actions without replacing Compose or Sync. See the [client integration guide](skills/nocobase-app-plugin-mail/references/client-integration.md) for authentication and permission wiring.
42
+
43
+ The plugin registers no built-in Dev, settings or management pages or routes; applications own their Mail pages. `mail.oauthReturnUrl` defaults to the application's root (`/`), not an account page. Register an application-owned, authenticated personal account page with `page / mail.workspace / access` permission and configure the return URL to that page. Production startup warns once only when the effective return URL targets the legacy `/dev/mail/accounts` destination, including prefixed and absolute forms; the current default does not trigger that warning. The warning does not block startup, change configuration or verify arbitrary application routes. An application-owned administrator overview using the read-only all-user APIs is not a substitute for personal connection. Application runtime environment checks use `app.nodeEnv`, including embedded apps with an environment distinct from their host.
44
+
37
45
  Other Server plugins may register custom providers through `mailProviderRegistryToken` and `MailProviderDefinition`. `createMailProviderRegistry()` creates a standalone registry for tests or isolated integrations; applications should extend the registry supplied by Mail Core. Provider capability records may contain capabilities unknown to this Mail version; Mail does not use unknown keys to enable built-in operations, and treats missing known capabilities as unsupported. Client UIs should tolerate unknown capability keys. A custom `MailCredentialVault` may be registered through `mailCredentialVaultToken` before Mail Core initializes when an application needs its own credential storage.
38
46
 
39
47
  `MailClient` is the preferred integration with Mail's HTTP API. The [HTTP API reference](skills/nocobase-app-plugin-mail/references/http-api.md) lists the `/api/mail` paths, request and response shapes, error codes, permission resources, realtime event, OAuth callback, and Provider webhook contracts. OAuth callbacks and Provider webhooks are protocol endpoints rather than general application APIs. A running application also serves the `/api/mail` routes in its OpenAPI document, at `/api/swagger/docs` (Swagger UI) and `/api/swagger` (JSON), for a signed-in user or an API key.
40
48
 
41
49
  Within a major version, existing public exports, required props, request fields, response meanings, error codes, permissions, and event semantics remain compatible. Additive fields and capabilities must be optional or safely ignored by older consumers. Removing or changing a public contract requires a new major version and a migration note.
42
50
 
51
+ ## Exact participant filtering
52
+
53
+ The workspace's independent **Participant** field and the optional `participant` in `MailMessagesQuery` and `MailManagedMessagesQuery` match actual From, To and Cc addresses. CRM pages can use the app-owned Mail client without changing keyword search:
54
+
55
+ ```ts
56
+ const correspondence = await mail.listMessages({
57
+ participant: 'alice@example.com',
58
+ });
59
+ const companyMail = await mail.listMessages({ participant: '@example.com' });
60
+ ```
61
+
62
+ Matching trims surrounding whitespace and lowercases the entire address or domain, then compares exactly. `@example.com` matches that domain only, not subdomains, lookalike domains or suffixes. Supported input is an ASCII dot-atom mailbox or `@` followed by a dotted DNS domain; display-name forms, quoted local parts and Unicode addresses are not supported. Aliases and `+tag` addresses are not folded. Subject, preview, body, display names, Bcc and Reply-To are excluded. `q` keeps its existing fuzzy subject/preview/sender/recipient search (including display names and Bcc); combining it with `participant` and other filters takes their intersection. Filtering is local to synchronized mail and never widens ownership or management permissions.
63
+
64
+ Omit `participant` to clear it; an explicitly empty, malformed or oversized API value returns `400 INVALID_INPUT` with a `participant` field violation. The client forwards supplied values unchanged. The workspace validates and debounces participant changes, clearing selection and pagination immediately and ignoring old responses; invalid input cannot fall back to an unfiltered request. The filter affects list totals and pagination, not complete conversation details or existing full-thread counts. IMAP folder copies retain their existing record granularity.
65
+
66
+ ## Upgrading the participant index
67
+
68
+ This feature adds an internal `mailMessageParticipants` schema and backfills existing From/To/Cc from stored sender/recipient JSON, without fetching provider history or rewriting original messages. Invalid or unsupported historical addresses are skipped, not truncated; other valid addresses on the same message are still indexed. The index is derived data, not a public CRUD resource.
69
+
70
+ Plan a maintenance window: measure representative and large mailboxes, back up the database, stop application writes and all Mail sync/background workers, deploy the new version and run the application's `nocobase db apply`, verify migration completion and known historical address/domain queries, then restart the application and workers. Do not expose participant results before the complete backfill is verified. Reading and inserting bounded batches limits memory and SQL parameters, not transaction duration or lock time: this is **not an online backfill**. Additional participant rows/indexes increase storage and write cost; measure migration time, locks and transaction-log space before deployment. If the measured mailbox scale does not fit the window, postpone deployment for a separately designed resumable backfill, rather than running this migration alongside writes. See [upgrade verification](skills/nocobase-app-plugin-mail/references/synchronization-and-diagnostics.md#participant-index-upgrade) for the operational checklist.
71
+
72
+ This release also corrects two over-wide unique indexes in the released `202609030001_create_mail_tables` migration that prevented MySQL installations with utf8mb4, and duplicate account cascade paths that prevented SQL Server installations. New signature/message-folder tables retain account checks without a second direct cascade; identity/message deletion still cascades to their descendants. Existing successful installations keep their original columns and data; expect a checksum warning on `nocobase db apply`, review the correction and acknowledge it with `nocobase db repair`. Fresh installations use a 667-character outbound storage-key bound and a 412-character provider subscription-ID bound, retaining full unique indexes within MySQL's key limit.
73
+
74
+ See the [acceptance scope and evidence](docs/participant-filter-acceptance.md) and [scale verification](docs/participant-filter-verification.md) for the checked behavior, database coverage and operational limitations.
75
+
43
76
  ## Agent integration
44
77
 
45
78
  The package ships `skills/nocobase-app-plugin-mail/` for application agents. Keep this Skill and its references synchronized with the installed package version; it contains the integration contract, safety gates, provider boundaries, and validation workflow.
@@ -10,6 +10,7 @@ export interface MailAccountConnectorLabels {
10
10
  readonly configurationRequired: string;
11
11
  readonly emailAddress?: string;
12
12
  readonly username?: string;
13
+ readonly usernameDescription?: string;
13
14
  readonly password?: string;
14
15
  readonly displayName?: string;
15
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mail-account-connector.d.ts","sourceRoot":"","sources":["../../../client/components/mail-account-connector.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAK1D,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtD,QAAQ,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IACpD,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAChD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,IAAI,CAChC,sBAAsB,EACtB,UAAU,GAAG,UAAU,CACxB,CAAC;IACF,QAAQ,CAAC,qBAAqB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,MAAM,CAAC;IACvE,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAC9B,QAAQ,EAAE,gBAAgB,EAC1B,WAAW,EAAE,sBAAsB,KAChC,IAAI,CAAC;CACX;AAED,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,MAAM,EACN,SAAS,EACT,oBAAoB,GACrB,EAAE,yBAAyB,GAAG,YAAY,CAmJ1C"}
1
+ {"version":3,"file":"mail-account-connector.d.ts","sourceRoot":"","sources":["../../../client/components/mail-account-connector.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAK1D,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtD,QAAQ,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IACpD,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAChD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,IAAI,CAChC,sBAAsB,EACtB,UAAU,GAAG,UAAU,CACxB,CAAC;IACF,QAAQ,CAAC,qBAAqB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,MAAM,CAAC;IACvE,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAC9B,QAAQ,EAAE,gBAAgB,EAC1B,WAAW,EAAE,sBAAsB,KAChC,IAAI,CAAC;CACX;AAED,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,MAAM,EACN,SAAS,EACT,oBAAoB,GACrB,EAAE,yBAAyB,GAAG,YAAY,CA6J1C"}
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Link2 } from 'lucide-react';
3
- import { useMemo, useState } from 'react';
3
+ import { useId, useMemo, useState } from 'react';
4
4
  import { Button } from './ui/button.js';
5
5
  import { Input } from './ui/input.js';
6
6
  import { NativeSelect } from './ui/native-select.js';
7
7
  export function MailAccountConnector({ providers, credentialDefaults, connectedAccountCount, connectingProviderName, labels, onConnect, onConnectCredentials, }) {
8
+ const usernameDescriptionId = useId();
8
9
  const [selectedKey, setSelectedKey] = useState('');
9
10
  const [address, setAddress] = useState('');
10
11
  const [username, setUsername] = useState(credentialDefaults?.username ?? '');
@@ -21,7 +22,6 @@ export function MailAccountConnector({ providers, credentialDefaults, connectedA
21
22
  : [];
22
23
  const usesCredentials = selectedProvider?.connection === 'credentials';
23
24
  const credentialsReady = address.trim().length > 0 &&
24
- username.trim().length > 0 &&
25
25
  password.length > 0 &&
26
26
  onConnectCredentials !== undefined;
27
27
  return (_jsxs("div", { className: 'space-y-4', children: [_jsxs("div", { className: 'grid gap-3 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-end', children: [_jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.accountType }), _jsxs(NativeSelect, { onChange: (event) => {
@@ -49,7 +49,8 @@ export function MailAccountConnector({ providers, credentialDefaults, connectedA
49
49
  else {
50
50
  onConnect(selectedProvider);
51
51
  }
52
- }, children: [_jsx(Link2, { "aria-hidden": 'true', className: 'size-4' }), connecting ? labels.connecting : labels.connect] })] }), usesCredentials && providerConfigured ? (_jsxs("div", { className: 'grid gap-3 sm:grid-cols-2', children: [_jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.emailAddress ?? 'Email address' }), _jsx(Input, { autoComplete: 'email', onChange: (event) => setAddress(event.target.value), value: address })] }), _jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.username ?? 'Username' }), _jsx(Input, { autoComplete: 'username', onChange: (event) => setUsername(event.target.value), value: username })] }), _jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.password ?? 'Password' }), _jsx(Input, { autoComplete: 'current-password', onChange: (event) => setPassword(event.target.value), type: 'password', value: password })] }), _jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.displayName ?? 'Sender name (optional)' }), _jsx(Input, { autoComplete: 'name', onChange: (event) => setDisplayName(event.target.value), value: displayName })] })] })) : null, selectedProvider ? (_jsx("div", { className: 'rounded-lg border bg-muted/20 p-4', children: _jsxs("div", { className: 'flex flex-wrap items-center justify-between gap-2', children: [_jsxs("div", { children: [_jsx("p", { className: 'font-medium', children: selectedProvider.label }), _jsx("p", { className: 'text-xs text-muted-foreground', children: providerConfigured
52
+ }, children: [_jsx(Link2, { "aria-hidden": 'true', className: 'size-4' }), connecting ? labels.connecting : labels.connect] })] }), usesCredentials && providerConfigured ? (_jsxs("div", { className: 'grid items-start gap-3 sm:grid-cols-2', children: [_jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.emailAddress ?? 'Email address' }), _jsx(Input, { autoComplete: 'email', onChange: (event) => setAddress(event.target.value), value: address })] }), _jsxs("div", { className: 'grid gap-2', children: [_jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.username ?? 'Username (optional)' }), _jsx(Input, { "aria-describedby": usernameDescriptionId, autoComplete: 'username', onChange: (event) => setUsername(event.target.value), value: username })] }), _jsx("p", { className: 'text-xs text-muted-foreground', id: usernameDescriptionId, children: labels.usernameDescription ??
53
+ 'Usually your email address. Leave blank to use the email address you entered.' })] }), _jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.password ?? 'Password' }), _jsx(Input, { autoComplete: 'current-password', onChange: (event) => setPassword(event.target.value), type: 'password', value: password })] }), _jsxs("label", { className: 'grid gap-2 text-sm font-medium', children: [_jsx("span", { children: labels.displayName ?? 'Sender name (optional)' }), _jsx(Input, { autoComplete: 'name', onChange: (event) => setDisplayName(event.target.value), value: displayName })] })] })) : null, selectedProvider ? (_jsx("div", { className: 'rounded-lg border bg-muted/20 p-4', children: _jsxs("div", { className: 'flex flex-wrap items-center justify-between gap-2', children: [_jsxs("div", { children: [_jsx("p", { className: 'font-medium', children: selectedProvider.label }), _jsx("p", { className: 'text-xs text-muted-foreground', children: providerConfigured
53
54
  ? labels.connectedAccounts(connectedAccountCount(selectedProvider))
54
55
  : labels.configurationRequired })] }), providerConfigured ? (_jsx("div", { className: 'flex flex-wrap justify-end gap-1.5', children: capabilities.map((capability) => (_jsx("span", { className: 'rounded-md border bg-background px-2 py-1 text-xs text-muted-foreground', children: labels.capability(capability) }, capability))) })) : null] }) })) : null] }));
55
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mail-account-connector.js","sourceRoot":"","sources":["../../../client/components/mail-account-connector.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mail-account-connector.js","sourceRoot":"","sources":["../../../client/components/mail-account-connector.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"mail-navigation-icon.d.ts","sourceRoot":"","sources":["../../../client/components/mail-navigation-icon.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAQ1C,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AAGrE,yDAAyD;AACzD,wBAAgB,kBAAkB,IAAI,YAAY,CAgEjD"}
1
+ {"version":3,"file":"mail-navigation-icon.d.ts","sourceRoot":"","sources":["../../../client/components/mail-navigation-icon.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAM1C,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AACrE,yDAAyD;AACzD,wBAAgB,kBAAkB,IAAI,YAAY,CAoBjD"}
@@ -1,61 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Mail } from 'lucide-react';
3
- import { realtimeClientToken, useService } from '@nocobase/app-client';
4
- import { useEffect, useState } from 'react';
5
3
  import { useTranslation } from '@nocobase/i18n/client';
6
- import { useMailClient } from '../runtime.js';
4
+ import { useMailUnreadCount } from '../hooks/use-mail-unread-count.js';
7
5
  import { MAIL_PLUGIN_NS } from '../namespace.js';
8
- import { subscribeToMailInvalidations } from '../subscription.js';
9
- const REFRESH_INTERVAL_MS = 60_000;
10
6
  export { MAIL_UNREAD_COUNT_CHANGED_EVENT } from '../subscription.js';
11
- import { MAIL_UNREAD_COUNT_CHANGED_EVENT } from '../subscription.js';
12
7
  /** Mail center icon with a current-user unread badge. */
13
8
  export function MailNavigationIcon() {
14
9
  const { t } = useTranslation(MAIL_PLUGIN_NS);
15
- const mail = useMailClient();
16
- const realtime = useService(realtimeClientToken);
17
- const [unread, setUnread] = useState(0);
18
- useEffect(() => {
19
- let active = true;
20
- let pending = false;
21
- let inFlight = false;
22
- let debounce;
23
- const refresh = () => {
24
- if (!active || inFlight)
25
- return;
26
- pending = false;
27
- inFlight = true;
28
- void mail
29
- .getUnreadCount()
30
- .then((count) => {
31
- if (active && !pending)
32
- setUnread(count);
33
- })
34
- .catch(() => undefined)
35
- .finally(() => {
36
- inFlight = false;
37
- if (active && pending)
38
- schedule();
39
- });
40
- };
41
- const schedule = () => {
42
- pending = true;
43
- window.clearTimeout(debounce);
44
- debounce = window.setTimeout(refresh, 100);
45
- };
46
- refresh();
47
- const unsubscribeRealtime = subscribeToMailInvalidations(realtime, window, schedule);
48
- const timer = window.setInterval(schedule, REFRESH_INTERVAL_MS);
49
- window.addEventListener(MAIL_UNREAD_COUNT_CHANGED_EVENT, schedule);
50
- return () => {
51
- active = false;
52
- window.clearInterval(timer);
53
- window.clearTimeout(debounce);
54
- unsubscribeRealtime();
55
- window.removeEventListener(MAIL_UNREAD_COUNT_CHANGED_EVENT, schedule);
56
- };
57
- }, [mail, realtime]);
58
- return (_jsxs("span", { className: 'relative inline-flex size-4 items-center justify-center', children: [_jsx(Mail, { "aria-hidden": 'true', className: 'size-4' }), unread > 0 ? (_jsx("span", { "aria-label": t('nav.unread', {
10
+ const { unreadCount: unread } = useMailUnreadCount();
11
+ return (_jsxs("span", { className: 'relative inline-flex size-4 items-center justify-center', children: [_jsx(Mail, { "aria-hidden": 'true', className: 'size-4' }), unread !== undefined && unread > 0 ? (_jsx("span", { "aria-label": t('nav.unread', {
59
12
  count: unread,
60
13
  defaultValue: '{{count}} unread messages',
61
14
  }), className: 'absolute -top-2 -right-2 min-w-4 rounded-full bg-primary px-1 text-center text-[9px] leading-4 font-semibold text-primary-foreground', children: unread > 99 ? '99+' : unread })) : null] }));
@@ -1 +1 @@
1
- {"version":3,"file":"mail-navigation-icon.js","sourceRoot":"","sources":["../../../client/components/mail-navigation-icon.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mail-navigation-icon.js","sourceRoot":"","sources":["../../../client/components/mail-navigation-icon.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AACrE,yDAAyD;AACzD,MAAM,UAAU,kBAAkB;IAChC,MAAM,EAAE,CAAC,EAAE,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;IAC7C,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAErD,OAAO,CACL,gBAAM,SAAS,EAAC,yDAAyD,aACvE,KAAC,IAAI,mBAAa,MAAM,EAAC,SAAS,EAAC,QAAQ,GAAG,EAC7C,MAAM,KAAK,SAAS,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACpC,6BACc,CAAC,CAAC,YAAY,EAAE;oBAC1B,KAAK,EAAE,MAAM;oBACb,YAAY,EAAE,2BAA2B;iBAC1C,CAAC,EACF,SAAS,EAAC,sIAAsI,YAE/I,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GACxB,CACR,CAAC,CAAC,CAAC,IAAI,IACH,CACR,CAAC;AACJ,CAAC"}
@@ -15,5 +15,5 @@ export * from './mailbox-sidebar.js';
15
15
  export { MailComposer } from './mail-composer.js';
16
16
  export { MailWorkspaceComposer } from './mail-workspace-composer.js';
17
17
  export type { MailPublicError } from '../../shared/mail.js';
18
- export { EMPTY_MAIL_COMPOSER, type ComposerState, type MailComposerCompletionResult, type MailComposerComponentProps, type MailComposerProps, type MailComposerRequest, type MailComposerState, type MailForwardQuote, type MailTemplateVariables, type MailWorkspaceComposerProps, } from '../contracts/composer.js';
18
+ export { EMPTY_MAIL_COMPOSER, type ComposerState, type MailComposerCompletionResult, type MailComposerCompletionDetails, type MailComposerCompletionCallback, type MailComposerSubmissionSnapshot, type MailComposerComponentProps, type MailComposerProps, type MailComposerRequest, type MailComposerState, type MailForwardQuote, type MailTemplateVariables, type MailWorkspaceComposerProps, } from '../contracts/composer.js';
19
19
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../client/components/public.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../client/components/public.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACnC,KAAK,8BAA8B,EACnC,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../client/components/public.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EACL,mBAAmB,GAUpB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../client/components/public.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EACL,mBAAmB,GAapB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ComponentProps, ReactElement } from 'react';
2
+ export declare function FieldGroup({ className, ...props }: ComponentProps<'div'>): ReactElement;
3
+ export declare function Field({ className, ...props }: ComponentProps<'div'>): ReactElement;
4
+ export declare function FieldLabel({ className, ...props }: ComponentProps<'label'>): ReactElement;
5
+ export declare function FieldDescription({ className, ...props }: ComponentProps<'p'>): ReactElement;
6
+ export declare function FieldError({ className, children, ...props }: ComponentProps<'div'>): ReactElement | null;
7
+ //# sourceMappingURL=field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/field.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1D,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAWtC;AAED,wBAAgB,KAAK,CAAC,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAatC;AAED,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,YAAY,CAWxC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG,YAAY,CAapC;AAED,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,GAAG,IAAI,CAY7C"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from 'cn';
3
+ export function FieldGroup({ className, ...props }) {
4
+ return (_jsx("div", { "data-slot": 'field-group', className: cn('group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4', className), ...props }));
5
+ }
6
+ export function Field({ className, ...props }) {
7
+ return (_jsx("div", { role: 'group', "data-slot": 'field', "data-orientation": 'vertical', className: cn('group/field flex w-full flex-col gap-2 data-[invalid=true]:text-destructive *:w-full [&>.sr-only]:w-auto', className), ...props }));
8
+ }
9
+ export function FieldLabel({ className, ...props }) {
10
+ return (_jsx("label", { "data-slot": 'field-label', className: cn('group/field-label peer/field-label flex w-fit items-center gap-2 text-sm font-medium leading-snug select-none group-data-[disabled=true]/field:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50', className), ...props }));
11
+ }
12
+ export function FieldDescription({ className, ...props }) {
13
+ return (_jsx("p", { "data-slot": 'field-description', className: cn('text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5', 'last:mt-0 nth-last-2:-mt-1', '[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary', className), ...props }));
14
+ }
15
+ export function FieldError({ className, children, ...props }) {
16
+ if (!children)
17
+ return null;
18
+ return (_jsx("div", { role: 'alert', "data-slot": 'field-error', className: cn('text-sm font-normal text-destructive', className), ...props, children: children }));
19
+ }
20
+ //# sourceMappingURL=field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field.js","sourceRoot":"","sources":["../../../../client/components/ui/field.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAExB,MAAM,UAAU,UAAU,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACc;IACtB,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,sIAAsI,EACtI,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,EACpB,SAAS,EACT,GAAG,KAAK,EACc;IACtB,OAAO,CACL,cACE,IAAI,EAAC,OAAO,eACF,OAAO,sBACA,UAAU,EAC3B,SAAS,EAAE,EAAE,CACX,0GAA0G,EAC1G,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACgB;IACxB,OAAO,CACL,6BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,qNAAqN,EACrN,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,SAAS,EACT,GAAG,KAAK,EACY;IACpB,OAAO,CACL,yBACY,mBAAmB,EAC7B,SAAS,EAAE,EAAE,CACX,mJAAmJ,EACnJ,4BAA4B,EAC5B,mEAAmE,EACnE,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACc;IACtB,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,CACL,cACE,IAAI,EAAC,OAAO,eACF,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,sCAAsC,EAAE,SAAS,CAAC,KAC5D,KAAK,YAER,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { MailAccountView, MailIdentity, MailMessage, MailOutboundAttachmentView, MailProviderView, MailPublicError } from '../../shared/mail.js';
1
+ import type { MailAccountView, MailBulkComposeInput, MailComposeInput, MailIdentity, MailMessage, MailOutboundAttachmentView, MailProviderView, MailPublicError, MailSubmissionView } from '../../shared/mail.js';
2
2
  /** Safe variables available when a saved mail template is applied. */
3
3
  export type MailTemplateVariables = Readonly<Record<string, unknown>>;
4
4
  export interface MailForwardQuote {
@@ -40,6 +40,30 @@ export interface MailComposerRequest {
40
40
  readonly uploads?: readonly MailOutboundAttachmentView[];
41
41
  }
42
42
  export type MailComposerCompletionResult = 'accepted' | 'scheduled' | 'draft' | 'unknown' | 'failed' | 'partial' | (string & {});
43
+ /** Client-submitted content, not final MIME, server-prepared content or delivery proof. */
44
+ export type MailComposerSubmissionSnapshot = {
45
+ readonly kind: 'normal';
46
+ readonly input: Omit<MailComposeInput, 'deliverySnapshot' | 'deliveryContext' | 'sourceDraft'>;
47
+ } | {
48
+ readonly kind: 'bulk';
49
+ readonly input: Omit<MailBulkComposeInput, 'deliverySnapshot' | 'deliveryContext' | 'sourceDraft'>;
50
+ };
51
+ /** Records returned for this operation; an unknown transport outcome may have no records. */
52
+ export type MailComposerCompletionDetails = (MailComposerSubmissionSnapshot & {
53
+ readonly submissions: readonly MailSubmissionView[];
54
+ }) | {
55
+ readonly kind: 'draft';
56
+ readonly submissions: readonly [];
57
+ readonly draft: Pick<MailMessage, 'id' | 'accountId'>;
58
+ };
59
+ type MailComposerCompletionArguments = [
60
+ result: MailComposerCompletionResult,
61
+ rejectedRecipients?: readonly string[],
62
+ error?: MailPublicError,
63
+ details?: MailComposerCompletionDetails
64
+ ];
65
+ /** Observe async completion while retaining legacy callbacks whose return values are discarded. */
66
+ export type MailComposerCompletionCallback = ((...args: MailComposerCompletionArguments) => void) | ((...args: MailComposerCompletionArguments) => Promise<void>);
43
67
  /** Inputs shared by the embedded and account-aware workspace composers. */
44
68
  export interface MailComposerProps {
45
69
  readonly allowBulkSend?: boolean;
@@ -56,7 +80,9 @@ export interface MailComposerProps {
56
80
  readonly providers: readonly MailProviderView[];
57
81
  readonly templateVariables?: MailTemplateVariables;
58
82
  readonly onClose: () => void;
59
- readonly onComplete: (result: MailComposerCompletionResult, rejectedRecipients?: readonly string[], error?: MailPublicError) => void;
83
+ readonly onComplete: MailComposerCompletionCallback;
84
+ /** Integration failures do not change the mail result or delay closing the composer. */
85
+ readonly onCompletionError?: (error: unknown) => void | Promise<void>;
60
86
  }
61
87
  export interface MailComposerComponentProps extends MailComposerProps {
62
88
  readonly inline?: boolean;
@@ -65,4 +91,5 @@ export interface MailComposerComponentProps extends MailComposerProps {
65
91
  export interface MailWorkspaceComposerProps extends MailComposerProps {
66
92
  readonly onSelectAccount: (accountId: string) => void;
67
93
  }
94
+ export {};
68
95
  //# sourceMappingURL=composer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../../client/contracts/composer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../../client/contracts/composer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,0BAA0B,EAC1B,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAE9B,sEAAsE;AACtE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,YAAY,CAAC,EAAE,gBAAgB,CAAC;IACzC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,gBAAgB,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;IACtD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;CACnD;AAED,iEAAiE;AACjE,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAE9C,uCAAuC;AACvC,eAAO,MAAM,mBAAmB,EAAE,iBAShC,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,0BAA0B,EAAE,CAAC;CAC1D;AAED,MAAM,MAAM,4BAA4B,GACpC,UAAU,GACV,WAAW,GACX,OAAO,GACP,SAAS,GACT,QAAQ,GACR,SAAS,GACT,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB,2FAA2F;AAC3F,MAAM,MAAM,8BAA8B,GACtC;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAClB,gBAAgB,EAChB,kBAAkB,GAAG,iBAAiB,GAAG,aAAa,CACvD,CAAC;CACH,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAClB,oBAAoB,EACpB,kBAAkB,GAAG,iBAAiB,GAAG,aAAa,CACvD,CAAC;CACH,CAAC;AAEN,6FAA6F;AAC7F,MAAM,MAAM,6BAA6B,GACrC,CAAC,8BAA8B,GAAG;IAChC,QAAQ,CAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACrD,CAAC,GACF;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,SAAS,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,WAAW,CAAC,CAAC;CACvD,CAAC;AAEN,KAAK,+BAA+B,GAAG;IACrC,MAAM,EAAE,4BAA4B;IACpC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE;IACtC,KAAK,CAAC,EAAE,eAAe;IACvB,OAAO,CAAC,EAAE,6BAA6B;CACxC,CAAC;AAEF,mGAAmG;AACnG,MAAM,MAAM,8BAA8B,GACtC,CAAC,CAAC,GAAG,IAAI,EAAE,+BAA+B,KAAK,IAAI,CAAC,GACpD,CAAC,CAAC,GAAG,IAAI,EAAE,+BAA+B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAElE,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE;QACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS;YACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;YAC3B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;SACjC,EAAE,CAAC;QACJ,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;KACpE,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAChD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,qBAAqB,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,8BAA8B,CAAC;IACpD,wFAAwF;IACxF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,0BAA2B,SAAQ,iBAAiB;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA2B,SAAQ,iBAAiB;IACnE,QAAQ,CAAC,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"composer.js","sourceRoot":"","sources":["../../../client/contracts/composer.ts"],"names":[],"mappings":"AA6CA,uCAAuC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAClE,IAAI,EAAE,KAAK;IACX,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,GAAG,EAAE,EAAE;IACP,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,WAAW,EAAE,EAAE;CAChB,CAAC,CAAC"}
1
+ {"version":3,"file":"composer.js","sourceRoot":"","sources":["../../../client/contracts/composer.ts"],"names":[],"mappings":"AAgDA,uCAAuC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAClE,IAAI,EAAE,KAAK;IACX,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,GAAG,EAAE,EAAE;IACP,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,WAAW,EAAE,EAAE;CAChB,CAAC,CAAC"}
@@ -3,7 +3,7 @@ import { useTranslation } from '@nocobase/i18n/client';
3
3
  import { type ComposerRecoverySnapshot } from '../lib/mail-composer-state.js';
4
4
  import type { ComposerState, MailComposerProps } from '../contracts/composer.js';
5
5
  import { type MailIdentity, type MailMessage, type MailOutboundAttachmentView, type MailSignature, type MailTemplate } from '../mail-client.js';
6
- export declare function useMailComposer({ request, allowBulkSend, senderSelection, accounts, providers, onClose, onComplete, }: MailComposerProps): MailComposerController;
6
+ export declare function useMailComposer({ request, allowBulkSend, senderSelection, accounts, providers, onClose, onComplete, onCompletionError, }: MailComposerProps): MailComposerController;
7
7
  export interface MailComposerController {
8
8
  readonly restoreDraft: () => void;
9
9
  readonly discardRecovery: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"use-mail-composer.d.ts","sourceRoot":"","sources":["../../../client/hooks/use-mail-composer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-mail-composer.d.ts","sourceRoot":"","sources":["../../../client/hooks/use-mail-composer.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { notifyComposerCompletion, reportComposerCompletionError, } from '../lib/mail-composer-completion.js';
1
2
  import { writePendingDelivery, clearPendingDelivery, } from '../lib/mail-pending-delivery.js';
2
3
  import { ApiClientError, resolveAppUrl } from '@nocobase/app-client';
3
4
  import { uploadedImageContentId } from '../../shared/inline-images.js';
@@ -9,9 +10,12 @@ import { MAIL_PLUGIN_NS } from '../namespace.js';
9
10
  import { useMailClient } from '../runtime.js';
10
11
  const AUTO_SAVE_DELAY_MS = 2_000;
11
12
  const AUTO_SAVE_MAX_WAIT_MS = 10_000;
12
- export function useMailComposer({ request, allowBulkSend = false, senderSelection, accounts, providers, onClose, onComplete, }) {
13
+ export function useMailComposer({ request, allowBulkSend = false, senderSelection, accounts, providers, onClose, onComplete, onCompletionError, }) {
13
14
  const { t } = useTranslation(MAIL_PLUGIN_NS);
14
15
  const mail = useMailClient();
16
+ const complete = useCallback((...args) => {
17
+ notifyComposerCompletion(onComplete, onCompletionError, ...args);
18
+ }, [onComplete, onCompletionError]);
15
19
  const [error, setError] = useState();
16
20
  const [initialRecovery] = useState(() => request.value.mode === 'new'
17
21
  ? readComposerRecovery(request.accountId)
@@ -248,6 +252,11 @@ export function useMailComposer({ request, allowBulkSend = false, senderSelectio
248
252
  setError(undefined);
249
253
  let input = buildComposerInput(composerAccountId, identityId, signatureId, composer, composeAttachments, retainedAttachments);
250
254
  let submitted = false;
255
+ let completion = {
256
+ kind: 'normal',
257
+ input: structuredClone(input),
258
+ submissions: [],
259
+ };
251
260
  const sendBulk = async () => {
252
261
  // Each recipient must own its delivery; sending the shared provider draft
253
262
  // would consume it on the first message and break the rest of the batch.
@@ -284,6 +293,11 @@ export function useMailComposer({ request, allowBulkSend = false, senderSelectio
284
293
  forwardBodyIncluded: input.forwardBodyIncluded,
285
294
  };
286
295
  const wire = { ...bulkInput, idempotencyKey: input.idempotencyKey };
296
+ completion = {
297
+ kind: 'bulk',
298
+ input: structuredClone(wire),
299
+ submissions: [],
300
+ };
287
301
  writePendingDelivery({
288
302
  accountId: composerAccountId,
289
303
  mode: 'bulk',
@@ -293,6 +307,11 @@ export function useMailComposer({ request, allowBulkSend = false, senderSelectio
293
307
  return mail.sendBulk(wire);
294
308
  };
295
309
  const sendSingle = () => {
310
+ completion = {
311
+ kind: 'normal',
312
+ input: structuredClone(input),
313
+ submissions: [],
314
+ };
296
315
  writePendingDelivery({
297
316
  accountId: composerAccountId,
298
317
  mode: 'normal',
@@ -323,10 +342,19 @@ export function useMailComposer({ request, allowBulkSend = false, senderSelectio
323
342
  ? 'partial'
324
343
  : 'accepted';
325
344
  clearPendingDelivery(composerAccountId, input.idempotencyKey);
326
- closeComposer(true);
327
- onComplete(outcome === 'accepted' && input.scheduledAt ? 'scheduled' : outcome, rejectedRecipients, operationError);
328
- })
329
- .catch((error) => {
345
+ const details = {
346
+ ...completion,
347
+ submissions: structuredClone(results),
348
+ };
349
+ try {
350
+ closeComposer(true);
351
+ }
352
+ finally {
353
+ complete(outcome === 'accepted' && input.scheduledAt
354
+ ? 'scheduled'
355
+ : outcome, rejectedRecipients, operationError, details);
356
+ }
357
+ }, (error) => {
330
358
  if (!submitted ||
331
359
  (error instanceof ApiClientError &&
332
360
  [400, 401, 403, 404, 422].includes(error.status))) {
@@ -337,9 +365,14 @@ export function useMailComposer({ request, allowBulkSend = false, senderSelectio
337
365
  }
338
366
  // A transport failure is not evidence of non-delivery. Keep the outgoing
339
367
  // snapshot in sending records, never restore it as an editable draft.
340
- closeComposer(true);
341
- onComplete('unknown');
368
+ try {
369
+ closeComposer(true);
370
+ }
371
+ finally {
372
+ complete('unknown', undefined, undefined, completion);
373
+ }
342
374
  })
375
+ .catch((error) => reportComposerCompletionError(onCompletionError, error))
343
376
  .finally(() => setSending(false));
344
377
  };
345
378
  const uploadInlineImage = async (file) => {
@@ -473,12 +506,22 @@ export function useMailComposer({ request, allowBulkSend = false, senderSelectio
473
506
  setDraftSaveStatus('saved');
474
507
  if (closeAfterSave &&
475
508
  latestComposerFingerprintRef.current === fingerprint) {
509
+ const details = {
510
+ kind: 'draft',
511
+ submissions: [],
512
+ draft: { id: draft.id, accountId: draft.accountId },
513
+ };
476
514
  endingRef.current = true;
477
515
  clearComposerRecovery(composerAccountId);
478
516
  composerSessionRef.current += 1;
479
517
  setComposer(undefined);
480
- onClose();
481
- onComplete('draft');
518
+ try {
519
+ onClose();
520
+ }
521
+ catch (error) {
522
+ reportComposerCompletionError(onCompletionError, error);
523
+ }
524
+ complete('draft', undefined, undefined, details);
482
525
  }
483
526
  })
484
527
  .catch(() => {
@@ -493,7 +536,8 @@ export function useMailComposer({ request, allowBulkSend = false, senderSelectio
493
536
  });
494
537
  }, [
495
538
  onClose,
496
- onComplete,
539
+ onCompletionError,
540
+ complete,
497
541
  composer,
498
542
  composerAccountId,
499
543
  identityId,