diff --git a/Cargo.toml b/Cargo.toml
index c71317fc..d213af1b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -55,7 +55,17 @@ windows = { version = "0.61", features = [
"Foundation",
"Networking_PushNotifications",
"UI_Notifications",
+ "Win32_Foundation",
+ "Win32_System_Com",
+ "Win32_UI_Notifications",
] }
+# The `#[implement]` macro from `windows::core::implement` emits `::windows_core::*`
+# absolute paths, so `windows-core` must be a direct dependency, not just
+# transitive through `windows`.
+windows-core = "0.61"
+# Used to parse user-supplied CLSID strings (accepts braced, unbraced, and
+# hyphen-less forms) before converting to `windows::core::GUID` via raw bits.
+uuid = { version = "1", default-features = false }
nt-time = "0.15"
[build-dependencies]
diff --git a/examples/notifications-demo/package.json b/examples/notifications-demo/package.json
index 3753e889..220e7604 100644
--- a/examples/notifications-demo/package.json
+++ b/examples/notifications-demo/package.json
@@ -9,7 +9,8 @@
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
- "tauri": "tauri"
+ "tauri": "tauri",
+ "tauri:windows:build": "tauri-windows-bundle build"
},
"license": "MIT",
"dependencies": {
@@ -25,6 +26,7 @@
"svelte": "^5.56.1",
"svelte-check": "^4.4.4",
"typescript": "~6.0.3",
- "vite": "^8.0.13"
+ "vite": "^8.0.13",
+ "@choochmeque/tauri-windows-bundle": "^0.1.20"
}
}
diff --git a/examples/notifications-demo/pnpm-lock.yaml b/examples/notifications-demo/pnpm-lock.yaml
index fea3e550..0fba3083 100644
--- a/examples/notifications-demo/pnpm-lock.yaml
+++ b/examples/notifications-demo/pnpm-lock.yaml
@@ -18,6 +18,9 @@ importers:
specifier: ^2
version: 2.5.4
devDependencies:
+ '@choochmeque/tauri-windows-bundle':
+ specifier: ^0.1.20
+ version: 0.1.21
'@sveltejs/adapter-static':
specifier: ^3.0.6
version: 3.0.10(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3(@typescript-eslint/types@8.58.0))(vite@8.0.16(esbuild@0.27.2)))(svelte@5.56.3(@typescript-eslint/types@8.58.0))(typescript@6.0.3)(vite@8.0.16(esbuild@0.27.2)))
@@ -48,6 +51,10 @@ packages:
'@choochmeque/tauri-plugin-notifications-api@file:../..':
resolution: {directory: ../.., type: directory}
+ '@choochmeque/tauri-windows-bundle@0.1.21':
+ resolution: {integrity: sha512-z5DuRUhokC64NvT3bFyEzPuxJiZ1xc3yUzF0S3HoUzhQpnivzjU13EIgEfC4f8USmu95V9sgBApOkl7GOIiYvA==}
+ hasBin: true
+
'@emnapi/core@1.10.0':
resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
@@ -471,6 +478,10 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
aria-query@5.3.1:
resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==}
engines: {node: '>= 0.4'}
@@ -479,6 +490,23 @@ packages:
resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
engines: {node: '>= 0.4'}
+ balanced-match@4.0.4:
+ resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
+ engines: {node: 18 || 20 || >=22}
+
+ binary-search@1.3.6:
+ resolution: {integrity: sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==}
+
+ brace-expansion@5.0.6:
+ resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==}
+ engines: {node: 18 || 20 || >=22}
+
+ bresenham-zingl@0.2.5:
+ resolution: {integrity: sha512-0TCrPvavRM/3Os9QIUDhe8jpAQXgEYjsVO+9IKnkC8cdzorDX5fMRfr3neEFGjcfRItEswHvIvPrqQzCalRYkw==}
+
+ cheminfo-types@1.15.0:
+ resolution: {integrity: sha512-shv45WN2u0yN9EHH1bisNrv+fy4Cw+eLM5lOoriP67mePrwbHZ1kJqg90C8GEU7K1A8gJsicEoVZHcuBbuul/w==}
+
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
@@ -487,10 +515,26 @@ packages:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
+ colord@2.9.3:
+ resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
+
+ commander@15.0.0:
+ resolution: {integrity: sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==}
+ engines: {node: '>=22.12.0'}
+
cookie@0.6.0:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
engines: {node: '>= 0.6'}
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
deepmerge@4.3.1:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'}
@@ -518,6 +562,15 @@ packages:
'@typescript-eslint/types':
optional: true
+ fast-bmp@4.0.1:
+ resolution: {integrity: sha512-+KtMijJj+uA8Sl6EXAnhza7US7EXSY5Z9NeiJwT1wopVUksyLMXL5iFmn9FjY8FdkstOkpJI9RuEVXkGpIPSwg==}
+
+ fast-jpeg@3.0.1:
+ resolution: {integrity: sha512-1r4CO4rgRY1CeqaHlXVBPhdGC+rbNwWFJvV9s3HTUC+svqTE7hC1cEH9srp5MPgAmhDdsZ/WtU3WGM8zVobFCA==}
+
+ fast-png@8.0.0:
+ resolution: {integrity: sha512-gCysNasJ8KEMgfdYIKd/wTDo6ENK1PWT0RJO7O+0pgmuHPw2O6tA1WvdxFRJoLf9V8yFYpG0FA1YgI8X97OhJA==}
+
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -527,14 +580,63 @@ packages:
picomatch:
optional: true
+ fflate@0.8.3:
+ resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==}
+
+ fft.js@4.0.4:
+ resolution: {integrity: sha512-f9c00hphOgeQTlDyavwTtu6RiK8AIFjD6+jvXkNkpeQ7rirK3uFWVpalkoS4LAwbdX7mfZ8aoBfFVQX1Re/8aw==}
+
+ file-type@10.11.0:
+ resolution: {integrity: sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==}
+ engines: {node: '>=6'}
+
+ follow-redirects@1.16.0:
+ resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
+ glob@13.0.6:
+ resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+ engines: {node: 18 || 20 || >=22}
+
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
+ image-js@1.6.1:
+ resolution: {integrity: sha512-lLhyJCj7Ip5I0nJLYlsir1SBlDJACracpcMkZtRN+FnrS1eN3SHD0F2Yb7kmfVxCp3EV9EcMyCXFfKCjHLRTEw==}
+
+ image-type@4.1.0:
+ resolution: {integrity: sha512-CFJMJ8QK8lJvRlTCEgarL4ro6hfDQKif2HjSvYCdQZESaIPV4v9imrf7BQHK+sQeTeNeMpWciR9hyC/g8ybXEg==}
+ engines: {node: '>=6'}
+
+ iobuffer@6.0.1:
+ resolution: {integrity: sha512-SZWYkWNfjIXIBYSDpXDYIgshqtbOPsi4lviawAEceR1Kqk+sHDlcQjWrzNQsii80AyBY0q5c8HCTNjqo74ul+Q==}
+
+ is-any-array@2.0.1:
+ resolution: {integrity: sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==}
+
+ is-any-array@3.0.0:
+ resolution: {integrity: sha512-o4h+tylWykC4BD1vaejp6gDxoM13bwW8FGuNs4yIKpj8xbBJcRxJx8vZpq0dCr7ZDEfeKjmsi/euolKhX6f/ww==}
+
is-reference@3.0.3:
resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
+ jpeg-js@0.4.4:
+ resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==}
+
+ js-priority-queue@0.1.5:
+ resolution: {integrity: sha512-2dPmJT4GbXUpob7AZDR1wFMKz3Biy6oW69mwt5PTtdeoOgDin1i0p5gUV9k0LFeUxDpwkfr+JGMZDpcprjiY5w==}
+
kleur@4.1.5:
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
engines: {node: '>=6'}
@@ -612,9 +714,69 @@ packages:
locate-character@3.0.0:
resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
+ lru-cache@11.5.1:
+ resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==}
+ engines: {node: 20 || >=22}
+
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+ median-quickselect@1.0.1:
+ resolution: {integrity: sha512-/QL9ptNuLsdA68qO+2o10TKCyu621zwwTFdLvtu8rzRNKsn8zvuGoq/vDxECPyELFG8wu+BpyoMR9BnsJqfVZQ==}
+
+ minimatch@10.2.5:
+ resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==}
+ engines: {node: 18 || 20 || >=22}
+
+ minipass@7.1.3:
+ resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ ml-affine-transform@1.0.3:
+ resolution: {integrity: sha512-uv13li9HOGuMdSKL+QEdaV25emO9kt17LzGCD+FLQrBsrU8p/r/3kS/GJ7xI+f3/aWghkBK733x0yBG6EwKFJA==}
+
+ ml-array-max@2.0.0:
+ resolution: {integrity: sha512-QQZ4kENwpWmyNb98UXRDFXrmtIXuXtt1+bSbda/2KA85+F+rrJP8hZk6QOkCQXM2Th9mUDYdq/PNByPdT9ID4A==}
+
+ ml-array-median@1.1.6:
+ resolution: {integrity: sha512-V6bV6bTPFRX8v5CaAx/7fuRXC39LLTHfPSVZZafdNaqNz2PFL5zEA7gesjv8dMXh+gwPeUMtB5QPovlTBaa4sw==}
+
+ ml-array-min@2.0.0:
+ resolution: {integrity: sha512-GRj6Ky6sW9vGL6yIjgsHmXZ9YgrdmcQ8nCxPqEGeKc6dkfYg1XDYxGFxADUjNuZyoCd5PUscWAS4N+cFaX6hFg==}
+
+ ml-array-rescale@2.0.0:
+ resolution: {integrity: sha512-2GGtKfSno94/kIloWGvpp/U5Q5vLvLrza+SAaGsLeo6Xj4mEbA6Gqx+oTfZFkxnd1grT2X007HfJNs3T5BsiVg==}
+
+ ml-convolution@2.0.0:
+ resolution: {integrity: sha512-ExW6zVmN2YGuyO3aBiS1ymybme3nVgv2ccCfynSdgtW5sNp4DOHnfow4K/ErTDMQ1s9tINjv7kvzjnVhQHXJBA==}
+
+ ml-matrix@6.12.2:
+ resolution: {integrity: sha512-GC+BnW+pBh8Auap8goAxY0senAmF0IEoc3HNVSfnfbvGw0buuDIYb9kAKMS1l+GiwJ1rfK2bzJ8IHhwjzATSFA==}
+
+ ml-random@0.5.0:
+ resolution: {integrity: sha512-zLJBmNb34LOz+vN6BD8l3aYm/VWYWbmAunrLMPs4dHf4gTl8BWlhil72j56HubPg86zrXioIs4qoHq7Topy6tw==}
+
+ ml-ransac@1.0.0:
+ resolution: {integrity: sha512-fGi45s7T5+BEqdb5JqZC699w2riy6j0tzuZ2ZP63xavRa/yVKQIbUbj4XiE4XMr9T7HSiq1D9y0uybiyikDPvA==}
+
+ ml-regression-base@4.0.1:
+ resolution: {integrity: sha512-kYJWRIfB88JDUN+QWBsOlI0dP5tMo/XPxqVU0Xjn6B0rfzPptUnON9xPNnMVEm43DkM621j9v6+Ln9vCk3N93A==}
+
+ ml-regression-multivariate-linear@2.0.4:
+ resolution: {integrity: sha512-/vShPAlP+mB7P2mC5TuXwObSJNl/UBI71/bszt9ilTg6yLKy6btDLpAYyJNa6t+JnL5a7q+Yy4dCltfpvqXRIw==}
+
+ ml-regression-polynomial-2d@1.0.0:
+ resolution: {integrity: sha512-r34kaawZKMwjORIdzpa/o5fnjlTXkkaLJ3B4vvFNeKlvEGPtApqFxbDRmw07e2CjUH2MhGIChpMeXp/XB3Iogg==}
+
+ ml-spectra-processing@14.29.0:
+ resolution: {integrity: sha512-825CS864krbjMv7OB0mbjgAmyOL5ymj1OGa0gAzz1h1Dcd3Eeol2DaOimSiPYmRhW+iYhpeQnb7cSU0mlSK6+g==}
+
+ ml-xsadd@2.0.0:
+ resolution: {integrity: sha512-VoAYUqmPRmzKbbqRejjqceGFp3VF81Qe8XXFGU0UXLxB7Mf4GGvyGq5Qn3k4AiQgDEV6WzobqlPOd+j0+m6IrA==}
+
+ ml-xsadd@3.0.1:
+ resolution: {integrity: sha512-Fz2q6dwgzGM8wYKGArTUTZDGa4lQFA2Vi6orjGeTVRy22ZnQFKlJuwS9n8NRviqz1KHAHAzdKJwbnYhdo38uYg==}
+
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@@ -623,14 +785,27 @@ packages:
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
engines: {node: '>=10'}
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
nanoid@3.3.12:
resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ next-power-of-two@1.0.0:
+ resolution: {integrity: sha512-+z6QY1SxkDk6CQJAeaIZKmcNubBCRP7J8DMQUBglz/sSkNsZoJ1kULjqk9skNPPplzs4i9PFhYrvNDdtQleF/A==}
+
obug@2.1.1:
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
+ parenthesis@3.1.8:
+ resolution: {integrity: sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==}
+
+ path-scurry@2.0.2:
+ resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+ engines: {node: 18 || 20 || >=22}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -646,6 +821,21 @@ packages:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
+ robust-orientation@1.2.1:
+ resolution: {integrity: sha512-FuTptgKwY6iNuU15nrIJDLjXzCChWB+T4AvksRtwPS/WZ3HuP1CElCm1t+OBfgQKfWbtZIawip+61k7+buRKAg==}
+
+ robust-point-in-polygon@1.0.3:
+ resolution: {integrity: sha512-pPzz7AevOOcPYnFv4Vs5L0C7BKOq6C/TfAw5EUE58CylbjGiPyMjAnPLzzSuPZ2zftUGwWbmLWPOjPOz61tAcA==}
+
+ robust-scale@1.0.2:
+ resolution: {integrity: sha512-jBR91a/vomMAzazwpsPTPeuTPPmWBacwA+WYGNKcRGSh6xweuQ2ZbjRZ4v792/bZOhRKXRiQH0F48AvuajY0tQ==}
+
+ robust-subtract@1.0.0:
+ resolution: {integrity: sha512-xhKUno+Rl+trmxAIVwjQMiVdpF5llxytozXJOdoT4eTIqmqsndQqFb1A0oiW3sZGlhMRhOi6pAD4MF1YYW6o/A==}
+
+ robust-sum@1.0.0:
+ resolution: {integrity: sha512-AvLExwpaqUqD1uwLU6MwzzfRdaI6VEZsyvQ3IAQ0ZJ08v1H+DTyqskrf2ZJyh0BDduFVLN7H04Zmc+qTiahhAw==}
+
rolldown@1.0.3:
resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -662,10 +852,19 @@ packages:
resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
engines: {node: '>=18'}
+ skia-canvas@3.0.8:
+ resolution: {integrity: sha512-FSYKxp8Ng2vOeeOBiyPhnn6ui6FirPJXMyjk4PKl8N/OWzVrkMawUgY9zubIWHMdYtyWFn0gfX3QlRwg6HBmdg==}
+
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
+ ssim.js@3.5.0:
+ resolution: {integrity: sha512-Aj6Jl2z6oDmgYFFbQqK7fght19bXdOxY7Tj03nF+03M9gCBAjeIiO8/PlEGMfKDwYpw4q6iBqVq2YuREorGg/g==}
+
+ string-split-by@1.0.0:
+ resolution: {integrity: sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==}
+
svelte-check@4.6.0:
resolution: {integrity: sha512-KhVnDFDSid57mmZtHz8gfW8AAGylOZ0vPnOIzVmAL+urzwK8sBYXRss953gD8T0OdgAQ11mdWhE6uadmtOz8TQ==}
engines: {node: '>= 18.0.0'}
@@ -678,6 +877,9 @@ packages:
resolution: {integrity: sha512-w7JvrM5IFl5cmfbY0TLik9o7mjRUJmRMhOR51tBPu708Gr/MjbGs7VnJnr/B0CaXeI4vtnOh7RKxDr0cwhMdDA==}
engines: {node: '>=18'}
+ tiff@7.1.3:
+ resolution: {integrity: sha512-YEEq3fT++2pdta/9P/vGG4QRMdZQoe6W6JNaWnIi6NvAsbeNITwFCtmWwL/BZvOi+uo2I3ohyOkD3sZfme+c6g==}
+
tinyglobby@0.2.17:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
engines: {node: '>=12.0.0'}
@@ -686,14 +888,26 @@ packages:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
+ ts-pattern@5.9.0:
+ resolution: {integrity: sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==}
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+ two-product@1.0.2:
+ resolution: {integrity: sha512-vOyrqmeYvzjToVM08iU52OFocWT6eB/I5LUWYnxeAPGXAhAxXYU/Yr/R2uY5/5n4bvJQL9AQulIuxpIsMoT8XQ==}
+
+ two-sum@1.0.0:
+ resolution: {integrity: sha512-phP48e8AawgsNUjEY2WvoIWqdie8PoiDZGxTDv70LDr01uX5wLEQbOgSP7Z/B6+SW5oLtbe8qaYX2fKJs3CGTw==}
+
typescript@6.0.3:
resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==}
engines: {node: '>=14.17'}
hasBin: true
+ uint8-base64@1.0.0:
+ resolution: {integrity: sha512-B6ZJfEZL2FAhbIyZZ7WlQq8MPq1X1P1DUA//LsSv/vB4r+Dao5/BPoxgw2t+t1XyvoSfBkE7zI4SYsnGj7BmlQ==}
+
vite@8.0.16:
resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -754,6 +968,15 @@ snapshots:
dependencies:
'@tauri-apps/api': 2.11.0
+ '@choochmeque/tauri-windows-bundle@0.1.21':
+ dependencies:
+ commander: 15.0.0
+ glob: 13.0.6
+ image-js: 1.6.1
+ transitivePeerDependencies:
+ - debug
+ - supports-color
+
'@emnapi/core@1.10.0':
dependencies:
'@emnapi/wasi-threads': 1.2.1
@@ -1039,18 +1262,42 @@ snapshots:
acorn@8.16.0: {}
+ agent-base@7.1.4:
+ optional: true
+
aria-query@5.3.1: {}
axobject-query@4.1.0: {}
+ balanced-match@4.0.4: {}
+
+ binary-search@1.3.6: {}
+
+ brace-expansion@5.0.6:
+ dependencies:
+ balanced-match: 4.0.4
+
+ bresenham-zingl@0.2.5: {}
+
+ cheminfo-types@1.15.0: {}
+
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
clsx@2.1.1: {}
+ colord@2.9.3: {}
+
+ commander@15.0.0: {}
+
cookie@0.6.0: {}
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+ optional: true
+
deepmerge@4.3.1: {}
detect-libc@2.1.2: {}
@@ -1095,17 +1342,97 @@ snapshots:
optionalDependencies:
'@typescript-eslint/types': 8.58.0
+ fast-bmp@4.0.1:
+ dependencies:
+ iobuffer: 6.0.1
+
+ fast-jpeg@3.0.1:
+ dependencies:
+ iobuffer: 6.0.1
+ tiff: 7.1.3
+
+ fast-png@8.0.0:
+ dependencies:
+ fflate: 0.8.3
+ iobuffer: 6.0.1
+
fdir@6.5.0(picomatch@4.0.4):
optionalDependencies:
picomatch: 4.0.4
+ fflate@0.8.3: {}
+
+ fft.js@4.0.4: {}
+
+ file-type@10.11.0: {}
+
+ follow-redirects@1.16.0:
+ optional: true
+
fsevents@2.3.3:
optional: true
+ glob@13.0.6:
+ dependencies:
+ minimatch: 10.2.5
+ minipass: 7.1.3
+ path-scurry: 2.0.2
+
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ image-js@1.6.1:
+ dependencies:
+ bresenham-zingl: 0.2.5
+ colord: 2.9.3
+ fast-bmp: 4.0.1
+ fast-jpeg: 3.0.1
+ fast-png: 8.0.0
+ image-type: 4.1.0
+ jpeg-js: 0.4.4
+ js-priority-queue: 0.1.5
+ median-quickselect: 1.0.1
+ ml-affine-transform: 1.0.3
+ ml-convolution: 2.0.0
+ ml-matrix: 6.12.2
+ ml-ransac: 1.0.0
+ ml-regression-multivariate-linear: 2.0.4
+ ml-regression-polynomial-2d: 1.0.0
+ ml-spectra-processing: 14.29.0
+ robust-point-in-polygon: 1.0.3
+ ssim.js: 3.5.0
+ tiff: 7.1.3
+ ts-pattern: 5.9.0
+ uint8-base64: 1.0.0
+ optionalDependencies:
+ skia-canvas: 3.0.8
+ transitivePeerDependencies:
+ - debug
+ - supports-color
+
+ image-type@4.1.0:
+ dependencies:
+ file-type: 10.11.0
+
+ iobuffer@6.0.1: {}
+
+ is-any-array@2.0.1: {}
+
+ is-any-array@3.0.0: {}
+
is-reference@3.0.3:
dependencies:
'@types/estree': 1.0.9
+ jpeg-js@0.4.4: {}
+
+ js-priority-queue@0.1.5: {}
+
kleur@4.1.5: {}
lightningcss-android-arm64@1.32.0:
@@ -1159,18 +1486,113 @@ snapshots:
locate-character@3.0.0: {}
+ lru-cache@11.5.1: {}
+
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ median-quickselect@1.0.1: {}
+
+ minimatch@10.2.5:
+ dependencies:
+ brace-expansion: 5.0.6
+
+ minipass@7.1.3: {}
+
+ ml-affine-transform@1.0.3:
+ dependencies:
+ ml-matrix: 6.12.2
+
+ ml-array-max@2.0.0:
+ dependencies:
+ is-any-array: 3.0.0
+
+ ml-array-median@1.1.6:
+ dependencies:
+ is-any-array: 2.0.1
+ median-quickselect: 1.0.1
+
+ ml-array-min@2.0.0:
+ dependencies:
+ is-any-array: 3.0.0
+
+ ml-array-rescale@2.0.0:
+ dependencies:
+ is-any-array: 3.0.0
+ ml-array-max: 2.0.0
+ ml-array-min: 2.0.0
+
+ ml-convolution@2.0.0:
+ dependencies:
+ fft.js: 4.0.4
+ next-power-of-two: 1.0.0
+
+ ml-matrix@6.12.2:
+ dependencies:
+ is-any-array: 3.0.0
+ ml-array-rescale: 2.0.0
+
+ ml-random@0.5.0:
+ dependencies:
+ ml-xsadd: 2.0.0
+
+ ml-ransac@1.0.0:
+ dependencies:
+ ml-array-median: 1.1.6
+ ml-matrix: 6.12.2
+ ml-random: 0.5.0
+
+ ml-regression-base@4.0.1:
+ dependencies:
+ cheminfo-types: 1.15.0
+ is-any-array: 3.0.0
+
+ ml-regression-multivariate-linear@2.0.4:
+ dependencies:
+ ml-matrix: 6.12.2
+
+ ml-regression-polynomial-2d@1.0.0:
+ dependencies:
+ cheminfo-types: 1.15.0
+ is-any-array: 2.0.1
+ ml-matrix: 6.12.2
+ ml-regression-base: 4.0.1
+
+ ml-spectra-processing@14.29.0:
+ dependencies:
+ binary-search: 1.3.6
+ cheminfo-types: 1.15.0
+ fft.js: 4.0.4
+ is-any-array: 3.0.0
+ ml-matrix: 6.12.2
+ ml-xsadd: 3.0.1
+
+ ml-xsadd@2.0.0: {}
+
+ ml-xsadd@3.0.1: {}
+
mri@1.2.0: {}
mrmime@2.0.1: {}
+ ms@2.1.3:
+ optional: true
+
nanoid@3.3.12: {}
+ next-power-of-two@1.0.0: {}
+
obug@2.1.1: {}
+ parenthesis@3.1.8:
+ optional: true
+
+ path-scurry@2.0.2:
+ dependencies:
+ lru-cache: 11.5.1
+ minipass: 7.1.3
+
picocolors@1.1.1: {}
picomatch@4.0.4: {}
@@ -1183,6 +1605,26 @@ snapshots:
readdirp@4.1.2: {}
+ robust-orientation@1.2.1:
+ dependencies:
+ robust-scale: 1.0.2
+ robust-subtract: 1.0.0
+ robust-sum: 1.0.0
+ two-product: 1.0.2
+
+ robust-point-in-polygon@1.0.3:
+ dependencies:
+ robust-orientation: 1.2.1
+
+ robust-scale@1.0.2:
+ dependencies:
+ two-product: 1.0.2
+ two-sum: 1.0.0
+
+ robust-subtract@1.0.0: {}
+
+ robust-sum@1.0.0: {}
+
rolldown@1.0.3:
dependencies:
'@oxc-project/types': 0.133.0
@@ -1216,8 +1658,26 @@ snapshots:
mrmime: 2.0.1
totalist: 3.0.1
+ skia-canvas@3.0.8:
+ dependencies:
+ detect-libc: 2.1.2
+ follow-redirects: 1.16.0
+ https-proxy-agent: 7.0.6
+ string-split-by: 1.0.0
+ transitivePeerDependencies:
+ - debug
+ - supports-color
+ optional: true
+
source-map-js@1.2.1: {}
+ ssim.js@3.5.0: {}
+
+ string-split-by@1.0.0:
+ dependencies:
+ parenthesis: 3.1.8
+ optional: true
+
svelte-check@4.6.0(picomatch@4.0.4)(svelte@5.56.3(@typescript-eslint/types@8.58.0))(typescript@6.0.3):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -1252,6 +1712,11 @@ snapshots:
transitivePeerDependencies:
- '@typescript-eslint/types'
+ tiff@7.1.3:
+ dependencies:
+ fflate: 0.8.3
+ iobuffer: 6.0.1
+
tinyglobby@0.2.17:
dependencies:
fdir: 6.5.0(picomatch@4.0.4)
@@ -1259,11 +1724,19 @@ snapshots:
totalist@3.0.1: {}
+ ts-pattern@5.9.0: {}
+
tslib@2.8.1:
optional: true
+ two-product@1.0.2: {}
+
+ two-sum@1.0.0: {}
+
typescript@6.0.3: {}
+ uint8-base64@1.0.0: {}
+
vite@8.0.16(esbuild@0.27.2):
dependencies:
lightningcss: 1.32.0
diff --git a/examples/notifications-demo/src-tauri/gen/windows/.gitignore b/examples/notifications-demo/src-tauri/gen/windows/.gitignore
new file mode 100644
index 00000000..64e107ed
--- /dev/null
+++ b/examples/notifications-demo/src-tauri/gen/windows/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+# Keep bundle.config.json and templates in git
diff --git a/examples/notifications-demo/src-tauri/gen/windows/AppxManifest.xml.template b/examples/notifications-demo/src-tauri/gen/windows/AppxManifest.xml.template
new file mode 100644
index 00000000..eff062fc
--- /dev/null
+++ b/examples/notifications-demo/src-tauri/gen/windows/AppxManifest.xml.template
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+ {{DISPLAY_NAME}}
+ {{PUBLISHER_DISPLAY_NAME}}
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{{EXTENSIONS}}
+
+
+
+
+{{CAPABILITIES}}
+
+
diff --git a/examples/notifications-demo/src-tauri/gen/windows/Assets/LargeTile.png b/examples/notifications-demo/src-tauri/gen/windows/Assets/LargeTile.png
new file mode 100644
index 00000000..f9bc0483
Binary files /dev/null and b/examples/notifications-demo/src-tauri/gen/windows/Assets/LargeTile.png differ
diff --git a/examples/notifications-demo/src-tauri/gen/windows/Assets/Square150x150Logo.png b/examples/notifications-demo/src-tauri/gen/windows/Assets/Square150x150Logo.png
new file mode 100644
index 00000000..624c7bfb
Binary files /dev/null and b/examples/notifications-demo/src-tauri/gen/windows/Assets/Square150x150Logo.png differ
diff --git a/examples/notifications-demo/src-tauri/gen/windows/Assets/Square44x44Logo.png b/examples/notifications-demo/src-tauri/gen/windows/Assets/Square44x44Logo.png
new file mode 100644
index 00000000..d5fbfb2a
Binary files /dev/null and b/examples/notifications-demo/src-tauri/gen/windows/Assets/Square44x44Logo.png differ
diff --git a/examples/notifications-demo/src-tauri/gen/windows/Assets/StoreLogo.png b/examples/notifications-demo/src-tauri/gen/windows/Assets/StoreLogo.png
new file mode 100644
index 00000000..45563882
Binary files /dev/null and b/examples/notifications-demo/src-tauri/gen/windows/Assets/StoreLogo.png differ
diff --git a/examples/notifications-demo/src-tauri/gen/windows/Assets/Wide310x150Logo.png b/examples/notifications-demo/src-tauri/gen/windows/Assets/Wide310x150Logo.png
new file mode 100644
index 00000000..79d394be
Binary files /dev/null and b/examples/notifications-demo/src-tauri/gen/windows/Assets/Wide310x150Logo.png differ
diff --git a/examples/notifications-demo/src-tauri/gen/windows/bundle.config.json b/examples/notifications-demo/src-tauri/gen/windows/bundle.config.json
new file mode 100644
index 00000000..63f6cdc3
--- /dev/null
+++ b/examples/notifications-demo/src-tauri/gen/windows/bundle.config.json
@@ -0,0 +1,26 @@
+{
+ "publisher": "CN=YourCompany",
+ "publisherDisplayName": "Your Company Name",
+ "capabilities": {
+ "general": [
+ "internetClient"
+ ]
+ },
+ "extensions": {
+ "shareTarget": false,
+ "fileAssociations": [],
+ "protocolHandlers": [],
+ "toastActivation": {
+ "activationType": "foreground",
+ "clsid": "{757B33CB-099E-4AA9-8741-314D2B54B59D}"
+ }
+ },
+ "signing": {
+ "pfx": null,
+ "pfxPassword": null
+ },
+ "resourceIndex": {
+ "enabled": false,
+ "keepConfig": false
+ }
+}
diff --git a/examples/notifications-demo/src-tauri/tauri.conf.json b/examples/notifications-demo/src-tauri/tauri.conf.json
index 30f9ee88..33b4d97d 100644
--- a/examples/notifications-demo/src-tauri/tauri.conf.json
+++ b/examples/notifications-demo/src-tauri/tauri.conf.json
@@ -21,6 +21,13 @@
"csp": null
}
},
+ "plugins": {
+ "notifications": {
+ "windows": {
+ "toastActivatorClsid": "{757B33CB-099E-4AA9-8741-314D2B54B59D}"
+ }
+ }
+ },
"bundle": {
"active": true,
"targets": "all",
diff --git a/src/lib.rs b/src/lib.rs
index 52f1ad98..9bcebd1b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,6 @@
//! Send message notifications (brief auto-expiring OS window element) to your user. Can also be used with the Notification Web API.
-use serde::Serialize;
+use serde::{Deserialize, Serialize};
#[cfg(mobile)]
use tauri::plugin::PluginHandle;
#[cfg(desktop)]
@@ -10,6 +10,33 @@ use tauri::{
Manager, Runtime,
};
+/// Top-level plugin config deserialized from the `plugins.notifications` block
+/// in `tauri.conf.json`. Optional in its entirety — apps without a config block
+/// get `PluginConfig::default()`.
+#[derive(Debug, Default, Clone, Deserialize)]
+#[serde(default, rename_all = "camelCase")]
+pub struct PluginConfig {
+ #[cfg(target_os = "windows")]
+ pub windows: WindowsConfig,
+}
+
+/// Windows-only plugin config.
+///
+/// Currently carries the toast activator CLSID used by
+/// `INotificationActivationCallback` registration; absent value means
+/// COM-based activation is disabled and the plugin falls back to in-process
+/// `Activated` events only.
+#[cfg(target_os = "windows")]
+#[derive(Debug, Default, Clone, Deserialize)]
+#[serde(default, rename_all = "camelCase")]
+pub struct WindowsConfig {
+ /// Toast activator CLSID. Must match the GUID declared in the MSIX
+ /// manifest's ``
+ /// and `` entries. Accepts the `xxxxxxxx-xxxx-...` form
+ /// with or without surrounding braces.
+ pub toast_activator_clsid: Option,
+}
+
pub use models::*;
pub use tauri::plugin::PermissionState;
@@ -266,8 +293,8 @@ impl> crate::NotificationsExt for T {
/// Initializes the plugin.
#[must_use]
-pub fn init() -> TauriPlugin {
- Builder::new("notifications")
+pub fn init() -> TauriPlugin {
+ Builder::::new("notifications")
.invoke_handler(tauri::generate_handler![
commands::notify,
commands::request_permission,
@@ -299,6 +326,8 @@ pub fn init() -> TauriPlugin {
.setup(|app, api| {
#[cfg(desktop)]
listeners::init();
+ #[cfg(all(target_os = "windows", not(feature = "notify-rust")))]
+ let windows_config = api.config().windows.clone();
#[cfg(mobile)]
let notification = mobile::init(app, api)?;
#[cfg(all(desktop, any(feature = "notify-rust", target_os = "linux")))]
@@ -306,7 +335,7 @@ pub fn init() -> TauriPlugin {
#[cfg(all(target_os = "macos", not(feature = "notify-rust")))]
let notification = macos::init(app, api)?;
#[cfg(all(target_os = "windows", not(feature = "notify-rust")))]
- let notification = windows::init(app, api)?;
+ let notification = windows::init(app, api, windows_config)?;
app.manage(notification);
Ok(())
})
diff --git a/src/listeners.rs b/src/listeners.rs
index a2532236..9df483e5 100644
--- a/src/listeners.rs
+++ b/src/listeners.rs
@@ -10,6 +10,10 @@
use std::collections::HashMap;
use std::sync::{OnceLock, RwLock};
+#[cfg(all(target_os = "windows", not(feature = "notify-rust")))]
+use tauri::Manager;
+use tauri::{AppHandle, Runtime};
+
use crate::error::{ErrorResponse, PluginInvokeError};
type ChannelMap = HashMap>;
@@ -66,14 +70,21 @@ pub fn trigger(event: &str, payload: String) -> crate::Result<()> {
}
/// Register a channel to receive events for the given event name.
+///
+/// On Windows, subscribing to `notificationClicked` synchronously drains any
+/// cold-start activation payload buffered by the COM activator before the JS
+/// listener was up. That makes the `push-listener.tsx` contract ("subscribing
+/// flushes the buffered tap") work without the app calling any extra command.
// Tauri commands receive serde-deserialized owned values.
#[allow(clippy::needless_pass_by_value)]
#[tauri::command]
-pub fn register_listener(
+pub fn register_listener(
+ app: AppHandle,
event: String,
handler: tauri::ipc::Channel,
) -> crate::Result<()> {
let listeners = LISTENERS.get_or_init(|| RwLock::new(HashMap::new()));
+ let should_drain_clicks = event == "notificationClicked";
{
let mut guard = listeners.write().map_err(|e| {
crate::Error::from(PluginInvokeError::InvokeRejected(ErrorResponse {
@@ -87,6 +98,14 @@ pub fn register_listener(
.or_default()
.insert(handler.id(), handler);
}
+ #[cfg(all(target_os = "windows", not(feature = "notify-rust")))]
+ if should_drain_clicks {
+ if let Some(notif) = app.try_state::>() {
+ notif.drain_pending_clicks();
+ }
+ }
+ #[cfg(not(all(target_os = "windows", not(feature = "notify-rust"))))]
+ let _ = (app, should_drain_clicks);
Ok(())
}
diff --git a/src/windows.rs b/src/windows.rs
index d3a599a2..9347811e 100644
--- a/src/windows.rs
+++ b/src/windows.rs
@@ -1,7 +1,8 @@
//! Windows implementation for notifications plugin using native Windows Toast API.
use std::collections::HashMap;
-use std::sync::{Arc, RwLock};
+use std::ffi::c_void;
+use std::sync::{Arc, RwLock, Weak};
use nt_time::FileTime;
use serde::de::DeserializeOwned;
@@ -9,7 +10,7 @@ use tauri::{
plugin::{PermissionState, PluginApi},
AppHandle, Runtime,
};
-use windows::core::{Interface, HSTRING};
+use windows::core::{implement, Interface, Ref, BOOL, GUID, HSTRING, PCWSTR};
use windows::ApplicationModel::Package;
use windows::Data::Xml::Dom::XmlDocument;
use windows::Foundation::{DateTime, TypedEventHandler};
@@ -17,11 +18,24 @@ use windows::Foundation::{DateTime, TypedEventHandler};
use windows::Networking::PushNotifications::{
PushNotificationChannel, PushNotificationChannelManager,
};
+use windows::Win32::Foundation::{CLASS_E_NOAGGREGATION, E_INVALIDARG, S_FALSE, S_OK};
+use windows::Win32::System::Com::{
+ CoInitializeEx, CoRegisterClassObject, IClassFactory, IClassFactory_Impl, CLSCTX_LOCAL_SERVER,
+ COINIT_APARTMENTTHREADED, REGCLS_MULTIPLEUSE,
+};
+use windows::Win32::UI::Notifications::{
+ INotificationActivationCallback, INotificationActivationCallback_Impl,
+ NOTIFICATION_USER_INPUT_DATA,
+};
use windows::UI::Notifications::{
NotificationSetting, ScheduledToastNotification, ToastActivatedEventArgs, ToastNotification,
ToastNotificationManager, ToastNotifier,
};
+use crate::error::{ErrorResponse, PluginInvokeError};
+use crate::models::*;
+use crate::WindowsConfig;
+
/// True when the current process has MSIX package identity.
///
/// WinRT notification APIs split into two flavors: no-arg variants that use the
@@ -35,8 +49,17 @@ fn is_packaged() -> bool {
Package::Current().is_ok()
}
-use crate::error::{ErrorResponse, PluginInvokeError};
-use crate::models::*;
+/// Accept any well-formed UUID string and reinterpret its bytes as a `GUID`.
+///
+/// Delegating to `uuid::Uuid::parse_str` lets the manifest CLSID and the
+/// `tauri.conf.json` CLSID use either braced (`{xxxxxxxx-…}`), unbraced
+/// (`xxxxxxxx-…`), or simple (32 hex chars, no hyphens) conventions without
+/// drift causing parse failures.
+fn parse_clsid(raw: &str) -> windows::core::Result {
+ let parsed = uuid::Uuid::parse_str(raw.trim())
+ .map_err(|e| windows::core::Error::new(E_INVALIDARG, format!("{e}")))?;
+ Ok(GUID::from_u128(parsed.as_u128()))
+}
// Enable `?` operator for windows::core::Error
impl From for crate::Error {
@@ -56,10 +79,41 @@ pub struct WindowsPlugin {
notifier: ToastNotifier,
action_types: RwLock>,
click_listener_active: RwLock,
+ /// Cold-start activation payloads queued before any JS listener has
+ /// subscribed. Drained synchronously the first time a `notificationClicked`
+ /// listener registers (see `crate::listeners::register_listener`).
+ pending_clicks: RwLock>,
+ /// `CoRegisterClassObject` cookie. Kept for the process lifetime — no
+ /// explicit `CoRevokeClassObject` on shutdown; the OS reclaims it on exit.
+ /// `None` when COM activator wasn't registered (unpackaged or no CLSID in
+ /// config).
+ _com_cookie: RwLock