feat: add message-list category tabs
This commit is contained in:
@@ -249,6 +249,51 @@ function buildPluginApi(manifest: PluginManifest) {
|
||||
downloadFile: (opts: { content: string; filename: string; contentType?: string }) =>
|
||||
callApi('ui.downloadFile', [opts]) as Promise<void>,
|
||||
},
|
||||
// Email keyword mutations (permission: email:write). Keywords follow JMAP
|
||||
// syntax, e.g. '$category-promotions' or '$label:<tagId>'.
|
||||
email: {
|
||||
setKeyword: (emailId: string, keyword: string, accountId?: string) =>
|
||||
callApi('email.setKeyword', [emailId, keyword, accountId]) as Promise<void>,
|
||||
removeKeyword: (emailId: string, keyword: string, accountId?: string) =>
|
||||
callApi('email.removeKeyword', [emailId, keyword, accountId]) as Promise<void>,
|
||||
},
|
||||
// Message-list category tabs (permission: ui:message-list-tabs; categorize
|
||||
// additionally needs email:write). The host renders the strip natively and
|
||||
// ANDs the active tab's JMAP search filter (`query`) or keyword into the
|
||||
// mailbox Email/query - see MessageListTabsConfig in plugin-types. Tabs
|
||||
// are cleared automatically when the plugin unloads.
|
||||
tabs: {
|
||||
/** Register (or replace) this plugin's tab set. */
|
||||
set: (config: unknown) => callApi('tabs.set', [config]) as Promise<void>,
|
||||
/** Remove this plugin's tabs from the strip. */
|
||||
clear: () => callApi('tabs.clear', []) as Promise<void>,
|
||||
/** Current merged tabs, active tab id and unread counts. */
|
||||
getState: () => callApi('tabs.getState', []) as Promise<{
|
||||
tabs: unknown[]; activeTabId: string | null; tabCounts: Record<string, number>;
|
||||
}>,
|
||||
/** Re-query per-tab unread counts for the current mailbox. */
|
||||
refreshCounts: () => callApi('tabs.refreshCounts', []) as Promise<Record<string, number>>,
|
||||
/**
|
||||
* Move messages to a tab (patches the category keywords via Email/set).
|
||||
* Fires onBeforeEmailCategorize (cancellable) and onEmailCategorize.
|
||||
* Resolves false when cancelled.
|
||||
*/
|
||||
categorize: (emailIds: string[], tabId: string) =>
|
||||
callApi('tabs.categorize', [emailIds, tabId]) as Promise<boolean>,
|
||||
},
|
||||
// Sieve integration for delivery-time classification (permissions:
|
||||
// filters:read / filters:write). Plugins never write scripts directly -
|
||||
// they register an onSieveScriptGenerate transform hook and call
|
||||
// regenerate(), so user filter rules and plugin sections coexist in the
|
||||
// single active script.
|
||||
sieve: {
|
||||
isSupported: () => callApi('sieve.isSupported', []) as Promise<boolean>,
|
||||
getActiveScript: () => callApi('sieve.getActiveScript', []) as Promise<{ id: string; name: string; content: string } | null>,
|
||||
validateScript: (content: string) =>
|
||||
callApi('sieve.validateScript', [content]) as Promise<{ isValid: boolean; errors?: string[] }>,
|
||||
/** Rebuild + re-upload the active script, running onSieveScriptGenerate. */
|
||||
regenerate: () => callApi('sieve.regenerate', []) as Promise<void>,
|
||||
},
|
||||
admin: {
|
||||
getConfig: (key: string) => callApi('admin.getConfig', [key]),
|
||||
getAllConfig: () => callApi('admin.getAllConfig', []),
|
||||
|
||||
Reference in New Issue
Block a user