1 Commits

Author SHA1 Message Date
Sebastian e13454e421 chore(deps): update tiptap monorepo to v3.30.5
Build Test / test (pull_request) Successful in 1m29s
JS Unit Tests / test (pull_request) Successful in 1m31s
PHP Integration Tests / Integration Tests (pull_request) Failing after 1m51s
PHP Unit Tests / test (pull_request) Failing after 2m14s
2026-08-27 03:01:53 +00:00
16 changed files with 336 additions and 576 deletions
Generated
+34 -46
View File
@@ -9,20 +9,20 @@
"packages-dev": [
{
"name": "myclabs/deep-copy",
"version": "1.14.0",
"version": "1.13.4",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae"
"reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae",
"reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
"reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
"shasum": ""
},
"require": {
"php": "^8.0"
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
@@ -57,15 +57,15 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.14.0"
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
},
"funding": [
{
"url": "https://github.com/mnapoli",
"type": "github"
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2026-08-11T10:17:44+00:00"
"time": "2025-08-01T08:46:24+00:00"
},
{
"name": "nikic/php-parser",
@@ -332,23 +332,23 @@
},
{
"name": "phpunit/php-file-iterator",
"version": "6.0.2",
"version": "6.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "a248d1640ab059b075f53a2ef0f9856e864e06b5"
"reference": "3d1cd096ef6bea4bf2762ba586e35dbd317cbfd5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a248d1640ab059b075f53a2ef0f9856e864e06b5",
"reference": "a248d1640ab059b075f53a2ef0f9856e864e06b5",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3d1cd096ef6bea4bf2762ba586e35dbd317cbfd5",
"reference": "3d1cd096ef6bea4bf2762ba586e35dbd317cbfd5",
"shasum": ""
},
"require": {
"php": ">=8.3"
},
"require-dev": {
"phpunit/phpunit": "^12.5.33"
"phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
@@ -381,7 +381,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.2"
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.1"
},
"funding": [
{
@@ -401,7 +401,7 @@
"type": "tidelift"
}
],
"time": "2026-08-25T14:40:53+00:00"
"time": "2026-02-02T14:04:18+00:00"
},
{
"name": "phpunit/php-invoker",
@@ -589,16 +589,16 @@
},
{
"name": "phpunit/phpunit",
"version": "12.5.35",
"version": "12.5.31",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "345ac22e42cb14cdc7aa8428655d8bb8c82a4aab"
"reference": "0608d157a284f15cc73b99a3327eff06b66a176d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/345ac22e42cb14cdc7aa8428655d8bb8c82a4aab",
"reference": "345ac22e42cb14cdc7aa8428655d8bb8c82a4aab",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0608d157a284f15cc73b99a3327eff06b66a176d",
"reference": "0608d157a284f15cc73b99a3327eff06b66a176d",
"shasum": ""
},
"require": {
@@ -608,18 +608,18 @@
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.14.0",
"myclabs/deep-copy": "^1.13.4",
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.3",
"phpunit/php-code-coverage": "^12.5.7",
"phpunit/php-file-iterator": "^6.0.2",
"phpunit/php-file-iterator": "^6.0.1",
"phpunit/php-invoker": "^6.0.0",
"phpunit/php-text-template": "^5.0.0",
"phpunit/php-timer": "^8.0.0",
"sebastian/cli-parser": "^4.2.1",
"sebastian/comparator": "^7.1.8",
"sebastian/diff": "^7.0.1",
"sebastian/diff": "^7.0.0",
"sebastian/environment": "^8.1.2",
"sebastian/exporter": "^7.0.3",
"sebastian/global-state": "^8.0.3",
@@ -667,7 +667,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.35"
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.31"
},
"funding": [
{
@@ -675,7 +675,7 @@
"type": "other"
}
],
"time": "2026-09-09T04:48:50+00:00"
"time": "2026-07-06T14:54:16+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -898,24 +898,24 @@
},
{
"name": "sebastian/diff",
"version": "7.0.1",
"version": "7.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "cd4cabe39f8a4e8ee6818ba99f10a05561ea4ad6"
"reference": "7ab1ea946c012266ca32390913653d844ecd085f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/cd4cabe39f8a4e8ee6818ba99f10a05561ea4ad6",
"reference": "cd4cabe39f8a4e8ee6818ba99f10a05561ea4ad6",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f",
"reference": "7ab1ea946c012266ca32390913653d844ecd085f",
"shasum": ""
},
"require": {
"php": ">=8.3"
},
"require-dev": {
"phpunit/phpunit": "^12.5.33",
"symfony/process": "^7.4.17"
"phpunit/phpunit": "^12.0",
"symfony/process": "^7.2"
},
"type": "library",
"extra": {
@@ -953,27 +953,15 @@
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"security": "https://github.com/sebastianbergmann/diff/security/policy",
"source": "https://github.com/sebastianbergmann/diff/tree/7.0.1"
"source": "https://github.com/sebastianbergmann/diff/tree/7.0.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/sebastian/diff",
"type": "tidelift"
}
],
"time": "2026-08-25T15:35:54+00:00"
"time": "2025-02-07T04:55:46+00:00"
},
{
"name": "sebastian/environment",
@@ -1710,5 +1698,5 @@
"php": ">=8.3"
},
"platform-dev": {},
"plugin-api-version": "2.9.0"
"plugin-api-version": "2.6.0"
}
+4 -4
View File
@@ -80,8 +80,8 @@ final class CompositionController extends ControllerAbstract {
if (!isset($data['action']) || !is_string($data['action'])) {
throw new InvalidArgumentException('Invalid parameter: action must be a string');
}
if (!in_array($data['action'], ['fresh', 'reply', 'replyAll', 'forward'], true)) {
throw new InvalidArgumentException('Invalid parameter: action must be one of fresh, reply, replyAll, forward');
if (!in_array($data['action'], ['fresh', 'reply', 'forward'], true)) {
throw new InvalidArgumentException('Invalid parameter: action must be one of fresh, reply, forward');
}
if (!isset($data['sender']) || !is_array($data['sender'])) {
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'])) {
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'] === '')) {
throw new InvalidArgumentException('Invalid parameter: source must be a non-empty string for reply, replyAll, or forward action');
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 or forward action');
}
return $this->compositionManager->stage($tenantId, $userId, $data['identifier'], $data['action'], $data['sender'], $data['message'], $data['source'] ?? null);
+12 -7
View File
@@ -4,14 +4,13 @@ namespace KTXM\Mail;
use KTXF\Event\DeliveryMode;
use KTXF\Event\EventListenerRegistrarInterface;
use KTXF\Module\Configuration\BrowserModuleContextInterface;
use KTXF\Module\Configuration\ModuleContextInterface;
use KTXF\Module\ModuleBrowserInterface;
use KTXF\Module\ModuleInstanceAbstract;
/**
* Mail Module - Email Client
*/
class Module extends ModuleInstanceAbstract
class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
{
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) {
$context->registerModule($this, 'Mail', 'static/module.mjs');
}
return [
'handle' => $this->handle(),
'namespace' => 'Mail',
'version' => $this->version(),
'label' => $this->label(),
'author' => $this->author(),
'description' => $this->description(),
'boot' => 'static/module.mjs',
];
}
}
+198 -198
View File
@@ -795,49 +795,49 @@
"license": "MIT"
},
"node_modules/@tiptap/core": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.29.0.tgz",
"integrity": "sha512-A/lrhKpOYtl0V5pmPS00Zps8pgBe1qDOoD9fzsumDSZ3HP8W398C959Jgru75PNFokAya9COPD3iaKP3NWF25g==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.30.5.tgz",
"integrity": "sha512-3O7N0FyKIfuLV+xrdWyDM3V5eUY/q2CgLjhhMwOAbM1Pu7VPp9VP+TpEYOdH8aRyB+h1vj5hX5A747D8ZrPfHA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/pm": "3.29.0"
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/extension-blockquote": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.29.0.tgz",
"integrity": "sha512-k8NKHLEYOqre7guObZBeFM04CaTwmEceCmdIrIjd7H9KoHSbRODaBNved6j5G33x/FWMwIF/RQbE2BjWaFSgzA==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.30.5.tgz",
"integrity": "sha512-8pf1ZDrl6XlVPUee/2YlWZPFSF7yqsJEX6WLW41x06MT1dapG3Qudcns0znj6kYsX8JXTJ+Mhegy4z19bvTtRg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0",
"@tiptap/pm": "3.29.0"
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/extension-bold": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.29.0.tgz",
"integrity": "sha512-BPUJvJ9sCsU3fxao5UJfDJrDuHhMn2hczZwZ9Qs4w1vkAeLGyOYbSejUTJdBYHLoexGiEwgnEeVeZN3C8GaI5g==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.30.5.tgz",
"integrity": "sha512-MLZS+s/BJiJbv2C2M3G4FQGn43kPwYUUr2TiW3afSn+dRkEZlDxx5CwZYbe1PEt2+VX/SIifn945Oqr3s0axSA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-bubble-menu": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.29.0.tgz",
"integrity": "sha512-aBNI8ebX76ObderRmu/PJ9Q2AGVEuhpg0TBvv2SNbHtmU5kNUMHQI8HxrxKFblJwETAmG6EJ3Ed/5jRxpJmrsg==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.30.5.tgz",
"integrity": "sha512-redcmBInVwmipjF/WEVcNwCUJgJygUv8leidfRb/jBSAwx7GgnQWPr2HVQDk9zeTt3ykWld2NRdrk94Crjymow==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -848,67 +848,80 @@
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0",
"@tiptap/pm": "3.29.0"
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/extension-bullet-list": {
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.30.5.tgz",
"integrity": "sha512-66OGw4suO0Gr/4QAEiSvVi0eSvEqStvu1moHUSvUlwvEqnuB0ME2w9HuRogPElzWdrYLzbBA47mlCi9Veva0ew==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/extension-list": "3.30.5"
}
},
"node_modules/@tiptap/extension-code": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.29.0.tgz",
"integrity": "sha512-Um0BlyunRJ8Fal288Jn7I2n15FRwQcTy3NnKBBrPz3ikwx+yZZ0n9xTozpLMSxXrTq6cRlxLkASp/9FFx9sX9A==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.30.5.tgz",
"integrity": "sha512-0dCt8eBo4sMtw+LjUu+0GF0JrTlREROdWoy8TM5kFPxJ5ZU2LKDiROXDPwXStaaoFFR/aStLH9xSpdz7cHUiUA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-code-block": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.29.0.tgz",
"integrity": "sha512-nKm1YSEiPVosjm4qeg6m+6SAKq82rKukAzE/g3M5eVs2OgEb4QIKQvQOmJ+zgGAnpb9Q/JIvcKsGGU1rn9Vnyw==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.30.5.tgz",
"integrity": "sha512-SvkNoOio2xBy9AtSMyFKMp88MTUvyIXsGCnuz71INV2wHdH4VfRPoQLT6e077LpTCa9w6LHyTKtbZA4HYOp7wg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0",
"@tiptap/pm": "3.29.0"
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/extension-document": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.29.0.tgz",
"integrity": "sha512-folTlrwmUL+WSnojvfjZ951Gb25Pw8BxjXwhvXFuZXJ92qMfOcezA480kwFuu5nG8pPc/76ezQlz9a86Y5uQJw==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.30.5.tgz",
"integrity": "sha512-4mKoD3bBr5W2AQ2Y/7amOqcVw0eqJbUwRtwvxypeo5Hi0PB9O5Ev8P05c3EUTo10bllqdKYXGeCU5AcgdQsHWQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-dropcursor": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.29.0.tgz",
"integrity": "sha512-IAY21q7KSXyCXN3u13kfpq0E8D2i3r9nSbsNYlLzkEv0Bpn+pWShZi05A0ubuothDNjdaMa96xaRY0f1y9gDZw==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.30.5.tgz",
"integrity": "sha512-gJxn9PMUee8zazQBYqbOZiI7zTFXPVJ15AzTnLfUu4eDtPieMwtpgcjhCt4bZlp37drLm+Li76wWLirb7iLxsw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/extensions": "3.29.0"
"@tiptap/extensions": "3.30.5"
}
},
"node_modules/@tiptap/extension-floating-menu": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.29.0.tgz",
"integrity": "sha512-/rFlN6T70HuT34kFvftKm56UX0IPff7vlII7Sqgs7DprKVYkItiU3lM7+AoeDRzCsWMg4z1yNHj70BPx7+EJ6Q==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.30.5.tgz",
"integrity": "sha512-gTjGPWUpGn8IoW533TciZJZC/81LmBgU7zee+aRMRF3ix3K2z1pJjl6knDvrRQA6Kom+yWFaiueqGNXkrk38XQ==",
"license": "MIT",
"optional": true,
"funding": {
@@ -917,80 +930,80 @@
},
"peerDependencies": {
"@floating-ui/dom": "^1.0.0",
"@tiptap/core": "3.29.0",
"@tiptap/pm": "3.29.0"
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/extension-gapcursor": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.29.0.tgz",
"integrity": "sha512-Jz0zwriGxPMuRjKo6x7WhPa/7pZn0dovyJu/GLarN4T+mMseGNXWwEBsLEKkuumsJVPDEPPFjX+rzEeaFKInPQ==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.30.5.tgz",
"integrity": "sha512-h3m2ZA1XXLAfdHwdtG0MZnf0KWbNyP8xTI3RUlTDR5apmKmYVBaeocOJwTcFFZ92gPKqxYKyhteZqYtHOCZGJA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/extensions": "3.29.0"
"@tiptap/extensions": "3.30.5"
}
},
"node_modules/@tiptap/extension-hard-break": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.29.0.tgz",
"integrity": "sha512-8qKj0oeuU7IYoG73Lj3W4EC/JS/dFjN5iHmc4yodqppP6qs0o2zsF/2ipceGN/REZq5megPtxRgXu/nxQZ1NYg==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.30.5.tgz",
"integrity": "sha512-PcL4Z8l/DlauwZUJg0jf6SXKk6/YOXJtd8yYzqHrmCLRoY4kAa7+TxUhc/lWhuitUiOZ8+nB8V/NNM+WR6mRaw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-heading": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.29.0.tgz",
"integrity": "sha512-xWb3QEKo7cp9u6Vzi6oYKODra6jPwziHBv3fJAnxWpRldxtJqfyOVMikWJJFuDjmr+K0qyegzf206pMk+y0bDg==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.30.5.tgz",
"integrity": "sha512-x7e7+p1bWXvwz6vqONPP1SVB73V0gZP7LIDL/5KMnxWLjahMTabgVPgjV30kz7GsOEgUYtEf7eCyGVGNNWL5Dg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-horizontal-rule": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.29.0.tgz",
"integrity": "sha512-u1OgncXkokIuUJQIh4jVQfYHL/6I8VnrokUcCud4eErWvgeLnCbNmVdih4kxIdfmvEyAxXjDwcqf4AB79TxuNg==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.30.5.tgz",
"integrity": "sha512-s5t2xM6wPYRJl2cqYplc7Ze8m8xddk4DP2v0aLFcUuD100D1B5eJbxsiwLK6wBAzNwiuVjd486RnmUpcswaXhQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0",
"@tiptap/pm": "3.29.0"
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/extension-italic": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.29.0.tgz",
"integrity": "sha512-c8gF+zM7yXB9iGxtVCioYecjQ+A2fLlNa1XYBYbTobNhbUo8a11akbTkGNcCIgttwnzwEoI4mB6/PK4yjaQvVg==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.30.5.tgz",
"integrity": "sha512-Fu9EuSRlHQNGES7UhY4mQod3yUKnWwxsGlPuDJURfwju/Ug04Jz8iRuERZBPcRgLNkwKDmbDsWUZF72RRIL2Uw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-link": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.29.0.tgz",
"integrity": "sha512-FuLDgE0k1dB4WCBTelw3re9BLmiurgXVSj3d3J4l3sunljyOs941RUU62b7pWP+ePNdGF7RgUMmMAB+58VZCIA==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.30.5.tgz",
"integrity": "sha512-zsQ+q83HpCYOMTNzdjb12dggE7sZMp0aqQJhArdavSTl8hLbVY/u3qJN88t25IEwAKVK0pcTJfWWA2QFl8bjAQ==",
"license": "MIT",
"dependencies": {
"linkifyjs": "^4.3.3"
@@ -1000,106 +1013,159 @@
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0",
"@tiptap/pm": "3.29.0"
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/extension-list": {
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.30.5.tgz",
"integrity": "sha512-CHThihH+7TA0TfwtmA+eTXP1MAsA/+p011olJHg8Rilj5xA+L+0IFkjhN16JnZkBgSA4MnfEv15UMNfRaNpuVg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/extension-list-item": {
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.30.5.tgz",
"integrity": "sha512-N0fKUyQkPQBvVB48imjfIfdexU9VsAX1RydajYP2xAt+QOJ8KHVmXv1EGTp+v7pGdZMLdls1cSZ2f352vW3aWQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/extension-list": "3.30.5"
}
},
"node_modules/@tiptap/extension-list-keymap": {
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.30.5.tgz",
"integrity": "sha512-3pLR2yo29uhowaGMbD8v71XpgdNmqotBg1NXlyTMVFzxELj+VjjeLLTqSguR/iWDUbHXNzIsfMEgpRnNMO//8w==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/extension-list": "3.30.5"
}
},
"node_modules/@tiptap/extension-ordered-list": {
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.30.5.tgz",
"integrity": "sha512-bUGUnSAgjZhoUWBtr+1wRJHF3NnNvuKQr6sQ8le1tJ2yvLq448ZsSZjZGvTNeLsy3GDKBoMJ0rqLUK34+nM3hg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/extension-list": "3.30.5"
}
},
"node_modules/@tiptap/extension-paragraph": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.29.0.tgz",
"integrity": "sha512-OtGrkwzqlW+ehW+d2qrQ7VVcP9PbDeQmuT4Ec4yFjf3vR4QO8OVdVfeOcUq52PtkT3kYRxz9fzEiEvjqRm72yA==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.30.5.tgz",
"integrity": "sha512-GrNNlAImfQhYRtGE95YNAjcTclUUMPHs9JeE9vMgfcoKcOmZ6GsbWUdN0hA55xqwGaUjnroOVtf77K9z1EbkJQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-placeholder": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.29.0.tgz",
"integrity": "sha512-V2jb0kL/k3rygAtKmSPYxoyBMCQJtJikPYnxiCYuY7FI1ohmCrmhyhkVqJv0b0EPMNW8BMIqf6DgpKJ/ODmXgA==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.30.5.tgz",
"integrity": "sha512-WgkX4ImAAeV+Qe7ATJ+Gio2MmKWON1CKpCKPHWgCObaoMEaSmdoxXPmI9wXMuM+AJydJepp4n7U/V4TVts14rg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/extensions": "3.29.0"
"@tiptap/extensions": "3.30.5"
}
},
"node_modules/@tiptap/extension-strike": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.29.0.tgz",
"integrity": "sha512-VzasZkckrEXzmFQT9z3O95rUWy1b0RLFHAC6GUSQHxKk4TpP+Ujfn5+rqmPukMn0eScJyw1Y36jwfJc0VuNR+Q==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.30.5.tgz",
"integrity": "sha512-r8IbWUm4YXNCkmc6h6dzuREQIGbO0x9z9l3GfQPUR3LxFtGssDLngE4dFXHRt/ejLWKEauy6clklf7LawtvYzw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-text": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.29.0.tgz",
"integrity": "sha512-AMsf2V7IiGvzbl+LqLLfyWzufazZxHuid1gOnEt3KwolQ9AO7p8WJgHld0PZLxNyEh4SaSqK7b3d3SM9sqrlTw==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.30.5.tgz",
"integrity": "sha512-pOgj4mIGFlw4NUdA6PCTFP/MHrYWnOYiZRYeu0I3/Yo3iN4Am/CgYBLl8PWsNh+YPO2hA2DWs7ZMke9D2j5R+g==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-text-align": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-3.29.0.tgz",
"integrity": "sha512-/1htV3teqRJ7i7trAuORDg62LV0CQ1qskbMcP3SB7grsw6H1G54zwdaJVXeiIXmQKDF7FoZgY7u/v/TJckthEw==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-3.30.5.tgz",
"integrity": "sha512-nRiAXqfpnuYkxOTFmK09vKf0Obv+yYA6UvmQ2yhjaThf7/i+ncxAbmxWttAV8GEy2fGpuXxkJYtIgDXXN7tVPg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extension-underline": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.29.0.tgz",
"integrity": "sha512-DSPTogdvxmoX/L0U5KgBC9jWffRvYkGiyh1tp28gn+QaARh4iJn79pAZpi1m1bEhal/0Mq5m4ukbiO7FWInwaA==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.30.5.tgz",
"integrity": "sha512-u12G/WW2uFRY95BzrSAU9RW002K+7lFpSCL6fb7Puh8yLhek3lddOtAx0P+NI/PyMKtcoVMtBxoi+0mwVM7NPQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0"
"@tiptap/core": "3.30.5"
}
},
"node_modules/@tiptap/extensions": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.29.0.tgz",
"integrity": "sha512-ltlrm8dDHIgeNj3cOLEdLFMPPVy3TYvWA8ftrrJ44C/L01MBmgFB1f/vkPFYYnAasb2BYyVG6HxAGcTQHo5jHw==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.30.5.tgz",
"integrity": "sha512-5x3OiCYBvXz0G5OGM8f7ka++1dh9EXdNRZ8IcMcEd+QwW4RPwvmJ2EjheA1eRRyMlcbNU7T+4IRlBXURlTetEA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.29.0",
"@tiptap/pm": "3.29.0"
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5"
}
},
"node_modules/@tiptap/pm": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.29.0.tgz",
"integrity": "sha512-4rr3HiZ8kbSNINuWXqKQJLv9fFMypCBN5gOwxoU+D4lEYVblkoM60fA1SlrI2BZVlZQmw2U38XKl5XMtUr55XQ==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.30.5.tgz",
"integrity": "sha512-gufkLkW2tA6PZPjivYxDiGzTIIftwqhmYI6lvvKu2S4FbhcysJgMAe/GXVSywzCRVVex9SrvCe6RFYrqnwRitQ==",
"license": "MIT",
"dependencies": {
"prosemirror-changeset": "^2.4.1",
@@ -1122,124 +1188,58 @@
}
},
"node_modules/@tiptap/starter-kit": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.29.0.tgz",
"integrity": "sha512-J3jTp3/WXnnL58TCtdMsfeQ2BeycFYrAib6Nbpjd9G0OLUBE7AILiH2HrobRQpvRbAUgD5SW+sBZYOonbWWqNg==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.30.5.tgz",
"integrity": "sha512-cmDRvukpoqjQjhE96q+l3tCLNZZcJKehxK+00Sp9F4XbKecfM2QpZ2TRHh3vi8qhCeDQNyMoCqfNaqznIjLjIQ==",
"license": "MIT",
"dependencies": {
"@tiptap/core": "^3.29.0",
"@tiptap/extension-blockquote": "^3.29.0",
"@tiptap/extension-bold": "^3.29.0",
"@tiptap/extension-bullet-list": "^3.29.0",
"@tiptap/extension-code": "^3.29.0",
"@tiptap/extension-code-block": "^3.29.0",
"@tiptap/extension-document": "^3.29.0",
"@tiptap/extension-dropcursor": "^3.29.0",
"@tiptap/extension-gapcursor": "^3.29.0",
"@tiptap/extension-hard-break": "^3.29.0",
"@tiptap/extension-heading": "^3.29.0",
"@tiptap/extension-horizontal-rule": "^3.29.0",
"@tiptap/extension-italic": "^3.29.0",
"@tiptap/extension-link": "^3.29.0",
"@tiptap/extension-list": "^3.29.0",
"@tiptap/extension-list-item": "^3.29.0",
"@tiptap/extension-list-keymap": "^3.29.0",
"@tiptap/extension-ordered-list": "^3.29.0",
"@tiptap/extension-paragraph": "^3.29.0",
"@tiptap/extension-strike": "^3.29.0",
"@tiptap/extension-text": "^3.29.0",
"@tiptap/extension-underline": "^3.29.0",
"@tiptap/extensions": "^3.29.0",
"@tiptap/pm": "^3.29.0"
"@tiptap/core": "3.30.5",
"@tiptap/extension-blockquote": "3.30.5",
"@tiptap/extension-bold": "3.30.5",
"@tiptap/extension-bullet-list": "3.30.5",
"@tiptap/extension-code": "3.30.5",
"@tiptap/extension-code-block": "3.30.5",
"@tiptap/extension-document": "3.30.5",
"@tiptap/extension-dropcursor": "3.30.5",
"@tiptap/extension-gapcursor": "3.30.5",
"@tiptap/extension-hard-break": "3.30.5",
"@tiptap/extension-heading": "3.30.5",
"@tiptap/extension-horizontal-rule": "3.30.5",
"@tiptap/extension-italic": "3.30.5",
"@tiptap/extension-link": "3.30.5",
"@tiptap/extension-list": "3.30.5",
"@tiptap/extension-list-item": "3.30.5",
"@tiptap/extension-list-keymap": "3.30.5",
"@tiptap/extension-ordered-list": "3.30.5",
"@tiptap/extension-paragraph": "3.30.5",
"@tiptap/extension-strike": "3.30.5",
"@tiptap/extension-text": "3.30.5",
"@tiptap/extension-underline": "3.30.5",
"@tiptap/extensions": "3.30.5",
"@tiptap/pm": "3.30.5"
},
"funding": {
"type": "github",
"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": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-3.29.0.tgz",
"integrity": "sha512-OFESbEFlmDYPns5LrkyeKggis6tYICBvz+jrlVwxICCWJqWZJJvYb7y/uMtMCxFF1nAeGb8AFr8UhFrLaX5aiA==",
"version": "3.30.5",
"resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-3.30.5.tgz",
"integrity": "sha512-YRHacQy09nFcokAScICxJ6pWr5daWbsLJuBiMo+DJQlr1XLi6o/zFhh3eR9+DKluL4OY3IZDYBYZfDs7YZtJNg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"optionalDependencies": {
"@tiptap/extension-bubble-menu": "^3.29.0",
"@tiptap/extension-floating-menu": "^3.29.0"
"@tiptap/extension-bubble-menu": "^3.30.5",
"@tiptap/extension-floating-menu": "^3.30.5"
},
"peerDependencies": {
"@floating-ui/dom": "^1.0.0",
"@tiptap/core": "3.29.0",
"@tiptap/pm": "3.29.0",
"@tiptap/core": "3.30.5",
"@tiptap/pm": "3.30.5",
"vue": "^3.0.0"
}
},
-53
View File
@@ -12,7 +12,6 @@ import type { CollectionObject, MessageAddressObject } from '@MailManager/models
import { useMailOperationsStore } from '@/stores/mailOperationsStore'
import { useMailCompositionStore } from '@/stores/mailCompositionStore'
import { ComposerMode } from '@/types/composer'
import type { ComposerFormat } from '@/types/composer'
import { documentsSelectorComponent } from '@/services/documentsSelector'
import ComposerToolbar from '@/components/composer/ComposerToolbar.vue'
import ComposerSender from '@/components/composer/ComposerSender.vue'
@@ -49,8 +48,6 @@ const {
// State
const showCc = ref(false)
const showBcc = ref(false)
const format = ref<ComposerFormat>('rich')
const textEdited = ref(false)
const applyingDraftToEditor = ref(false)
const showDocumentSelector = ref(false)
const showCloseDialog = ref(false)
@@ -88,14 +85,6 @@ const subject = computed({
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
const editor = useEditor({
extensions: [
@@ -129,8 +118,6 @@ watch(
compositionStore.openDraft(props.mode, props.source)
showCc.value = (activeDraft.value?.message.cc.length ?? 0) > 0
showBcc.value = (activeDraft.value?.message.bcc.length ?? 0) > 0
format.value = 'rich'
textEdited.value = false
applyingDraftToEditor.value = true
currentEditor.commands.setContent(activeDraft.value?.message.body.html || '')
@@ -262,42 +249,6 @@ const toggleLink = () => {
const isActive = (name: string, attrs?: any) => {
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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
}
</script>
<template>
@@ -346,8 +297,6 @@ function escapeHtml(value: string): string {
<ComposerEditor
:editor="editor"
:format="format"
:text="text"
:is-bold-active="isActive('bold')"
:is-italic-active="isActive('italic')"
:is-underline-active="isActive('underline')"
@@ -360,8 +309,6 @@ function escapeHtml(value: string): string {
@bullet-list="toggleBulletList"
@ordered-list="toggleOrderedList"
@link="toggleLink"
@toggle-format="toggleFormat"
@update:text="text = $event"
@attach-from-device="handleAttachFromDevice"
@attach-from-documents="handleAttachFromDocuments"
/>
+2 -4
View File
@@ -16,14 +16,12 @@ interface Props {
selectionMode?: boolean
selectedCollection?: CollectionObject | null
loading?: boolean
searchActive?: boolean
}
const props = withDefaults(defineProps<Props>(), {
loading: false,
selectionList: () => [],
selectionMode: false,
searchActive: false,
})
// Emits
@@ -374,10 +372,10 @@ onBeforeUnmount(() => {
<!-- Empty state -->
<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-body-2 text-medium-emphasis">
{{ searchActive ? 'No messages match your search' : 'This folder is empty' }}
This folder is empty
</div>
</div>
+2 -12
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { usePreviewStore, useUser } from '@KTXC'
import { useUser } from '@KTXC'
import { useMailUiStore } from '@/stores/mailUiStore'
import type { EntityObject, MessageObject } from '@MailManager/models'
import { SecurityLevel } from '@/utile/emailSanitizer'
@@ -19,7 +19,6 @@ const props = defineProps<{
// Emits
const emit = defineEmits<{
reply: [entity: EntityObject]
replyAll: [entity: EntityObject]
forward: [entity: EntityObject]
move: [entity: EntityObject]
delete: [entity: EntityObject]
@@ -29,7 +28,6 @@ const emit = defineEmits<{
// User settings
const { getSetting } = useUser()
const previewStore = usePreviewStore()
const mailUiStore = useMailUiStore()
// Security overrides
@@ -66,7 +64,6 @@ const effectiveSecurityLevel = computed(() => {
// Preview state
const previewDialog = computed(() => mediaViewerComponent('dialog'))
const previewItems = computed<MediaViewerItem[]>(() => {
if (!previewStore.availability.storage) return []
const attachments = message.value?.attachments ?? []
const items: MediaViewerItem[] = []
attachments.forEach((attachment, index) => {
@@ -110,12 +107,6 @@ const handleReply = () => {
}
}
const handleReplyAll = () => {
if (props.entity) {
emit('replyAll', props.entity)
}
}
const handleForward = () => {
if (props.entity) {
emit('forward', props.entity)
@@ -161,7 +152,7 @@ const handlePreview = (index: number) => {
const handleViewerRetrieve = (item: MediaViewerItem): Promise<Blob> => {
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) => {
@@ -185,7 +176,6 @@ const handleViewerDownload = (item: MediaViewerItem) => {
:security-level="effectiveSecurityLevel"
:is-security-overridden="overrideSecurityLevel !== null"
@reply="handleReply"
@reply-all="handleReplyAll"
@forward="handleForward"
@move="handleMove"
@delete="handleDelete"
+58 -99
View File
@@ -9,14 +9,6 @@ defineProps({
type: Object as PropType<Editor | null>,
default: null,
},
format: {
type: String as PropType<'rich' | 'plain'>,
required: true,
},
text: {
type: String,
default: '',
},
isBoldActive: {
type: Boolean,
required: true,
@@ -50,8 +42,6 @@ const emit = defineEmits<{
bulletList: []
orderedList: []
link: []
toggleFormat: []
'update:text': [value: string]
attachFromDevice: [files: File[]]
attachFromDocuments: []
}>()
@@ -76,84 +66,68 @@ function handleFileChange(event: Event) {
<template>
<v-toolbar density="compact" elevation="0" class="editor-toolbar">
<template v-if="format === 'rich'">
<v-btn
icon
size="small"
:class="{ 'v-btn--active': isBoldActive }"
@click="$emit('bold')"
>
<v-icon>mdi-format-bold</v-icon>
<v-tooltip activator="parent" location="bottom">Bold</v-tooltip>
</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
icon
size="small"
:class="{ 'v-btn--active': isBoldActive }"
@click="$emit('bold')"
>
<v-icon>mdi-format-bold</v-icon>
<v-tooltip activator="parent" location="bottom">Bold</v-tooltip>
</v-btn>
<v-btn
icon
size="small"
:class="{ 'v-btn--active': format === 'plain' }"
@click="$emit('toggleFormat')"
:class="{ 'v-btn--active': isItalicActive }"
@click="$emit('italic')"
>
<v-icon>{{ format === 'plain' ? 'mdi-format-text' : 'mdi-code-tags' }}</v-icon>
<v-tooltip activator="parent" location="bottom">
{{ format === 'plain' ? 'Rich Text' : 'Plain Text' }}
</v-tooltip>
<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-spacer />
@@ -180,17 +154,7 @@ function handleFileChange(event: Event) {
<v-divider />
<div class="editor-container">
<EditorContent v-if="format === 'rich'" :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)"
/>
<EditorContent :editor="editor ?? undefined" />
</div>
</template>
@@ -215,11 +179,6 @@ function handleFileChange(event: Event) {
color: rgb(var(--v-theme-primary));
}
.text-editor :deep(textarea) {
min-height: 300px;
font-family: inherit;
}
:deep(.tiptap-editor) {
outline: none;
min-height: 300px;
+1 -1
View File
@@ -30,7 +30,7 @@ defineEmits<{
</v-btn>
<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-spacer />
+3 -6
View File
@@ -1,6 +1,5 @@
<script setup lang="ts">
import { computed } from 'vue'
import { usePreviewStore } from '@KTXC'
import RecipientDetails from '@/components/common/RecipientDetails.vue'
import { formatFileSize } from '@/utile/format'
import { mediaViewerCanDisplay, mediaViewerComponent } from '@/services/mediaViewer'
@@ -28,9 +27,7 @@ const emit = defineEmits<{
}>()
const mailUiStore = useMailUiStore()
const previewStore = usePreviewStore()
const previewsAvailable = computed(() => previewStore.availability.storage)
const previewPopover = computed(() => previewsAvailable.value ? mediaViewerComponent('popover') : null)
const previewPopover = computed(() => mediaViewerComponent('popover'))
const message = computed(() => {
return props.entity?.properties ?? null
@@ -51,7 +48,7 @@ const attachmentItems = computed<AttachmentItem[]>(() =>
)
const isPreviewable = (attachment: MessagePartInterface): boolean => {
return previewsAvailable.value && mediaViewerCanDisplay(attachment.type)
return mediaViewerCanDisplay(attachment.type)
}
const handleAttachmentClick = (attachment: MessagePartInterface, index: number): void => {
@@ -64,7 +61,7 @@ const handleAttachmentClick = (attachment: MessagePartInterface, index: number):
const handleViewerRetrieve = (item: AttachmentItem): Promise<Blob> => {
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
+1 -2
View File
@@ -13,7 +13,6 @@ const props = defineProps<Props>()
const emit = defineEmits<{
reply: []
replyAll: []
forward: []
move: []
delete: []
@@ -48,7 +47,7 @@ const currentSecurityLevel = computed(() => {
<v-btn
icon="mdi-reply-all"
variant="text"
@click="emit('replyAll')"
@click="emit('reply')"
>
<v-icon>mdi-reply-all</v-icon>
<v-tooltip activator="parent" location="bottom">Reply All</v-tooltip>
+11 -16
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, onMounted, ref, unref, watch } from 'vue'
import { computed, onMounted, ref, unref } from 'vue'
import { storeToRefs } from 'pinia'
import { useDisplay } from 'vuetify'
import { useModuleStore } from '@KTXC'
@@ -41,8 +41,6 @@ const {
loading,
selectedMessage,
currentMessages,
searchResults,
searching,
} = storeToRefs(mailOperationsStore)
const {
@@ -76,19 +74,21 @@ const {
// Complex store/composable objects accessed directly (not simple refs)
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('')
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
// query for a folder whose results are no longer being filtered.
watch(selectedFolder, () => {
searchQuery.value = ''
return currentMessages.value.filter((message: EntityObject) => {
const subject = (message.properties.subject || '').toLowerCase()
const fromLabel = (message.properties.from?.label || '').toLowerCase()
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 lastSync = unref(unref(mailSync.lastSync))
@@ -167,8 +167,6 @@ const handleMessageComposeFresh = () => mailUiStore.openComposer()
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 handleMessageComposeClose = () => mailUiStore.closeComposer()
@@ -252,7 +250,6 @@ const handleMessageSelectionDelete = () => mailUiStore.deleteSelectedMessages()
variant="outlined"
placeholder="Search messages..."
prepend-inner-icon="mdi-magnify"
:loading="searching"
hide-details
single-line
clearable
@@ -311,7 +308,6 @@ const handleMessageSelectionDelete = () => mailUiStore.deleteSelectedMessages()
:selection-list="selectionList"
:selection-mode="selectionMode"
:loading="loading"
:search-active="searchResults !== null"
@open="handleMessageOpen"
@reply="handleMessageComposeReply"
@forward="handleMessageComposeForward"
@@ -343,7 +339,6 @@ const handleMessageSelectionDelete = () => mailUiStore.deleteSelectedMessages()
:entity="selectedMessage"
@compose="handleMessageComposeFresh"
@reply="handleMessageComposeReply"
@reply-all="handleMessageComposeReplyAll"
@forward="handleMessageComposeForward"
@move="handleMessageMove"
@delete="handleMessageDelete"
+8 -25
View File
@@ -118,8 +118,7 @@ export const useMailCompositionStore = defineStore('mailCompositionStore', () =>
return
}
const ownAddresses = senderIdentities.value.map(identity => identity.address)
activeDraft.value = buildDraft(mode, sender, source, ownAddresses)
activeDraft.value = buildDraft(mode, sender, source)
activeDraft.value.action = mode
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 freshMessage = buildMessage(mode, source, ownAddresses)
const freshMessage = buildMessage(mode, source)
const freshAttachments = buildAttachments(composition, mode, source)
const sourceIdentifier = source instanceof EntityObject ? source.identifier : null
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) {
return emptyMessage()
@@ -604,28 +603,12 @@ function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressO
const sentAt = sourceMessage.sent || source.created || ''
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 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 {
to,
cc,
to: replyToAddress ? [{ address: replyToAddress, label: replyToAddr?.label }] : [],
cc: [],
bcc: [],
subject: /^Re:/i.test(originalSubject) ? originalSubject : `Re: ${originalSubject}`,
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> {
if (mode === ComposerMode.Fresh || mode === ComposerMode.Reply || mode === ComposerMode.ReplyAll || !(source instanceof EntityObject)) {
if (mode === ComposerMode.Fresh || mode === ComposerMode.Reply || !(source instanceof EntityObject)) {
return {}
}
+1 -89
View File
@@ -4,8 +4,7 @@ import { useCollectionsStore } from '@MailManager/stores/collectionsStore'
import { useEntitiesStore } from '@MailManager/stores/entitiesStore'
import { useServicesStore } from '@MailManager/stores/servicesStore'
import { useMailSync } from '@MailManager/composables/useMailSync'
import type { ServiceIdentifier, CollectionIdentifier, EntityIdentifier, ListFilter } from '@MailManager/types/common'
import { ListFilterComparisonOperator, ListFilterConjunctionOperator } from '@MailManager/types/common'
import type { ServiceIdentifier, CollectionIdentifier, EntityIdentifier } from '@MailManager/types/common'
import type { EntityTransmitRequest, EntityBlobSelector } from '@MailManager/types/entity'
import type { MessageAddressInterface, MessageInterface, MessagePartInterface } from '@MailManager/types/message'
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 selectedMessage = shallowRef<EntityObject | null>(null)
const searchResults = shallowRef<EntityObject[] | null>(null)
const searching = ref(false)
const composerSaving = ref(false)
const composerSending = ref(false)
const composerLastSaved = ref<Date | null>(null)
@@ -296,7 +293,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
}
async function selectFolder(folder: CollectionObject | null) {
clearSearch()
selectedFolder.value = folder
selectedMessage.value = null
@@ -311,67 +307,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
_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) {
selectedMessage.value = entity
}
@@ -640,24 +575,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
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 ───────────────────────────────────────────────────────────────
return {
@@ -670,8 +587,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
// State
loading,
selectedMessage,
searchResults,
searching,
composerSaving,
composerSending,
composerLastSaved,
@@ -687,8 +602,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
retrieveService,
selectFolder,
selectMessage,
searchMessages,
clearSearch,
createFolder,
saveComposerDraft,
sendComposerMessage,
@@ -699,7 +612,6 @@ export const useMailOperationsStore = defineStore('mailOperationsStore', () => {
moveMessages,
downloadMessage,
attachmentBlob,
attachmentPreviewBlob,
moveFolder,
renameFolder,
isServiceFolderLoading,
+1 -10
View File
@@ -714,14 +714,6 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
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 {
sidebarVisible,
settingsDialogVisible,
@@ -771,7 +763,6 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
moveMessages,
downloadMessage,
attachmentBlob,
attachmentPreviewBlob,
messageSelectionModeActivate,
messageSelectionModeDeactivate,
messageSelectionToggleOne,
@@ -797,4 +788,4 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
confirmDeleteFolder,
flagSelectedMessages,
}
})
})
-4
View File
@@ -5,13 +5,9 @@ import type { MessageAddressInterface } from "@MailManager/types/message"
export enum ComposerMode {
Fresh = 'fresh',
Reply = 'reply',
ReplyAll = 'replyAll',
Forward = 'forward',
}
/** Body editing format: rich (Tiptap/HTML) or plain text. */
export type ComposerFormat = 'rich' | 'plain'
export interface ComposerDraftAttachment {
identifier: string
composition: string