Compare commits
1 Commits
main
..
a2daf1f7de
| Author | SHA1 | Date | |
|---|---|---|---|
| a2daf1f7de |
@@ -80,8 +80,8 @@ final class CompositionController extends ControllerAbstract {
|
|||||||
if (!isset($data['action']) || !is_string($data['action'])) {
|
if (!isset($data['action']) || !is_string($data['action'])) {
|
||||||
throw new InvalidArgumentException('Invalid parameter: action must be a string');
|
throw new InvalidArgumentException('Invalid parameter: action must be a string');
|
||||||
}
|
}
|
||||||
if (!in_array($data['action'], ['fresh', 'reply', 'replyAll', 'forward'], true)) {
|
if (!in_array($data['action'], ['fresh', 'reply', 'forward'], true)) {
|
||||||
throw new InvalidArgumentException('Invalid parameter: action must be one of fresh, reply, replyAll, forward');
|
throw new InvalidArgumentException('Invalid parameter: action must be one of fresh, reply, forward');
|
||||||
}
|
}
|
||||||
if (!isset($data['sender']) || !is_array($data['sender'])) {
|
if (!isset($data['sender']) || !is_array($data['sender'])) {
|
||||||
throw new InvalidArgumentException('Invalid parameter: sender must be an array');
|
throw new InvalidArgumentException('Invalid parameter: sender must be an array');
|
||||||
@@ -89,8 +89,8 @@ final class CompositionController extends ControllerAbstract {
|
|||||||
if (!isset($data['message']) || !is_array($data['message'])) {
|
if (!isset($data['message']) || !is_array($data['message'])) {
|
||||||
throw new InvalidArgumentException('Invalid parameter: message must be an array');
|
throw new InvalidArgumentException('Invalid parameter: message must be an array');
|
||||||
}
|
}
|
||||||
if (($data['action'] === 'reply' || $data['action'] === 'replyAll' || $data['action'] === 'forward') && (!isset($data['source']) || !is_string($data['source']) || $data['source'] === '')) {
|
if (($data['action'] === 'reply' || $data['action'] === 'forward') && (!isset($data['source']) || !is_string($data['source']) || $data['source'] === '')) {
|
||||||
throw new InvalidArgumentException('Invalid parameter: source must be a non-empty string for reply, replyAll, or forward action');
|
throw new InvalidArgumentException('Invalid parameter: source must be a non-empty string for reply or forward action');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->compositionManager->stage($tenantId, $userId, $data['identifier'], $data['action'], $data['sender'], $data['message'], $data['source'] ?? null);
|
return $this->compositionManager->stage($tenantId, $userId, $data['identifier'], $data['action'], $data['sender'], $data['message'], $data['source'] ?? null);
|
||||||
|
|||||||
+12
-7
@@ -4,14 +4,13 @@ namespace KTXM\Mail;
|
|||||||
|
|
||||||
use KTXF\Event\DeliveryMode;
|
use KTXF\Event\DeliveryMode;
|
||||||
use KTXF\Event\EventListenerRegistrarInterface;
|
use KTXF\Event\EventListenerRegistrarInterface;
|
||||||
use KTXF\Module\Configuration\BrowserModuleContextInterface;
|
use KTXF\Module\ModuleBrowserInterface;
|
||||||
use KTXF\Module\Configuration\ModuleContextInterface;
|
|
||||||
use KTXF\Module\ModuleInstanceAbstract;
|
use KTXF\Module\ModuleInstanceAbstract;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mail Module - Email Client
|
* Mail Module - Email Client
|
||||||
*/
|
*/
|
||||||
class Module extends ModuleInstanceAbstract
|
class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
@@ -80,10 +79,16 @@ class Module extends ModuleInstanceAbstract
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function configure(ModuleContextInterface $context): void
|
public function registerBI(): array
|
||||||
{
|
{
|
||||||
if ($context instanceof BrowserModuleContextInterface) {
|
return [
|
||||||
$context->registerModule($this, 'Mail', 'static/module.mjs');
|
'handle' => $this->handle(),
|
||||||
}
|
'namespace' => 'Mail',
|
||||||
|
'version' => $this->version(),
|
||||||
|
'label' => $this->label(),
|
||||||
|
'author' => $this->author(),
|
||||||
|
'description' => $this->description(),
|
||||||
|
'boot' => 'static/module.mjs',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+198
-198
@@ -795,49 +795,49 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/core": {
|
"node_modules/@tiptap/core": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.30.3.tgz",
|
||||||
"integrity": "sha512-A/lrhKpOYtl0V5pmPS00Zps8pgBe1qDOoD9fzsumDSZ3HP8W398C959Jgru75PNFokAya9COPD3iaKP3NWF25g==",
|
"integrity": "sha512-kDD8KY99lBCKntCqTBE9eNR1ul/i/wPFw2METWT+LYZvifljXq2oiX6JaGF1Sk59efe7+sq9IISxOk47YlBiWQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/pm": "3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-blockquote": {
|
"node_modules/@tiptap/extension-blockquote": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.30.3.tgz",
|
||||||
"integrity": "sha512-k8NKHLEYOqre7guObZBeFM04CaTwmEceCmdIrIjd7H9KoHSbRODaBNved6j5G33x/FWMwIF/RQbE2BjWaFSgzA==",
|
"integrity": "sha512-Dh8yfEqBKTqEdBKZ4Ta3DkTecP0VJxvRNA5b1LCF7gBbe54Lm3A28UuVvK/Sdhh9FJDrIVCQTDS0yHGbi6G9ew==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/pm": "3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-bold": {
|
"node_modules/@tiptap/extension-bold": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.30.3.tgz",
|
||||||
"integrity": "sha512-BPUJvJ9sCsU3fxao5UJfDJrDuHhMn2hczZwZ9Qs4w1vkAeLGyOYbSejUTJdBYHLoexGiEwgnEeVeZN3C8GaI5g==",
|
"integrity": "sha512-a4BSAjWRN4mWklRTdDCIaG9R+PqyUxXNYGQ2CLtOhO51Wq6daw2qFTHR+cTqAjaiiUSuDYII86UChb2qQRq8Lg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-bubble-menu": {
|
"node_modules/@tiptap/extension-bubble-menu": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.30.3.tgz",
|
||||||
"integrity": "sha512-aBNI8ebX76ObderRmu/PJ9Q2AGVEuhpg0TBvv2SNbHtmU5kNUMHQI8HxrxKFblJwETAmG6EJ3Ed/5jRxpJmrsg==",
|
"integrity": "sha512-YryCf9fq+9n1XIW6f5weSCD2MbL/LhRQ7jArRToQQ/oNxc422LqYVjijQQTNuk2cZEqE9fdO3Hw27tmwEEs9UQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -848,67 +848,80 @@
|
|||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/pm": "3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-bullet-list": {
|
||||||
|
"version": "3.30.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.30.3.tgz",
|
||||||
|
"integrity": "sha512-Z/ZqUfrd3Fd8hHpHEPv3XRzqwqVLD4CP67xFMyjy0cqEgnjgvd1iR6QzJsKD79V9zyu0Agu7ab9ZBf4NktpWcw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extension-list": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-code": {
|
"node_modules/@tiptap/extension-code": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.30.3.tgz",
|
||||||
"integrity": "sha512-Um0BlyunRJ8Fal288Jn7I2n15FRwQcTy3NnKBBrPz3ikwx+yZZ0n9xTozpLMSxXrTq6cRlxLkASp/9FFx9sX9A==",
|
"integrity": "sha512-mOV4Fg+ji6uXmFxTMuug9WK6zk0ksNQepnuvoDR4g4d+tnz2y9iEbgOXFohVxhOXOLDLdNeKdwHxbHQdi5Ivbw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-code-block": {
|
"node_modules/@tiptap/extension-code-block": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.30.3.tgz",
|
||||||
"integrity": "sha512-nKm1YSEiPVosjm4qeg6m+6SAKq82rKukAzE/g3M5eVs2OgEb4QIKQvQOmJ+zgGAnpb9Q/JIvcKsGGU1rn9Vnyw==",
|
"integrity": "sha512-xT2cDil/ipy/LklPgv/JqSsXys1mjcqlIPDUetK3llB2DT7XZssYPV3qv278tqRO4pJDbrXk82I6Lh7vLwmIAg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/pm": "3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-document": {
|
"node_modules/@tiptap/extension-document": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.30.3.tgz",
|
||||||
"integrity": "sha512-folTlrwmUL+WSnojvfjZ951Gb25Pw8BxjXwhvXFuZXJ92qMfOcezA480kwFuu5nG8pPc/76ezQlz9a86Y5uQJw==",
|
"integrity": "sha512-B9gqrgM1uHjCKr/PSnnSl+bS+YQb5EN/PUW9KWp9nSgmIaqxXws2ufqowS65uTLJLqd7pwF4l5lUrsfhq0EKzw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-dropcursor": {
|
"node_modules/@tiptap/extension-dropcursor": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.30.3.tgz",
|
||||||
"integrity": "sha512-IAY21q7KSXyCXN3u13kfpq0E8D2i3r9nSbsNYlLzkEv0Bpn+pWShZi05A0ubuothDNjdaMa96xaRY0f1y9gDZw==",
|
"integrity": "sha512-xdY66lcQakBLvWbJQHeJy/Td0f10YRXLyFeOFzt9PODsX4nqwJMju9tpqcLIGp0waaztu8PGwZ81oSCdQldIHQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/extensions": "3.29.0"
|
"@tiptap/extensions": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-floating-menu": {
|
"node_modules/@tiptap/extension-floating-menu": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.30.3.tgz",
|
||||||
"integrity": "sha512-/rFlN6T70HuT34kFvftKm56UX0IPff7vlII7Sqgs7DprKVYkItiU3lM7+AoeDRzCsWMg4z1yNHj70BPx7+EJ6Q==",
|
"integrity": "sha512-4l5Qee1wBk2YBFEFbWHFhUt++6hDY7Yp81BkO3wY6KFToxs+cm9JIm3xr3KF9UJ/vnUpIhBWIbZl3uKf37SJLA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
@@ -917,80 +930,80 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@floating-ui/dom": "^1.0.0",
|
"@floating-ui/dom": "^1.0.0",
|
||||||
"@tiptap/core": "3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/pm": "3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-gapcursor": {
|
"node_modules/@tiptap/extension-gapcursor": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.30.3.tgz",
|
||||||
"integrity": "sha512-Jz0zwriGxPMuRjKo6x7WhPa/7pZn0dovyJu/GLarN4T+mMseGNXWwEBsLEKkuumsJVPDEPPFjX+rzEeaFKInPQ==",
|
"integrity": "sha512-+mwm64+RiArd1G8xSgtaTrvx1X5Lzz6sJ93zTmaiMVNc2N29AN77BVPTJ0e+853+/F6Bec/vOnVkIjTLg/ZBRw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/extensions": "3.29.0"
|
"@tiptap/extensions": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-hard-break": {
|
"node_modules/@tiptap/extension-hard-break": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.30.3.tgz",
|
||||||
"integrity": "sha512-8qKj0oeuU7IYoG73Lj3W4EC/JS/dFjN5iHmc4yodqppP6qs0o2zsF/2ipceGN/REZq5megPtxRgXu/nxQZ1NYg==",
|
"integrity": "sha512-/tX+IFW2C4RJltbwcn8/4zoHwj5YycRNOugb4Ul9Fl1AOJqjNwRx8xc0NpaOjuADhlMYMczEtSaOiDh5ZEOmjg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-heading": {
|
"node_modules/@tiptap/extension-heading": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.30.3.tgz",
|
||||||
"integrity": "sha512-xWb3QEKo7cp9u6Vzi6oYKODra6jPwziHBv3fJAnxWpRldxtJqfyOVMikWJJFuDjmr+K0qyegzf206pMk+y0bDg==",
|
"integrity": "sha512-y+0u9qdrUAOGNrP52hAEiH1mvr1ZmzmkCBICICiXRH4+QNXpKkiBK3zlbDOPVQj0g0YIg6XIIU0vIaUBDPIaMQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-horizontal-rule": {
|
"node_modules/@tiptap/extension-horizontal-rule": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.30.3.tgz",
|
||||||
"integrity": "sha512-u1OgncXkokIuUJQIh4jVQfYHL/6I8VnrokUcCud4eErWvgeLnCbNmVdih4kxIdfmvEyAxXjDwcqf4AB79TxuNg==",
|
"integrity": "sha512-J/ioKlXu5oJ+pPtybFonByx1LusbR0PUd1nkx6XsZqY9wyW6uecZQgAyI8KUWIXqOfhnAW38UTsHMBRdm2XupA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/pm": "3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-italic": {
|
"node_modules/@tiptap/extension-italic": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.30.3.tgz",
|
||||||
"integrity": "sha512-c8gF+zM7yXB9iGxtVCioYecjQ+A2fLlNa1XYBYbTobNhbUo8a11akbTkGNcCIgttwnzwEoI4mB6/PK4yjaQvVg==",
|
"integrity": "sha512-dVWqJ/kDXdPHRBp4nU7bwi2G+c3oNruIgQHYVRgYlWkwW/opvnlACZLBUgEhihH7ANiSaGW1zLQ7HuUDSL3vog==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-link": {
|
"node_modules/@tiptap/extension-link": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.30.3.tgz",
|
||||||
"integrity": "sha512-FuLDgE0k1dB4WCBTelw3re9BLmiurgXVSj3d3J4l3sunljyOs941RUU62b7pWP+ePNdGF7RgUMmMAB+58VZCIA==",
|
"integrity": "sha512-MAAXfLJNf6ZFiFK3w51yiLKc31HAQWJWNV+nQ1dAdRpa6WiXdjpkcrWTuxmPd/o6Qt+yNv+hoItAVxDPEox8qQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"linkifyjs": "^4.3.3"
|
"linkifyjs": "^4.3.3"
|
||||||
@@ -1000,106 +1013,159 @@
|
|||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/pm": "3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-list": {
|
||||||
|
"version": "3.30.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.30.3.tgz",
|
||||||
|
"integrity": "sha512-cCX99WoVb4UyXkamSh0vlXiRFhlZnwk3WXWdnXpR1E9+auxsQewk2Q9NDW1Ra0vwgzer1gkFhlOl9TCVzH2VVg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/core": "3.30.3",
|
||||||
|
"@tiptap/pm": "3.30.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-list-item": {
|
||||||
|
"version": "3.30.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.30.3.tgz",
|
||||||
|
"integrity": "sha512-RhSyDlAATvXDTg/1VOw5aFTaewdCm+BAU3EG3eUCw4e5eoZ5pbhPOdOPTtaO45UR4i/AvjQNAZQ9LMDWX5WZFQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extension-list": "3.30.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-list-keymap": {
|
||||||
|
"version": "3.30.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.30.3.tgz",
|
||||||
|
"integrity": "sha512-u6tOpQFnE1pOyvnzI2MvhW/Yw0omAIMlMfkykYx4N4zB1JDi+16OeOuKf3rX6G3V9VUu+qeOIGpSkifkME6H9Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extension-list": "3.30.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tiptap/extension-ordered-list": {
|
||||||
|
"version": "3.30.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.30.3.tgz",
|
||||||
|
"integrity": "sha512-lct/FV8vm9Y5kZFcF5TXIM18opi6m7AAkGoChgGP/A7LYalaniX1X6Ja2j13Y22ZdGaOoPTgd8oKRZXP1/miaA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tiptap/extension-list": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-paragraph": {
|
"node_modules/@tiptap/extension-paragraph": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.30.3.tgz",
|
||||||
"integrity": "sha512-OtGrkwzqlW+ehW+d2qrQ7VVcP9PbDeQmuT4Ec4yFjf3vR4QO8OVdVfeOcUq52PtkT3kYRxz9fzEiEvjqRm72yA==",
|
"integrity": "sha512-Z9OHCX9b2bDcMDeR3ODCFRAyHT5eNGO4AsDFeAJS/XSitffMyjFHtOkXlyyZ3+pIHxxX6xkUXAwaLMjyATRo1A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-placeholder": {
|
"node_modules/@tiptap/extension-placeholder": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.30.3.tgz",
|
||||||
"integrity": "sha512-V2jb0kL/k3rygAtKmSPYxoyBMCQJtJikPYnxiCYuY7FI1ohmCrmhyhkVqJv0b0EPMNW8BMIqf6DgpKJ/ODmXgA==",
|
"integrity": "sha512-B7LwMzeQajQ18FWPGYv2UDh64HSUfXxh/mdIhS6ZQEDJS9NyUD0hPPnwaMQ1w870L/APgJdb2/EGqIkZqjJRSg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/extensions": "3.29.0"
|
"@tiptap/extensions": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-strike": {
|
"node_modules/@tiptap/extension-strike": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.30.3.tgz",
|
||||||
"integrity": "sha512-VzasZkckrEXzmFQT9z3O95rUWy1b0RLFHAC6GUSQHxKk4TpP+Ujfn5+rqmPukMn0eScJyw1Y36jwfJc0VuNR+Q==",
|
"integrity": "sha512-e9BI8Hzei23GjmYysXxL+CHq3fIgOm29BbSUMbYXxT2cJ+TkkgJp7EvHf74gSABNME0gUN+mG0pRR5wTFoOCcg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-text": {
|
"node_modules/@tiptap/extension-text": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.30.3.tgz",
|
||||||
"integrity": "sha512-AMsf2V7IiGvzbl+LqLLfyWzufazZxHuid1gOnEt3KwolQ9AO7p8WJgHld0PZLxNyEh4SaSqK7b3d3SM9sqrlTw==",
|
"integrity": "sha512-Jh8ZyI0HLOJOIPZl5a5XRJbTs4pAUakYIWCZ3Hv3lF9ouXW/C0bY67XQU7bv6Rvu8AHzDszhKklnOZ6z1NQPXQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-text-align": {
|
"node_modules/@tiptap/extension-text-align": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-3.30.3.tgz",
|
||||||
"integrity": "sha512-/1htV3teqRJ7i7trAuORDg62LV0CQ1qskbMcP3SB7grsw6H1G54zwdaJVXeiIXmQKDF7FoZgY7u/v/TJckthEw==",
|
"integrity": "sha512-pwIZMn/PYoWZiUXrrD9oomV+Oh/GGhlIpa7Hr2WxdI8k3HZraweHa8S3ygvCUbodo9BWSI4zBs4KM3ic50cwlg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extension-underline": {
|
"node_modules/@tiptap/extension-underline": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.30.3.tgz",
|
||||||
"integrity": "sha512-DSPTogdvxmoX/L0U5KgBC9jWffRvYkGiyh1tp28gn+QaARh4iJn79pAZpi1m1bEhal/0Mq5m4ukbiO7FWInwaA==",
|
"integrity": "sha512-TiZ+b524Ee4PNlW+HNmkg3x4btR1K6btJy9pEjMuDf0Rx01UaTBvHpHmABR/DbbcC1CuZiQ3ylJwLL+90PaEoA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0"
|
"@tiptap/core": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/extensions": {
|
"node_modules/@tiptap/extensions": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.30.3.tgz",
|
||||||
"integrity": "sha512-ltlrm8dDHIgeNj3cOLEdLFMPPVy3TYvWA8ftrrJ44C/L01MBmgFB1f/vkPFYYnAasb2BYyVG6HxAGcTQHo5jHw==",
|
"integrity": "sha512-vig8ZjUL/NFnniEVbYDYj2UOIdkwZVha+9myFZkanShedviE3kl7c4uCY3fMl5EnqgyFIy2TQSKbg/i99xpztA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/pm": "3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/pm": {
|
"node_modules/@tiptap/pm": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.30.3.tgz",
|
||||||
"integrity": "sha512-4rr3HiZ8kbSNINuWXqKQJLv9fFMypCBN5gOwxoU+D4lEYVblkoM60fA1SlrI2BZVlZQmw2U38XKl5XMtUr55XQ==",
|
"integrity": "sha512-VheaqLAFUe+PCYEgHubM96Z1OAiluFhijQ2Cy1Ghiozoxm5OzevSaKhqm8SQ1VGfzZZko59oUjRzOmu8tB8yfA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"prosemirror-changeset": "^2.4.1",
|
"prosemirror-changeset": "^2.4.1",
|
||||||
@@ -1122,124 +1188,58 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/starter-kit": {
|
"node_modules/@tiptap/starter-kit": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.30.3.tgz",
|
||||||
"integrity": "sha512-J3jTp3/WXnnL58TCtdMsfeQ2BeycFYrAib6Nbpjd9G0OLUBE7AILiH2HrobRQpvRbAUgD5SW+sBZYOonbWWqNg==",
|
"integrity": "sha512-hj4rAhAoQm+wRk8eLNTyK+wK81+epbuo4O9PvPRv7GJGwYycej+xUN7jGM7Tney7GuTZpHoDCuwLKD2n1oG+pg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tiptap/core": "^3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/extension-blockquote": "^3.29.0",
|
"@tiptap/extension-blockquote": "3.30.3",
|
||||||
"@tiptap/extension-bold": "^3.29.0",
|
"@tiptap/extension-bold": "3.30.3",
|
||||||
"@tiptap/extension-bullet-list": "^3.29.0",
|
"@tiptap/extension-bullet-list": "3.30.3",
|
||||||
"@tiptap/extension-code": "^3.29.0",
|
"@tiptap/extension-code": "3.30.3",
|
||||||
"@tiptap/extension-code-block": "^3.29.0",
|
"@tiptap/extension-code-block": "3.30.3",
|
||||||
"@tiptap/extension-document": "^3.29.0",
|
"@tiptap/extension-document": "3.30.3",
|
||||||
"@tiptap/extension-dropcursor": "^3.29.0",
|
"@tiptap/extension-dropcursor": "3.30.3",
|
||||||
"@tiptap/extension-gapcursor": "^3.29.0",
|
"@tiptap/extension-gapcursor": "3.30.3",
|
||||||
"@tiptap/extension-hard-break": "^3.29.0",
|
"@tiptap/extension-hard-break": "3.30.3",
|
||||||
"@tiptap/extension-heading": "^3.29.0",
|
"@tiptap/extension-heading": "3.30.3",
|
||||||
"@tiptap/extension-horizontal-rule": "^3.29.0",
|
"@tiptap/extension-horizontal-rule": "3.30.3",
|
||||||
"@tiptap/extension-italic": "^3.29.0",
|
"@tiptap/extension-italic": "3.30.3",
|
||||||
"@tiptap/extension-link": "^3.29.0",
|
"@tiptap/extension-link": "3.30.3",
|
||||||
"@tiptap/extension-list": "^3.29.0",
|
"@tiptap/extension-list": "3.30.3",
|
||||||
"@tiptap/extension-list-item": "^3.29.0",
|
"@tiptap/extension-list-item": "3.30.3",
|
||||||
"@tiptap/extension-list-keymap": "^3.29.0",
|
"@tiptap/extension-list-keymap": "3.30.3",
|
||||||
"@tiptap/extension-ordered-list": "^3.29.0",
|
"@tiptap/extension-ordered-list": "3.30.3",
|
||||||
"@tiptap/extension-paragraph": "^3.29.0",
|
"@tiptap/extension-paragraph": "3.30.3",
|
||||||
"@tiptap/extension-strike": "^3.29.0",
|
"@tiptap/extension-strike": "3.30.3",
|
||||||
"@tiptap/extension-text": "^3.29.0",
|
"@tiptap/extension-text": "3.30.3",
|
||||||
"@tiptap/extension-underline": "^3.29.0",
|
"@tiptap/extension-underline": "3.30.3",
|
||||||
"@tiptap/extensions": "^3.29.0",
|
"@tiptap/extensions": "3.30.3",
|
||||||
"@tiptap/pm": "^3.29.0"
|
"@tiptap/pm": "3.30.3"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/starter-kit/node_modules/@tiptap/extension-bullet-list": {
|
|
||||||
"version": "3.29.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.29.0.tgz",
|
|
||||||
"integrity": "sha512-1045sC5CRn7KD0wluxZeksBwpm2k3LKBUOM3kNwExHAPSV4in4gdarYJ2/WCmIKsmyj2FzUcF4rbpLLSB/dBSg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@tiptap/extension-list": "3.29.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tiptap/starter-kit/node_modules/@tiptap/extension-list": {
|
|
||||||
"version": "3.29.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.29.0.tgz",
|
|
||||||
"integrity": "sha512-k0B/+nIkn4VvHSQ0kP+AzzAmgeOVxKMAdqG4a6qwxp/lR12aJGHlOP92KCjXV2RNPtuwDksJ1RIXrgxdf9WmJg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@tiptap/core": "3.29.0",
|
|
||||||
"@tiptap/pm": "3.29.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tiptap/starter-kit/node_modules/@tiptap/extension-list-item": {
|
|
||||||
"version": "3.29.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.29.0.tgz",
|
|
||||||
"integrity": "sha512-JSz27OIDHWDL7uw28E4W3eaN3H1u+NzJQKZkNXo5Qsvvsx8m/YIQWO9XlhiL3V4TZMjfvlc94lUp5tKW5KwETw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@tiptap/extension-list": "3.29.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tiptap/starter-kit/node_modules/@tiptap/extension-list-keymap": {
|
|
||||||
"version": "3.29.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.29.0.tgz",
|
|
||||||
"integrity": "sha512-g14QLZR9fmfJIL+X2R/cVTvQS0Mp7CoenA9PO+8adTjK7hCeB8hA3UAakMB4ekkElOXNOtb16e0wqulDcoqANg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@tiptap/extension-list": "3.29.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tiptap/starter-kit/node_modules/@tiptap/extension-ordered-list": {
|
|
||||||
"version": "3.29.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.29.0.tgz",
|
|
||||||
"integrity": "sha512-9TXUDFagkGeu6Bo8L0b2SAVAYrY2Xzd28MXwiDxYvDKMjEGWkkCUpMiEI5Qav3GnfFWLmS3jI8PgUjxIw9wLLQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@tiptap/extension-list": "3.29.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tiptap/vue-3": {
|
"node_modules/@tiptap/vue-3": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-3.30.3.tgz",
|
||||||
"integrity": "sha512-OFESbEFlmDYPns5LrkyeKggis6tYICBvz+jrlVwxICCWJqWZJJvYb7y/uMtMCxFF1nAeGb8AFr8UhFrLaX5aiA==",
|
"integrity": "sha512-lmGTJgHd1CuYjRmedtKPHRFvOPGWmC/sqBPr9DVCq6Te4tECdi6q7/EiYrhfiTkCptvPxub/06JQJVnvP+lytg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ueberdosis"
|
"url": "https://github.com/sponsors/ueberdosis"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@tiptap/extension-bubble-menu": "^3.29.0",
|
"@tiptap/extension-bubble-menu": "^3.30.3",
|
||||||
"@tiptap/extension-floating-menu": "^3.29.0"
|
"@tiptap/extension-floating-menu": "^3.30.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@floating-ui/dom": "^1.0.0",
|
"@floating-ui/dom": "^1.0.0",
|
||||||
"@tiptap/core": "3.29.0",
|
"@tiptap/core": "3.30.3",
|
||||||
"@tiptap/pm": "3.29.0",
|
"@tiptap/pm": "3.30.3",
|
||||||
"vue": "^3.0.0"
|
"vue": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import type { CollectionObject, MessageAddressObject } from '@MailManager/models
|
|||||||
import { useMailOperationsStore } from '@/stores/mailOperationsStore'
|
import { useMailOperationsStore } from '@/stores/mailOperationsStore'
|
||||||
import { useMailCompositionStore } from '@/stores/mailCompositionStore'
|
import { useMailCompositionStore } from '@/stores/mailCompositionStore'
|
||||||
import { ComposerMode } from '@/types/composer'
|
import { ComposerMode } from '@/types/composer'
|
||||||
import type { ComposerFormat } from '@/types/composer'
|
|
||||||
import { documentsSelectorComponent } from '@/services/documentsSelector'
|
import { documentsSelectorComponent } from '@/services/documentsSelector'
|
||||||
import ComposerToolbar from '@/components/composer/ComposerToolbar.vue'
|
import ComposerToolbar from '@/components/composer/ComposerToolbar.vue'
|
||||||
import ComposerSender from '@/components/composer/ComposerSender.vue'
|
import ComposerSender from '@/components/composer/ComposerSender.vue'
|
||||||
@@ -49,8 +48,6 @@ const {
|
|||||||
// State
|
// State
|
||||||
const showCc = ref(false)
|
const showCc = ref(false)
|
||||||
const showBcc = ref(false)
|
const showBcc = ref(false)
|
||||||
const format = ref<ComposerFormat>('rich')
|
|
||||||
const textEdited = ref(false)
|
|
||||||
const applyingDraftToEditor = ref(false)
|
const applyingDraftToEditor = ref(false)
|
||||||
const showDocumentSelector = ref(false)
|
const showDocumentSelector = ref(false)
|
||||||
const showCloseDialog = ref(false)
|
const showCloseDialog = ref(false)
|
||||||
@@ -88,14 +85,6 @@ const subject = computed({
|
|||||||
|
|
||||||
const attachments = computed(() => activeDraft.value?.attachments ?? {})
|
const attachments = computed(() => activeDraft.value?.attachments ?? {})
|
||||||
|
|
||||||
const text = computed({
|
|
||||||
get: () => activeDraft.value?.message.body.text ?? '',
|
|
||||||
set: value => {
|
|
||||||
textEdited.value = true
|
|
||||||
compositionStore.updateBody({ text: value, html: textToHtml(value) })
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Initialize Tiptap editor
|
// Initialize Tiptap editor
|
||||||
const editor = useEditor({
|
const editor = useEditor({
|
||||||
extensions: [
|
extensions: [
|
||||||
@@ -129,8 +118,6 @@ watch(
|
|||||||
compositionStore.openDraft(props.mode, props.source)
|
compositionStore.openDraft(props.mode, props.source)
|
||||||
showCc.value = (activeDraft.value?.message.cc.length ?? 0) > 0
|
showCc.value = (activeDraft.value?.message.cc.length ?? 0) > 0
|
||||||
showBcc.value = (activeDraft.value?.message.bcc.length ?? 0) > 0
|
showBcc.value = (activeDraft.value?.message.bcc.length ?? 0) > 0
|
||||||
format.value = 'rich'
|
|
||||||
textEdited.value = false
|
|
||||||
|
|
||||||
applyingDraftToEditor.value = true
|
applyingDraftToEditor.value = true
|
||||||
currentEditor.commands.setContent(activeDraft.value?.message.body.html || '')
|
currentEditor.commands.setContent(activeDraft.value?.message.body.html || '')
|
||||||
@@ -262,42 +249,6 @@ const toggleLink = () => {
|
|||||||
const isActive = (name: string, attrs?: any) => {
|
const isActive = (name: string, attrs?: any) => {
|
||||||
return editor.value?.isActive(name, attrs) || false
|
return editor.value?.isActive(name, attrs) || false
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleFormat = () => {
|
|
||||||
if (format.value === 'rich') {
|
|
||||||
if (editor.value) {
|
|
||||||
compositionStore.updateBody({
|
|
||||||
html: activeDraft.value?.message.body.html ?? '',
|
|
||||||
text: editor.value.getText(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
textEdited.value = false
|
|
||||||
format.value = 'plain'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
format.value = 'rich'
|
|
||||||
if (textEdited.value && editor.value) {
|
|
||||||
applyingDraftToEditor.value = true
|
|
||||||
editor.value.commands.setContent(activeDraft.value?.message.body.html || '')
|
|
||||||
applyingDraftToEditor.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function textToHtml(text: string): string {
|
|
||||||
if (!text) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
return text
|
|
||||||
.split(/\r?\n/)
|
|
||||||
.map(line => `<p>${escapeHtml(line) || '<br>'}</p>`)
|
|
||||||
.join('')
|
|
||||||
}
|
|
||||||
|
|
||||||
function escapeHtml(value: string): string {
|
|
||||||
return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -346,8 +297,6 @@ function escapeHtml(value: string): string {
|
|||||||
|
|
||||||
<ComposerEditor
|
<ComposerEditor
|
||||||
:editor="editor"
|
:editor="editor"
|
||||||
:format="format"
|
|
||||||
:text="text"
|
|
||||||
:is-bold-active="isActive('bold')"
|
:is-bold-active="isActive('bold')"
|
||||||
:is-italic-active="isActive('italic')"
|
:is-italic-active="isActive('italic')"
|
||||||
:is-underline-active="isActive('underline')"
|
:is-underline-active="isActive('underline')"
|
||||||
@@ -360,8 +309,6 @@ function escapeHtml(value: string): string {
|
|||||||
@bullet-list="toggleBulletList"
|
@bullet-list="toggleBulletList"
|
||||||
@ordered-list="toggleOrderedList"
|
@ordered-list="toggleOrderedList"
|
||||||
@link="toggleLink"
|
@link="toggleLink"
|
||||||
@toggle-format="toggleFormat"
|
|
||||||
@update:text="text = $event"
|
|
||||||
@attach-from-device="handleAttachFromDevice"
|
@attach-from-device="handleAttachFromDevice"
|
||||||
@attach-from-documents="handleAttachFromDocuments"
|
@attach-from-documents="handleAttachFromDocuments"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,14 +16,12 @@ interface Props {
|
|||||||
selectionMode?: boolean
|
selectionMode?: boolean
|
||||||
selectedCollection?: CollectionObject | null
|
selectedCollection?: CollectionObject | null
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
searchActive?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
loading: false,
|
loading: false,
|
||||||
selectionList: () => [],
|
selectionList: () => [],
|
||||||
selectionMode: false,
|
selectionMode: false,
|
||||||
searchActive: false,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Emits
|
// Emits
|
||||||
@@ -374,10 +372,10 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
<!-- Empty state -->
|
<!-- Empty state -->
|
||||||
<div v-else-if="messages.length === 0" class="pa-8 text-center">
|
<div v-else-if="messages.length === 0" class="pa-8 text-center">
|
||||||
<v-icon size="64" color="grey-lighten-1">{{ searchActive ? 'mdi-email-search-outline' : 'mdi-email-outline' }}</v-icon>
|
<v-icon size="64" color="grey-lighten-1">mdi-email-outline</v-icon>
|
||||||
<div class="text-h6 mt-4 text-medium-emphasis">No messages</div>
|
<div class="text-h6 mt-4 text-medium-emphasis">No messages</div>
|
||||||
<div class="text-body-2 text-medium-emphasis">
|
<div class="text-body-2 text-medium-emphasis">
|
||||||
{{ searchActive ? 'No messages match your search' : 'This folder is empty' }}
|
This folder is empty
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { usePreviewStore, useUser } from '@KTXC'
|
import { useUser } from '@KTXC'
|
||||||
import { useMailUiStore } from '@/stores/mailUiStore'
|
import { useMailUiStore } from '@/stores/mailUiStore'
|
||||||
import type { EntityObject, MessageObject } from '@MailManager/models'
|
import type { EntityObject, MessageObject } from '@MailManager/models'
|
||||||
import { SecurityLevel } from '@/utile/emailSanitizer'
|
import { SecurityLevel } from '@/utile/emailSanitizer'
|
||||||
@@ -19,7 +19,6 @@ const props = defineProps<{
|
|||||||
// Emits
|
// Emits
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
reply: [entity: EntityObject]
|
reply: [entity: EntityObject]
|
||||||
replyAll: [entity: EntityObject]
|
|
||||||
forward: [entity: EntityObject]
|
forward: [entity: EntityObject]
|
||||||
move: [entity: EntityObject]
|
move: [entity: EntityObject]
|
||||||
delete: [entity: EntityObject]
|
delete: [entity: EntityObject]
|
||||||
@@ -29,7 +28,6 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
// User settings
|
// User settings
|
||||||
const { getSetting } = useUser()
|
const { getSetting } = useUser()
|
||||||
const previewStore = usePreviewStore()
|
|
||||||
const mailUiStore = useMailUiStore()
|
const mailUiStore = useMailUiStore()
|
||||||
|
|
||||||
// Security overrides
|
// Security overrides
|
||||||
@@ -66,7 +64,6 @@ const effectiveSecurityLevel = computed(() => {
|
|||||||
// Preview state
|
// Preview state
|
||||||
const previewDialog = computed(() => mediaViewerComponent('dialog'))
|
const previewDialog = computed(() => mediaViewerComponent('dialog'))
|
||||||
const previewItems = computed<MediaViewerItem[]>(() => {
|
const previewItems = computed<MediaViewerItem[]>(() => {
|
||||||
if (!previewStore.availability.storage) return []
|
|
||||||
const attachments = message.value?.attachments ?? []
|
const attachments = message.value?.attachments ?? []
|
||||||
const items: MediaViewerItem[] = []
|
const items: MediaViewerItem[] = []
|
||||||
attachments.forEach((attachment, index) => {
|
attachments.forEach((attachment, index) => {
|
||||||
@@ -110,12 +107,6 @@ const handleReply = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleReplyAll = () => {
|
|
||||||
if (props.entity) {
|
|
||||||
emit('replyAll', props.entity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleForward = () => {
|
const handleForward = () => {
|
||||||
if (props.entity) {
|
if (props.entity) {
|
||||||
emit('forward', props.entity)
|
emit('forward', props.entity)
|
||||||
@@ -161,7 +152,7 @@ const handlePreview = (index: number) => {
|
|||||||
|
|
||||||
const handleViewerRetrieve = (item: MediaViewerItem): Promise<Blob> => {
|
const handleViewerRetrieve = (item: MediaViewerItem): Promise<Blob> => {
|
||||||
if (!props.entity) return Promise.reject(new Error('No message selected'))
|
if (!props.entity) return Promise.reject(new Error('No message selected'))
|
||||||
return mailUiStore.attachmentPreviewBlob(props.entity, item.meta.attachment, 'fullscreen')
|
return mailUiStore.attachmentBlob(props.entity, item.meta.attachment)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleViewerDownload = (item: MediaViewerItem) => {
|
const handleViewerDownload = (item: MediaViewerItem) => {
|
||||||
@@ -185,7 +176,6 @@ const handleViewerDownload = (item: MediaViewerItem) => {
|
|||||||
:security-level="effectiveSecurityLevel"
|
:security-level="effectiveSecurityLevel"
|
||||||
:is-security-overridden="overrideSecurityLevel !== null"
|
:is-security-overridden="overrideSecurityLevel !== null"
|
||||||
@reply="handleReply"
|
@reply="handleReply"
|
||||||
@reply-all="handleReplyAll"
|
|
||||||
@forward="handleForward"
|
@forward="handleForward"
|
||||||
@move="handleMove"
|
@move="handleMove"
|
||||||
@delete="handleDelete"
|
@delete="handleDelete"
|
||||||
|
|||||||
@@ -9,14 +9,6 @@ defineProps({
|
|||||||
type: Object as PropType<Editor | null>,
|
type: Object as PropType<Editor | null>,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
format: {
|
|
||||||
type: String as PropType<'rich' | 'plain'>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
isBoldActive: {
|
isBoldActive: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: true,
|
||||||
@@ -50,8 +42,6 @@ const emit = defineEmits<{
|
|||||||
bulletList: []
|
bulletList: []
|
||||||
orderedList: []
|
orderedList: []
|
||||||
link: []
|
link: []
|
||||||
toggleFormat: []
|
|
||||||
'update:text': [value: string]
|
|
||||||
attachFromDevice: [files: File[]]
|
attachFromDevice: [files: File[]]
|
||||||
attachFromDocuments: []
|
attachFromDocuments: []
|
||||||
}>()
|
}>()
|
||||||
@@ -76,84 +66,68 @@ function handleFileChange(event: Event) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-toolbar density="compact" elevation="0" class="editor-toolbar">
|
<v-toolbar density="compact" elevation="0" class="editor-toolbar">
|
||||||
<template v-if="format === 'rich'">
|
<v-btn
|
||||||
<v-btn
|
icon
|
||||||
icon
|
size="small"
|
||||||
size="small"
|
:class="{ 'v-btn--active': isBoldActive }"
|
||||||
:class="{ 'v-btn--active': isBoldActive }"
|
@click="$emit('bold')"
|
||||||
@click="$emit('bold')"
|
>
|
||||||
>
|
<v-icon>mdi-format-bold</v-icon>
|
||||||
<v-icon>mdi-format-bold</v-icon>
|
<v-tooltip activator="parent" location="bottom">Bold</v-tooltip>
|
||||||
<v-tooltip activator="parent" location="bottom">Bold</v-tooltip>
|
</v-btn>
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
icon
|
|
||||||
size="small"
|
|
||||||
:class="{ 'v-btn--active': isItalicActive }"
|
|
||||||
@click="$emit('italic')"
|
|
||||||
>
|
|
||||||
<v-icon>mdi-format-italic</v-icon>
|
|
||||||
<v-tooltip activator="parent" location="bottom">Italic</v-tooltip>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
icon
|
|
||||||
size="small"
|
|
||||||
:class="{ 'v-btn--active': isUnderlineActive }"
|
|
||||||
@click="$emit('underline')"
|
|
||||||
>
|
|
||||||
<v-icon>mdi-format-underline</v-icon>
|
|
||||||
<v-tooltip activator="parent" location="bottom">Underline</v-tooltip>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-divider vertical class="mx-2" />
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
icon
|
|
||||||
size="small"
|
|
||||||
:class="{ 'v-btn--active': isBulletListActive }"
|
|
||||||
@click="$emit('bulletList')"
|
|
||||||
>
|
|
||||||
<v-icon>mdi-format-list-bulleted</v-icon>
|
|
||||||
<v-tooltip activator="parent" location="bottom">Bullet List</v-tooltip>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
icon
|
|
||||||
size="small"
|
|
||||||
:class="{ 'v-btn--active': isOrderedListActive }"
|
|
||||||
@click="$emit('orderedList')"
|
|
||||||
>
|
|
||||||
<v-icon>mdi-format-list-numbered</v-icon>
|
|
||||||
<v-tooltip activator="parent" location="bottom">Numbered List</v-tooltip>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-divider vertical class="mx-2" />
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
icon
|
|
||||||
size="small"
|
|
||||||
:class="{ 'v-btn--active': isLinkActive }"
|
|
||||||
@click="$emit('link')"
|
|
||||||
>
|
|
||||||
<v-icon>mdi-link</v-icon>
|
|
||||||
<v-tooltip activator="parent" location="bottom">Link</v-tooltip>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-divider vertical class="mx-2" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
icon
|
icon
|
||||||
size="small"
|
size="small"
|
||||||
:class="{ 'v-btn--active': format === 'plain' }"
|
:class="{ 'v-btn--active': isItalicActive }"
|
||||||
@click="$emit('toggleFormat')"
|
@click="$emit('italic')"
|
||||||
>
|
>
|
||||||
<v-icon>{{ format === 'plain' ? 'mdi-format-text' : 'mdi-code-tags' }}</v-icon>
|
<v-icon>mdi-format-italic</v-icon>
|
||||||
<v-tooltip activator="parent" location="bottom">
|
<v-tooltip activator="parent" location="bottom">Italic</v-tooltip>
|
||||||
{{ format === 'plain' ? 'Rich Text' : 'Plain Text' }}
|
</v-btn>
|
||||||
</v-tooltip>
|
|
||||||
|
<v-btn
|
||||||
|
icon
|
||||||
|
size="small"
|
||||||
|
:class="{ 'v-btn--active': isUnderlineActive }"
|
||||||
|
@click="$emit('underline')"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-format-underline</v-icon>
|
||||||
|
<v-tooltip activator="parent" location="bottom">Underline</v-tooltip>
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<v-divider vertical class="mx-2" />
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
icon
|
||||||
|
size="small"
|
||||||
|
:class="{ 'v-btn--active': isBulletListActive }"
|
||||||
|
@click="$emit('bulletList')"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-format-list-bulleted</v-icon>
|
||||||
|
<v-tooltip activator="parent" location="bottom">Bullet List</v-tooltip>
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
icon
|
||||||
|
size="small"
|
||||||
|
:class="{ 'v-btn--active': isOrderedListActive }"
|
||||||
|
@click="$emit('orderedList')"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-format-list-numbered</v-icon>
|
||||||
|
<v-tooltip activator="parent" location="bottom">Numbered List</v-tooltip>
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<v-divider vertical class="mx-2" />
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
icon
|
||||||
|
size="small"
|
||||||
|
:class="{ 'v-btn--active': isLinkActive }"
|
||||||
|
@click="$emit('link')"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-link</v-icon>
|
||||||
|
<v-tooltip activator="parent" location="bottom">Link</v-tooltip>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
@@ -180,17 +154,7 @@ function handleFileChange(event: Event) {
|
|||||||
<v-divider />
|
<v-divider />
|
||||||
|
|
||||||
<div class="editor-container">
|
<div class="editor-container">
|
||||||
<EditorContent v-if="format === 'rich'" :editor="editor ?? undefined" />
|
<EditorContent :editor="editor ?? undefined" />
|
||||||
<v-textarea
|
|
||||||
v-else
|
|
||||||
:model-value="text"
|
|
||||||
variant="plain"
|
|
||||||
auto-grow
|
|
||||||
hide-details
|
|
||||||
placeholder="Write your message..."
|
|
||||||
class="text-editor pa-4"
|
|
||||||
@update:model-value="$emit('update:text', $event)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -215,11 +179,6 @@ function handleFileChange(event: Event) {
|
|||||||
color: rgb(var(--v-theme-primary));
|
color: rgb(var(--v-theme-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-editor :deep(textarea) {
|
|
||||||
min-height: 300px;
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.tiptap-editor) {
|
:deep(.tiptap-editor) {
|
||||||
outline: none;
|
outline: none;
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ defineEmits<{
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-toolbar-title>
|
<v-toolbar-title>
|
||||||
{{ mode === ComposerMode.Reply ? 'Reply' : mode === ComposerMode.ReplyAll ? 'Reply All' : mode === ComposerMode.Forward ? 'Forward' : 'New Message' }}
|
{{ mode === ComposerMode.Reply ? 'Reply' : mode === ComposerMode.Forward ? 'Forward' : 'New Message' }}
|
||||||
</v-toolbar-title>
|
</v-toolbar-title>
|
||||||
|
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { usePreviewStore } from '@KTXC'
|
|
||||||
import RecipientDetails from '@/components/common/RecipientDetails.vue'
|
import RecipientDetails from '@/components/common/RecipientDetails.vue'
|
||||||
import { formatFileSize } from '@/utile/format'
|
import { formatFileSize } from '@/utile/format'
|
||||||
import { mediaViewerCanDisplay, mediaViewerComponent } from '@/services/mediaViewer'
|
import { mediaViewerCanDisplay, mediaViewerComponent } from '@/services/mediaViewer'
|
||||||
@@ -28,9 +27,7 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const mailUiStore = useMailUiStore()
|
const mailUiStore = useMailUiStore()
|
||||||
const previewStore = usePreviewStore()
|
const previewPopover = computed(() => mediaViewerComponent('popover'))
|
||||||
const previewsAvailable = computed(() => previewStore.availability.storage)
|
|
||||||
const previewPopover = computed(() => previewsAvailable.value ? mediaViewerComponent('popover') : null)
|
|
||||||
|
|
||||||
const message = computed(() => {
|
const message = computed(() => {
|
||||||
return props.entity?.properties ?? null
|
return props.entity?.properties ?? null
|
||||||
@@ -51,7 +48,7 @@ const attachmentItems = computed<AttachmentItem[]>(() =>
|
|||||||
)
|
)
|
||||||
|
|
||||||
const isPreviewable = (attachment: MessagePartInterface): boolean => {
|
const isPreviewable = (attachment: MessagePartInterface): boolean => {
|
||||||
return previewsAvailable.value && mediaViewerCanDisplay(attachment.type)
|
return mediaViewerCanDisplay(attachment.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleAttachmentClick = (attachment: MessagePartInterface, index: number): void => {
|
const handleAttachmentClick = (attachment: MessagePartInterface, index: number): void => {
|
||||||
@@ -64,7 +61,7 @@ const handleAttachmentClick = (attachment: MessagePartInterface, index: number):
|
|||||||
|
|
||||||
const handleViewerRetrieve = (item: AttachmentItem): Promise<Blob> => {
|
const handleViewerRetrieve = (item: AttachmentItem): Promise<Blob> => {
|
||||||
if (!props.entity) return Promise.reject(new Error('No message selected'))
|
if (!props.entity) return Promise.reject(new Error('No message selected'))
|
||||||
return mailUiStore.attachmentPreviewBlob(props.entity, item.meta.attachment, 'inline')
|
return mailUiStore.attachmentBlob(props.entity, item.meta.attachment)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format date for display
|
// Format date for display
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const props = defineProps<Props>()
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
reply: []
|
reply: []
|
||||||
replyAll: []
|
|
||||||
forward: []
|
forward: []
|
||||||
move: []
|
move: []
|
||||||
delete: []
|
delete: []
|
||||||
@@ -48,7 +47,7 @@ const currentSecurityLevel = computed(() => {
|
|||||||
<v-btn
|
<v-btn
|
||||||
icon="mdi-reply-all"
|
icon="mdi-reply-all"
|
||||||
variant="text"
|
variant="text"
|
||||||
@click="emit('replyAll')"
|
@click="emit('reply')"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-reply-all</v-icon>
|
<v-icon>mdi-reply-all</v-icon>
|
||||||
<v-tooltip activator="parent" location="bottom">Reply All</v-tooltip>
|
<v-tooltip activator="parent" location="bottom">Reply All</v-tooltip>
|
||||||
|
|||||||
+11
-16
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref, unref, watch } from 'vue'
|
import { computed, onMounted, ref, unref } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import { useModuleStore } from '@KTXC'
|
import { useModuleStore } from '@KTXC'
|
||||||
@@ -41,8 +41,6 @@ const {
|
|||||||
loading,
|
loading,
|
||||||
selectedMessage,
|
selectedMessage,
|
||||||
currentMessages,
|
currentMessages,
|
||||||
searchResults,
|
|
||||||
searching,
|
|
||||||
} = storeToRefs(mailOperationsStore)
|
} = storeToRefs(mailOperationsStore)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -76,19 +74,21 @@ const {
|
|||||||
// Complex store/composable objects accessed directly (not simple refs)
|
// Complex store/composable objects accessed directly (not simple refs)
|
||||||
const { mailSync, entitiesStore } = mailOperationsStore
|
const { mailSync, entitiesStore } = mailOperationsStore
|
||||||
|
|
||||||
// Message search — debounced server-side search of the selected folder
|
// Message search (filters the current message list by subject/sender)
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('')
|
||||||
|
|
||||||
watch(searchQuery, query => mailOperationsStore.searchMessages(query))
|
const filteredMessages = computed(() => {
|
||||||
|
const query = (searchQuery.value ?? '').trim().toLowerCase()
|
||||||
|
if (!query) return currentMessages.value
|
||||||
|
|
||||||
// Reset the search box when the folder changes so it doesn't show a stale
|
return currentMessages.value.filter((message: EntityObject) => {
|
||||||
// query for a folder whose results are no longer being filtered.
|
const subject = (message.properties.subject || '').toLowerCase()
|
||||||
watch(selectedFolder, () => {
|
const fromLabel = (message.properties.from?.label || '').toLowerCase()
|
||||||
searchQuery.value = ''
|
const fromAddress = (message.properties.from?.address || '').toLowerCase()
|
||||||
|
return subject.includes(query) || fromLabel.includes(query) || fromAddress.includes(query)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const filteredMessages = computed(() => searchResults.value ?? currentMessages.value)
|
|
||||||
|
|
||||||
const lastSyncLabel = computed(() => {
|
const lastSyncLabel = computed(() => {
|
||||||
const lastSync = unref(unref(mailSync.lastSync))
|
const lastSync = unref(unref(mailSync.lastSync))
|
||||||
|
|
||||||
@@ -167,8 +167,6 @@ const handleMessageComposeFresh = () => mailUiStore.openComposer()
|
|||||||
|
|
||||||
const handleMessageComposeReply = (message: EntityObject) => mailUiStore.openComposer(message, ComposerMode.Reply)
|
const handleMessageComposeReply = (message: EntityObject) => mailUiStore.openComposer(message, ComposerMode.Reply)
|
||||||
|
|
||||||
const handleMessageComposeReplyAll = (message: EntityObject) => mailUiStore.openComposer(message, ComposerMode.ReplyAll)
|
|
||||||
|
|
||||||
const handleMessageComposeForward = (message: EntityObject) => mailUiStore.openComposer(message, ComposerMode.Forward)
|
const handleMessageComposeForward = (message: EntityObject) => mailUiStore.openComposer(message, ComposerMode.Forward)
|
||||||
|
|
||||||
const handleMessageComposeClose = () => mailUiStore.closeComposer()
|
const handleMessageComposeClose = () => mailUiStore.closeComposer()
|
||||||
@@ -252,7 +250,6 @@ const handleMessageSelectionDelete = () => mailUiStore.deleteSelectedMessages()
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
placeholder="Search messages..."
|
placeholder="Search messages..."
|
||||||
prepend-inner-icon="mdi-magnify"
|
prepend-inner-icon="mdi-magnify"
|
||||||
:loading="searching"
|
|
||||||
hide-details
|
hide-details
|
||||||
single-line
|
single-line
|
||||||
clearable
|
clearable
|
||||||
@@ -311,7 +308,6 @@ const handleMessageSelectionDelete = () => mailUiStore.deleteSelectedMessages()
|
|||||||
:selection-list="selectionList"
|
:selection-list="selectionList"
|
||||||
:selection-mode="selectionMode"
|
:selection-mode="selectionMode"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:search-active="searchResults !== null"
|
|
||||||
@open="handleMessageOpen"
|
@open="handleMessageOpen"
|
||||||
@reply="handleMessageComposeReply"
|
@reply="handleMessageComposeReply"
|
||||||
@forward="handleMessageComposeForward"
|
@forward="handleMessageComposeForward"
|
||||||
@@ -343,7 +339,6 @@ const handleMessageSelectionDelete = () => mailUiStore.deleteSelectedMessages()
|
|||||||
:entity="selectedMessage"
|
:entity="selectedMessage"
|
||||||
@compose="handleMessageComposeFresh"
|
@compose="handleMessageComposeFresh"
|
||||||
@reply="handleMessageComposeReply"
|
@reply="handleMessageComposeReply"
|
||||||
@reply-all="handleMessageComposeReplyAll"
|
|
||||||
@forward="handleMessageComposeForward"
|
@forward="handleMessageComposeForward"
|
||||||
@move="handleMessageMove"
|
@move="handleMessageMove"
|
||||||
@delete="handleMessageDelete"
|
@delete="handleMessageDelete"
|
||||||
|
|||||||
@@ -118,8 +118,7 @@ export const useMailCompositionStore = defineStore('mailCompositionStore', () =>
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownAddresses = senderIdentities.value.map(identity => identity.address)
|
activeDraft.value = buildDraft(mode, sender, source)
|
||||||
activeDraft.value = buildDraft(mode, sender, source, ownAddresses)
|
|
||||||
activeDraft.value.action = mode
|
activeDraft.value.action = mode
|
||||||
|
|
||||||
stageDraft()
|
stageDraft()
|
||||||
@@ -559,9 +558,9 @@ export const useMailCompositionStore = defineStore('mailCompositionStore', () =>
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function buildDraft(mode: ComposerMode, sender: ComposerSenderIdentity, source: EntityObject | MessageAddressObject | null | undefined, ownAddresses: string[]): ComposerDraft {
|
function buildDraft(mode: ComposerMode, sender: ComposerSenderIdentity, source?: EntityObject | MessageAddressObject | null): ComposerDraft {
|
||||||
const composition = createIdentifier()
|
const composition = createIdentifier()
|
||||||
const freshMessage = buildMessage(mode, source, ownAddresses)
|
const freshMessage = buildMessage(mode, source)
|
||||||
const freshAttachments = buildAttachments(composition, mode, source)
|
const freshAttachments = buildAttachments(composition, mode, source)
|
||||||
const sourceIdentifier = source instanceof EntityObject ? source.identifier : null
|
const sourceIdentifier = source instanceof EntityObject ? source.identifier : null
|
||||||
return {
|
return {
|
||||||
@@ -577,7 +576,7 @@ function buildDraft(mode: ComposerMode, sender: ComposerSenderIdentity, source:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressObject | null | undefined, ownAddresses: string[] = []): ComposerDraftMessage {
|
function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressObject | null | undefined): ComposerDraftMessage {
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
return emptyMessage()
|
return emptyMessage()
|
||||||
@@ -604,28 +603,12 @@ function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressO
|
|||||||
const sentAt = sourceMessage.sent || source.created || ''
|
const sentAt = sourceMessage.sent || source.created || ''
|
||||||
const sentLabel = sentAt ? new Date(sentAt).toLocaleString() : 'an unknown time'
|
const sentLabel = sentAt ? new Date(sentAt).toLocaleString() : 'an unknown time'
|
||||||
|
|
||||||
if (mode === ComposerMode.Reply || mode === ComposerMode.ReplyAll) {
|
if (mode === ComposerMode.Reply) {
|
||||||
const replyToAddr = sourceMessage.replyTo?.[0] ?? sourceMessage.from ?? null
|
const replyToAddr = sourceMessage.replyTo?.[0] ?? sourceMessage.from ?? null
|
||||||
const replyToAddress = replyToAddr?.address || ''
|
const replyToAddress = replyToAddr?.address || ''
|
||||||
const to: MessageAddressInterface[] = replyToAddress ? [{ address: replyToAddress, label: replyToAddr?.label }] : []
|
|
||||||
|
|
||||||
let cc: MessageAddressInterface[] = []
|
|
||||||
if (mode === ComposerMode.ReplyAll) {
|
|
||||||
const excluded = new Set([replyToAddress.toLowerCase(), ...ownAddresses.map(addr => addr.toLowerCase())])
|
|
||||||
const seen = new Set<string>()
|
|
||||||
cc = [...(sourceMessage.to || []), ...(sourceMessage.cc || [])].filter(recipient => {
|
|
||||||
const address = recipient.address?.toLowerCase() || ''
|
|
||||||
if (!address || excluded.has(address) || seen.has(address)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
seen.add(address)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
to,
|
to: replyToAddress ? [{ address: replyToAddress, label: replyToAddr?.label }] : [],
|
||||||
cc,
|
cc: [],
|
||||||
bcc: [],
|
bcc: [],
|
||||||
subject: /^Re:/i.test(originalSubject) ? originalSubject : `Re: ${originalSubject}`,
|
subject: /^Re:/i.test(originalSubject) ? originalSubject : `Re: ${originalSubject}`,
|
||||||
body: {
|
body: {
|
||||||
@@ -648,7 +631,7 @@ function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressO
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildAttachments(composition: string, mode: ComposerMode, source?: EntityObject | MessageAddressObject | null): Record<string, ComposerDraftAttachment> {
|
function buildAttachments(composition: string, mode: ComposerMode, source?: EntityObject | MessageAddressObject | null): Record<string, ComposerDraftAttachment> {
|
||||||
if (mode === ComposerMode.Fresh || mode === ComposerMode.Reply || mode === ComposerMode.ReplyAll || !(source instanceof EntityObject)) {
|
if (mode === ComposerMode.Fresh || mode === ComposerMode.Reply || !(source instanceof EntityObject)) {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import { useCollectionsStore } from '@MailManager/stores/collectionsStore'
|
|||||||
import { useEntitiesStore } from '@MailManager/stores/entitiesStore'
|
import { useEntitiesStore } from '@MailManager/stores/entitiesStore'
|
||||||
import { useServicesStore } from '@MailManager/stores/servicesStore'
|
import { useServicesStore } from '@MailManager/stores/servicesStore'
|
||||||
import { useMailSync } from '@MailManager/composables/useMailSync'
|
import { useMailSync } from '@MailManager/composables/useMailSync'
|
||||||
import type { ServiceIdentifier, CollectionIdentifier, EntityIdentifier, ListFilter } from '@MailManager/types/common'
|
import type { ServiceIdentifier, CollectionIdentifier, EntityIdentifier } from '@MailManager/types/common'
|
||||||
import { ListFilterComparisonOperator, ListFilterConjunctionOperator } from '@MailManager/types/common'
|
|
||||||
import type { EntityTransmitRequest, EntityBlobSelector } from '@MailManager/types/entity'
|
import type { EntityTransmitRequest, EntityBlobSelector } from '@MailManager/types/entity'
|
||||||
import type { MessageAddressInterface, MessageInterface, MessagePartInterface } from '@MailManager/types/message'
|
import type { MessageAddressInterface, MessageInterface, MessagePartInterface } from '@MailManager/types/message'
|
||||||
import { ServiceObject, type CollectionObject, type EntityObject } from '@MailManager/models'
|
import { ServiceObject, type CollectionObject, type EntityObject } from '@MailManager/models'
|
||||||
@@ -51,8 +50,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
|
|||||||
|
|
||||||
const selectedFolder = shallowRef<CollectionObject | null>(null)
|
const selectedFolder = shallowRef<CollectionObject | null>(null)
|
||||||
const selectedMessage = shallowRef<EntityObject | null>(null)
|
const selectedMessage = shallowRef<EntityObject | null>(null)
|
||||||
const searchResults = shallowRef<EntityObject[] | null>(null)
|
|
||||||
const searching = ref(false)
|
|
||||||
const composerSaving = ref(false)
|
const composerSaving = ref(false)
|
||||||
const composerSending = ref(false)
|
const composerSending = ref(false)
|
||||||
const composerLastSaved = ref<Date | null>(null)
|
const composerLastSaved = ref<Date | null>(null)
|
||||||
@@ -296,7 +293,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function selectFolder(folder: CollectionObject | null) {
|
async function selectFolder(folder: CollectionObject | null) {
|
||||||
clearSearch()
|
|
||||||
selectedFolder.value = folder
|
selectedFolder.value = folder
|
||||||
selectedMessage.value = null
|
selectedMessage.value = null
|
||||||
|
|
||||||
@@ -311,67 +307,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
|
|||||||
_updateSyncSources()
|
_updateSyncSources()
|
||||||
}
|
}
|
||||||
|
|
||||||
const SEARCH_DEBOUNCE_MS = 300
|
|
||||||
let searchDebounceTimer: ReturnType<typeof setTimeout> | null = null
|
|
||||||
// Monotonic token so out-of-order/stale search responses are discarded.
|
|
||||||
let searchToken = 0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Debounced server-side search of the selected folder. Clearing the query
|
|
||||||
* (or the folder) reverts the message list back to `currentMessages`.
|
|
||||||
*/
|
|
||||||
function searchMessages(query: string) {
|
|
||||||
const trimmed = (query ?? '').trim()
|
|
||||||
|
|
||||||
if (searchDebounceTimer) {
|
|
||||||
clearTimeout(searchDebounceTimer)
|
|
||||||
searchDebounceTimer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!trimmed || !selectedFolder.value) {
|
|
||||||
searchToken++
|
|
||||||
searchResults.value = null
|
|
||||||
searching.value = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const folder = selectedFolder.value
|
|
||||||
// 'from'/'to'/'subject'/'body' are the attributes both IMAP and JMAP
|
|
||||||
// backends whitelist for entity search (see their entityListFilter
|
|
||||||
// capability); OR them together for a single-box search.
|
|
||||||
const filter: ListFilter = {
|
|
||||||
from: [trimmed, ListFilterComparisonOperator.LIKE],
|
|
||||||
to: [trimmed, ListFilterComparisonOperator.LIKE, ListFilterConjunctionOperator.OR],
|
|
||||||
subject: [trimmed, ListFilterComparisonOperator.LIKE, ListFilterConjunctionOperator.OR],
|
|
||||||
body: [trimmed, ListFilterComparisonOperator.LIKE, ListFilterConjunctionOperator.OR],
|
|
||||||
}
|
|
||||||
searching.value = true
|
|
||||||
const token = ++searchToken
|
|
||||||
|
|
||||||
searchDebounceTimer = setTimeout(async () => {
|
|
||||||
try {
|
|
||||||
const results = await entitiesStore.list([folder.identifier], filter)
|
|
||||||
if (token !== searchToken) return
|
|
||||||
searchResults.value = Object.values(results)
|
|
||||||
} catch (error) {
|
|
||||||
if (token === searchToken) searchResults.value = []
|
|
||||||
console.error('[Mail][Operations] Failed to search messages:', error)
|
|
||||||
} finally {
|
|
||||||
if (token === searchToken) searching.value = false
|
|
||||||
}
|
|
||||||
}, SEARCH_DEBOUNCE_MS)
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearSearch() {
|
|
||||||
if (searchDebounceTimer) {
|
|
||||||
clearTimeout(searchDebounceTimer)
|
|
||||||
searchDebounceTimer = null
|
|
||||||
}
|
|
||||||
searchToken++
|
|
||||||
searchResults.value = null
|
|
||||||
searching.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectMessage(entity: EntityObject | null) {
|
function selectMessage(entity: EntityObject | null) {
|
||||||
selectedMessage.value = entity
|
selectedMessage.value = entity
|
||||||
}
|
}
|
||||||
@@ -640,24 +575,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
|
|||||||
return blob
|
return blob
|
||||||
}
|
}
|
||||||
|
|
||||||
async function attachmentPreviewBlob(
|
|
||||||
entity: EntityObject,
|
|
||||||
part: MessagePartInterface,
|
|
||||||
variant: 'inline' | 'fullscreen' = 'inline',
|
|
||||||
): Promise<Blob> {
|
|
||||||
return entitiesStore.preview({
|
|
||||||
target: entity.identifier,
|
|
||||||
part: {
|
|
||||||
blobId: part.blobId ?? undefined,
|
|
||||||
partId: part.partId ?? undefined,
|
|
||||||
cid: part.cid ?? undefined,
|
|
||||||
type: part.type || 'application/octet-stream',
|
|
||||||
size: part.size ?? null,
|
|
||||||
},
|
|
||||||
variant,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Exports ───────────────────────────────────────────────────────────────
|
// ── Exports ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -670,8 +587,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
|
|||||||
// State
|
// State
|
||||||
loading,
|
loading,
|
||||||
selectedMessage,
|
selectedMessage,
|
||||||
searchResults,
|
|
||||||
searching,
|
|
||||||
composerSaving,
|
composerSaving,
|
||||||
composerSending,
|
composerSending,
|
||||||
composerLastSaved,
|
composerLastSaved,
|
||||||
@@ -687,8 +602,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
|
|||||||
retrieveService,
|
retrieveService,
|
||||||
selectFolder,
|
selectFolder,
|
||||||
selectMessage,
|
selectMessage,
|
||||||
searchMessages,
|
|
||||||
clearSearch,
|
|
||||||
createFolder,
|
createFolder,
|
||||||
saveComposerDraft,
|
saveComposerDraft,
|
||||||
sendComposerMessage,
|
sendComposerMessage,
|
||||||
@@ -699,7 +612,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
|
|||||||
moveMessages,
|
moveMessages,
|
||||||
downloadMessage,
|
downloadMessage,
|
||||||
attachmentBlob,
|
attachmentBlob,
|
||||||
attachmentPreviewBlob,
|
|
||||||
moveFolder,
|
moveFolder,
|
||||||
renameFolder,
|
renameFolder,
|
||||||
isServiceFolderLoading,
|
isServiceFolderLoading,
|
||||||
|
|||||||
@@ -714,14 +714,6 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
|
|||||||
return mailOperationsStore.attachmentBlob(entity, part)
|
return mailOperationsStore.attachmentBlob(entity, part)
|
||||||
}
|
}
|
||||||
|
|
||||||
function attachmentPreviewBlob(
|
|
||||||
entity: EntityObject,
|
|
||||||
part: Parameters<typeof mailOperationsStore.attachmentPreviewBlob>[1],
|
|
||||||
variant: 'inline' | 'fullscreen' = 'inline',
|
|
||||||
) {
|
|
||||||
return mailOperationsStore.attachmentPreviewBlob(entity, part, variant)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sidebarVisible,
|
sidebarVisible,
|
||||||
settingsDialogVisible,
|
settingsDialogVisible,
|
||||||
@@ -771,7 +763,6 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
|
|||||||
moveMessages,
|
moveMessages,
|
||||||
downloadMessage,
|
downloadMessage,
|
||||||
attachmentBlob,
|
attachmentBlob,
|
||||||
attachmentPreviewBlob,
|
|
||||||
messageSelectionModeActivate,
|
messageSelectionModeActivate,
|
||||||
messageSelectionModeDeactivate,
|
messageSelectionModeDeactivate,
|
||||||
messageSelectionToggleOne,
|
messageSelectionToggleOne,
|
||||||
@@ -797,4 +788,4 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
|
|||||||
confirmDeleteFolder,
|
confirmDeleteFolder,
|
||||||
flagSelectedMessages,
|
flagSelectedMessages,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -5,13 +5,9 @@ import type { MessageAddressInterface } from "@MailManager/types/message"
|
|||||||
export enum ComposerMode {
|
export enum ComposerMode {
|
||||||
Fresh = 'fresh',
|
Fresh = 'fresh',
|
||||||
Reply = 'reply',
|
Reply = 'reply',
|
||||||
ReplyAll = 'replyAll',
|
|
||||||
Forward = 'forward',
|
Forward = 'forward',
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Body editing format: rich (Tiptap/HTML) or plain text. */
|
|
||||||
export type ComposerFormat = 'rich' | 'plain'
|
|
||||||
|
|
||||||
export interface ComposerDraftAttachment {
|
export interface ComposerDraftAttachment {
|
||||||
identifier: string
|
identifier: string
|
||||||
composition: string
|
composition: string
|
||||||
|
|||||||
Reference in New Issue
Block a user