diff --git a/package.json b/package.json index 8155e091..09d80de6 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "@tauri-apps/plugin-http": "^2.5.2", "@tauri-apps/plugin-log": "^2.6.0", "@tauri-apps/plugin-notification": "^2.3.1", + "@tauri-apps/plugin-opener": "^2.5.0", "@tauri-apps/plugin-window-state": "^2.4.0", "@types/byte-size": "^8.1.2", "@use-gesture/react": "^10.3.1", @@ -69,7 +70,7 @@ "classnames": "^2.5.1", "clsx": "^2.1.1", "compare-versions": "^6.1.1", - "dayjs": "^1.11.14", + "dayjs": "^1.11.15", "deepmerge-ts": "^7.1.5", "detect-browser": "^5.3.0", "fast-deep-equal": "^3.1.3", @@ -113,9 +114,9 @@ "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", "@types/node": "^24.3.0", - "@types/react": "^19.1.11", + "@types/react": "^19.1.12", "@types/react-dom": "^19.1.8", - "@vitejs/plugin-react": "^5.0.1", + "@vitejs/plugin-react": "^5.0.2", "@vitejs/plugin-react-swc": "^4.0.1", "autoprefixer": "^10.4.21", "npm-run-all": "^4.1.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 038bd533..d295a28f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,9 @@ importers: '@tauri-apps/plugin-notification': specifier: ^2.3.1 version: 2.3.1 + '@tauri-apps/plugin-opener': + specifier: ^2.5.0 + version: 2.5.0 '@tauri-apps/plugin-window-state': specifier: ^2.4.0 version: 2.4.0 @@ -75,8 +78,8 @@ importers: specifier: ^6.1.1 version: 6.1.1 dayjs: - specifier: ^1.11.14 - version: 1.11.14 + specifier: ^1.11.15 + version: 1.11.15 deepmerge-ts: specifier: ^7.1.5 version: 7.1.5 @@ -94,7 +97,7 @@ importers: version: 1.0.3 html-react-parser: specifier: ^5.2.6 - version: 5.2.6(@types/react@19.1.11)(react@19.1.1) + version: 5.2.6(@types/react@19.1.12)(react@19.1.1) itertools: specifier: ^2.4.1 version: 2.4.1 @@ -106,7 +109,7 @@ importers: version: 4.17.21 merge-refs: specifier: ^2.0.0 - version: 2.0.0(@types/react@19.1.11) + version: 2.0.0(@types/react@19.1.12) millify: specifier: ^6.1.0 version: 6.1.0 @@ -142,7 +145,7 @@ importers: version: 3.5.0(react@19.1.1) react-markdown: specifier: ^10.1.0 - version: 10.1.0(@types/react@19.1.11)(react@19.1.1) + version: 10.1.0(@types/react@19.1.12)(react@19.1.1) react-qr-code: specifier: ^2.0.18 version: 2.0.18(react@19.1.1) @@ -157,7 +160,7 @@ importers: version: 1.0.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1) recharts: specifier: ^3.1.2 - version: 3.1.2(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react-is@18.3.1)(react@19.1.1)(redux@5.0.1) + version: 3.1.2(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react-is@18.3.1)(react@19.1.1)(redux@5.0.1) rehype-sanitize: specifier: ^6.0.0 version: 6.0.0 @@ -172,14 +175,14 @@ importers: version: 3.25.76 zustand: specifier: ^5.0.8 - version: 5.0.8(@types/react@19.1.11)(immer@10.1.1)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)) + version: 5.0.8(@types/react@19.1.12)(immer@10.1.1)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)) devDependencies: '@biomejs/biome': specifier: ^2.2.2 version: 2.2.2 '@hookform/devtools': specifier: ^4.4.0 - version: 4.4.0(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 4.4.0(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@svgr/cli': specifier: ^8.1.0 version: 8.1.0(typescript@5.9.2) @@ -202,14 +205,14 @@ importers: specifier: ^24.3.0 version: 24.3.0 '@types/react': - specifier: ^19.1.11 - version: 19.1.11 + specifier: ^19.1.12 + version: 19.1.12 '@types/react-dom': specifier: ^19.1.8 - version: 19.1.8(@types/react@19.1.11) + version: 19.1.8(@types/react@19.1.12) '@vitejs/plugin-react': - specifier: ^5.0.1 - version: 5.0.1(vite@7.1.3(@types/node@24.3.0)(sass@1.70.0)(yaml@2.8.1)) + specifier: ^5.0.2 + version: 5.0.2(vite@7.1.3(@types/node@24.3.0)(sass@1.70.0)(yaml@2.8.1)) '@vitejs/plugin-react-swc': specifier: ^4.0.1 version: 4.0.1(vite@7.1.3(@types/node@24.3.0)(sass@1.70.0)(yaml@2.8.1)) @@ -618,8 +621,8 @@ packages: '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} - '@gerrit0/mini-shiki@3.11.0': - resolution: {integrity: sha512-ooCDMAOKv71O7MszbXjSQGcI6K5T6NKlemQZOBHLq7Sv/oXCRfYbZ7UgbzFdl20lSXju6Juds4I3y30R6rHA4Q==} + '@gerrit0/mini-shiki@3.12.0': + resolution: {integrity: sha512-CF1vkfe2ViPtmoFEvtUWilEc4dOCiFzV8+J7/vEISSsslKQ97FjeTPNMCqUhZEiKySmKRgK3UO/CxtkyOp7DvA==} '@hookform/devtools@4.4.0': resolution: {integrity: sha512-Mtlic+uigoYBPXlfvPBfiYYUZuyMrD3pTjDpVIhL6eCZTvQkHsKBSKeZCvXWUZr8fqrkzDg27N+ZuazLKq6Vmg==} @@ -678,103 +681,106 @@ packages: '@rolldown/pluginutils@1.0.0-beta.32': resolution: {integrity: sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g==} - '@rollup/rollup-android-arm-eabi@4.48.1': - resolution: {integrity: sha512-rGmb8qoG/zdmKoYELCBwu7vt+9HxZ7Koos3pD0+sH5fR3u3Wb/jGcpnqxcnWsPEKDUyzeLSqksN8LJtgXjqBYw==} + '@rolldown/pluginutils@1.0.0-beta.34': + resolution: {integrity: sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA==} + + '@rollup/rollup-android-arm-eabi@4.49.0': + resolution: {integrity: sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.48.1': - resolution: {integrity: sha512-4e9WtTxrk3gu1DFE+imNJr4WsL13nWbD/Y6wQcyku5qadlKHY3OQ3LJ/INrrjngv2BJIHnIzbqMk1GTAC2P8yQ==} + '@rollup/rollup-android-arm64@4.49.0': + resolution: {integrity: sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.48.1': - resolution: {integrity: sha512-+XjmyChHfc4TSs6WUQGmVf7Hkg8ferMAE2aNYYWjiLzAS/T62uOsdfnqv+GHRjq7rKRnYh4mwWb4Hz7h/alp8A==} + '@rollup/rollup-darwin-arm64@4.49.0': + resolution: {integrity: sha512-99kMMSMQT7got6iYX3yyIiJfFndpojBmkHfTc1rIje8VbjhmqBXE+nb7ZZP3A5skLyujvT0eIUCUsxAe6NjWbw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.48.1': - resolution: {integrity: sha512-upGEY7Ftw8M6BAJyGwnwMw91rSqXTcOKZnnveKrVWsMTF8/k5mleKSuh7D4v4IV1pLxKAk3Tbs0Lo9qYmii5mQ==} + '@rollup/rollup-darwin-x64@4.49.0': + resolution: {integrity: sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.48.1': - resolution: {integrity: sha512-P9ViWakdoynYFUOZhqq97vBrhuvRLAbN/p2tAVJvhLb8SvN7rbBnJQcBu8e/rQts42pXGLVhfsAP0k9KXWa3nQ==} + '@rollup/rollup-freebsd-arm64@4.49.0': + resolution: {integrity: sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.48.1': - resolution: {integrity: sha512-VLKIwIpnBya5/saccM8JshpbxfyJt0Dsli0PjXozHwbSVaHTvWXJH1bbCwPXxnMzU4zVEfgD1HpW3VQHomi2AQ==} + '@rollup/rollup-freebsd-x64@4.49.0': + resolution: {integrity: sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.48.1': - resolution: {integrity: sha512-3zEuZsXfKaw8n/yF7t8N6NNdhyFw3s8xJTqjbTDXlipwrEHo4GtIKcMJr5Ed29leLpB9AugtAQpAHW0jvtKKaQ==} + '@rollup/rollup-linux-arm-gnueabihf@4.49.0': + resolution: {integrity: sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.48.1': - resolution: {integrity: sha512-leo9tOIlKrcBmmEypzunV/2w946JeLbTdDlwEZ7OnnsUyelZ72NMnT4B2vsikSgwQifjnJUbdXzuW4ToN1wV+Q==} + '@rollup/rollup-linux-arm-musleabihf@4.49.0': + resolution: {integrity: sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.48.1': - resolution: {integrity: sha512-Vy/WS4z4jEyvnJm+CnPfExIv5sSKqZrUr98h03hpAMbE2aI0aD2wvK6GiSe8Gx2wGp3eD81cYDpLLBqNb2ydwQ==} + '@rollup/rollup-linux-arm64-gnu@4.49.0': + resolution: {integrity: sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.48.1': - resolution: {integrity: sha512-x5Kzn7XTwIssU9UYqWDB9VpLpfHYuXw5c6bJr4Mzv9kIv242vmJHbI5PJJEnmBYitUIfoMCODDhR7KoZLot2VQ==} + '@rollup/rollup-linux-arm64-musl@4.49.0': + resolution: {integrity: sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.48.1': - resolution: {integrity: sha512-yzCaBbwkkWt/EcgJOKDUdUpMHjhiZT/eDktOPWvSRpqrVE04p0Nd6EGV4/g7MARXXeOqstflqsKuXVM3H9wOIQ==} + '@rollup/rollup-linux-loongarch64-gnu@4.49.0': + resolution: {integrity: sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.48.1': - resolution: {integrity: sha512-UK0WzWUjMAJccHIeOpPhPcKBqax7QFg47hwZTp6kiMhQHeOYJeaMwzeRZe1q5IiTKsaLnHu9s6toSYVUlZ2QtQ==} + '@rollup/rollup-linux-ppc64-gnu@4.49.0': + resolution: {integrity: sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.48.1': - resolution: {integrity: sha512-3NADEIlt+aCdCbWVZ7D3tBjBX1lHpXxcvrLt/kdXTiBrOds8APTdtk2yRL2GgmnSVeX4YS1JIf0imFujg78vpw==} + '@rollup/rollup-linux-riscv64-gnu@4.49.0': + resolution: {integrity: sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.48.1': - resolution: {integrity: sha512-euuwm/QTXAMOcyiFCcrx0/S2jGvFlKJ2Iro8rsmYL53dlblp3LkUQVFzEidHhvIPPvcIsxDhl2wkBE+I6YVGzA==} + '@rollup/rollup-linux-riscv64-musl@4.49.0': + resolution: {integrity: sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.48.1': - resolution: {integrity: sha512-w8mULUjmPdWLJgmTYJx/W6Qhln1a+yqvgwmGXcQl2vFBkWsKGUBRbtLRuKJUln8Uaimf07zgJNxOhHOvjSQmBQ==} + '@rollup/rollup-linux-s390x-gnu@4.49.0': + resolution: {integrity: sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.48.1': - resolution: {integrity: sha512-90taWXCWxTbClWuMZD0DKYohY1EovA+W5iytpE89oUPmT5O1HFdf8cuuVIylE6vCbrGdIGv85lVRzTcpTRZ+kA==} + '@rollup/rollup-linux-x64-gnu@4.49.0': + resolution: {integrity: sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.48.1': - resolution: {integrity: sha512-2Gu29SkFh1FfTRuN1GR1afMuND2GKzlORQUP3mNMJbqdndOg7gNsa81JnORctazHRokiDzQ5+MLE5XYmZW5VWg==} + '@rollup/rollup-linux-x64-musl@4.49.0': + resolution: {integrity: sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.48.1': - resolution: {integrity: sha512-6kQFR1WuAO50bxkIlAVeIYsz3RUx+xymwhTo9j94dJ+kmHe9ly7muH23sdfWduD0BA8pD9/yhonUvAjxGh34jQ==} + '@rollup/rollup-win32-arm64-msvc@4.49.0': + resolution: {integrity: sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.48.1': - resolution: {integrity: sha512-RUyZZ/mga88lMI3RlXFs4WQ7n3VyU07sPXmMG7/C1NOi8qisUg57Y7LRarqoGoAiopmGmChUhSwfpvQ3H5iGSQ==} + '@rollup/rollup-win32-ia32-msvc@4.49.0': + resolution: {integrity: sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.48.1': - resolution: {integrity: sha512-8a/caCUN4vkTChxkaIJcMtwIVcBhi4X2PQRoT+yCK3qRYaZ7cURrmJFL5Ux9H9RaMIXj9RuihckdmkBX3zZsgg==} + '@rollup/rollup-win32-x64-msvc@4.49.0': + resolution: {integrity: sha512-gEtqFbzmZLFk2xKh7g0Rlo8xzho8KrEFEkzvHbfUGkrgXOpZ4XagQ6n+wIZFNh1nTb8UD16J4nFSFKXYgnbdBg==} cpu: [x64] os: [win32] @@ -1104,6 +1110,9 @@ packages: '@tauri-apps/plugin-notification@2.3.1': resolution: {integrity: sha512-7gqgfANSREKhh35fY1L4j3TUjUdePmU735FYDqRGeIf8nMXWpcx6j4FhN9/4nYz+m0mv79DCTPLqIPTySggGgg==} + '@tauri-apps/plugin-opener@2.5.0': + resolution: {integrity: sha512-B0LShOYae4CZjN8leiNDbnfjSrTwoZakqKaWpfoH6nXiJwt6Rgj6RnVIffG3DoJiKsffRhMkjmBV9VeilSb4TA==} + '@tauri-apps/plugin-window-state@2.4.0': resolution: {integrity: sha512-hRSzPNi2NG0lPFthfVY0V5C1MyWN/gGaQtQYw7i9zZhLzrhZveHZ2omHG1rIiIsjfTGbO7fhjydSoeTTK9GqLw==} @@ -1191,8 +1200,8 @@ packages: peerDependencies: '@types/react': ^19.0.0 - '@types/react@19.1.11': - resolution: {integrity: sha512-lr3jdBw/BGj49Eps7EvqlUaoeA0xpj3pc0RoJkHpYaCHkVK7i28dKyImLQb3JVlqs3aYSXf7qYuWOW/fgZnTXQ==} + '@types/react@19.1.12': + resolution: {integrity: sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==} '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -1220,8 +1229,8 @@ packages: peerDependencies: vite: ^4 || ^5 || ^6 || ^7 - '@vitejs/plugin-react@5.0.1': - resolution: {integrity: sha512-DE4UNaBXwtVoDJ0ccBdLVjFTWL70NRuWNCxEieTI3lrq9ORB9aOCQEKstwDXBl87NvFdbqh/p7eINGyj0BthJA==} + '@vitejs/plugin-react@5.0.2': + resolution: {integrity: sha512-tmyFgixPZCx2+e6VO9TNITWcCQl8+Nl/E8YbAyPVv85QCc7/A3JrdfG2A8gIzvVhWuzMOVrFW1aReaNxrI6tbw==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -1505,8 +1514,8 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} - dayjs@1.11.14: - resolution: {integrity: sha512-E8fIdSxUlyqSA8XYGnNa3IkIzxtEmFjI+JU/6ic0P1zmSqyL6HyG5jHnpPjRguDNiaHLpfvHKWFiohNsJLqcJQ==} + dayjs@1.11.15: + resolution: {integrity: sha512-MC+DfnSWiM9APs7fpiurHGCoeIx0Gdl6QZBy+5lu8MbYKN5FZEXqOgrundfibdfhGZ15o9hzmZ2xJjZnbvgKXQ==} debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} @@ -1569,8 +1578,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.209: - resolution: {integrity: sha512-Xoz0uMrim9ZETCQt8UgM5FxQF9+imA7PBpokoGcZloA1uw2LeHzTlip5cb5KOAsXZLjh/moN2vReN3ZjJmjI9A==} + electron-to-chromium@1.5.211: + resolution: {integrity: sha512-IGBvimJkotaLzFnwIVgW9/UD/AOJ2tByUmeOrtqBfACSbAw5b1G0XpvdaieKyc7ULmbwXVx+4e4Be8pOPBrYkw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2488,8 +2497,8 @@ packages: engines: {node: '>= 0.4'} hasBin: true - rollup@4.48.1: - resolution: {integrity: sha512-jVG20NvbhTYDkGAty2/Yh7HK6/q3DGSRH4o8ALKGArmMuaauM9kLfoMZ+WliPwA5+JHr2lTn3g557FxBV87ifg==} + rollup@4.49.0: + resolution: {integrity: sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -3081,7 +3090,7 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.1.11)(react@19.1.1)': + '@emotion/react@11.14.0(@types/react@19.1.12)(react@19.1.1)': dependencies: '@babel/runtime': 7.28.3 '@emotion/babel-plugin': 11.13.5 @@ -3093,7 +3102,7 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 19.1.1 optionalDependencies: - '@types/react': 19.1.11 + '@types/react': 19.1.12 transitivePeerDependencies: - supports-color @@ -3107,18 +3116,18 @@ snapshots: '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.11)(react@19.1.1))(@types/react@19.1.11)(react@19.1.1)': + '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.12)(react@19.1.1))(@types/react@19.1.12)(react@19.1.1)': dependencies: '@babel/runtime': 7.28.3 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.3.1 - '@emotion/react': 11.14.0(@types/react@19.1.11)(react@19.1.1) + '@emotion/react': 11.14.0(@types/react@19.1.12)(react@19.1.1) '@emotion/serialize': 1.3.3 '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.1.1) '@emotion/utils': 1.4.2 react: 19.1.1 optionalDependencies: - '@types/react': 19.1.11 + '@types/react': 19.1.12 transitivePeerDependencies: - supports-color @@ -3235,7 +3244,7 @@ snapshots: '@floating-ui/utils@0.2.10': {} - '@gerrit0/mini-shiki@3.11.0': + '@gerrit0/mini-shiki@3.12.0': dependencies: '@shikijs/engine-oniguruma': 3.12.0 '@shikijs/langs': 3.12.0 @@ -3243,10 +3252,10 @@ snapshots: '@shikijs/types': 3.12.0 '@shikijs/vscode-textmate': 10.0.2 - '@hookform/devtools@4.4.0(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@hookform/devtools@4.4.0(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@emotion/react': 11.14.0(@types/react@19.1.11)(react@19.1.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.11)(react@19.1.1))(@types/react@19.1.11)(react@19.1.1) + '@emotion/react': 11.14.0(@types/react@19.1.12)(react@19.1.1) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.12)(react@19.1.1))(@types/react@19.1.12)(react@19.1.1) '@types/lodash': 4.17.20 little-state-machine: 4.8.1(react@19.1.1) lodash: 4.17.21 @@ -3291,7 +3300,7 @@ snapshots: '@react-hook/passive-layout-effect': 1.2.1(react@19.1.1) react: 19.1.1 - '@reduxjs/toolkit@2.8.2(react-redux@9.2.0(@types/react@19.1.11)(react@19.1.1)(redux@5.0.1))(react@19.1.1)': + '@reduxjs/toolkit@2.8.2(react-redux@9.2.0(@types/react@19.1.12)(react@19.1.1)(redux@5.0.1))(react@19.1.1)': dependencies: '@standard-schema/spec': 1.0.0 '@standard-schema/utils': 0.3.0 @@ -3301,70 +3310,72 @@ snapshots: reselect: 5.1.1 optionalDependencies: react: 19.1.1 - react-redux: 9.2.0(@types/react@19.1.11)(react@19.1.1)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.1.12)(react@19.1.1)(redux@5.0.1) '@remix-run/router@1.23.0': {} '@rolldown/pluginutils@1.0.0-beta.32': {} - '@rollup/rollup-android-arm-eabi@4.48.1': + '@rolldown/pluginutils@1.0.0-beta.34': {} + + '@rollup/rollup-android-arm-eabi@4.49.0': optional: true - '@rollup/rollup-android-arm64@4.48.1': + '@rollup/rollup-android-arm64@4.49.0': optional: true - '@rollup/rollup-darwin-arm64@4.48.1': + '@rollup/rollup-darwin-arm64@4.49.0': optional: true - '@rollup/rollup-darwin-x64@4.48.1': + '@rollup/rollup-darwin-x64@4.49.0': optional: true - '@rollup/rollup-freebsd-arm64@4.48.1': + '@rollup/rollup-freebsd-arm64@4.49.0': optional: true - '@rollup/rollup-freebsd-x64@4.48.1': + '@rollup/rollup-freebsd-x64@4.49.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.48.1': + '@rollup/rollup-linux-arm-gnueabihf@4.49.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.48.1': + '@rollup/rollup-linux-arm-musleabihf@4.49.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.48.1': + '@rollup/rollup-linux-arm64-gnu@4.49.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.48.1': + '@rollup/rollup-linux-arm64-musl@4.49.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.48.1': + '@rollup/rollup-linux-loongarch64-gnu@4.49.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.48.1': + '@rollup/rollup-linux-ppc64-gnu@4.49.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.48.1': + '@rollup/rollup-linux-riscv64-gnu@4.49.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.48.1': + '@rollup/rollup-linux-riscv64-musl@4.49.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.48.1': + '@rollup/rollup-linux-s390x-gnu@4.49.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.48.1': + '@rollup/rollup-linux-x64-gnu@4.49.0': optional: true - '@rollup/rollup-linux-x64-musl@4.48.1': + '@rollup/rollup-linux-x64-musl@4.49.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.48.1': + '@rollup/rollup-win32-arm64-msvc@4.49.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.48.1': + '@rollup/rollup-win32-ia32-msvc@4.49.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.48.1': + '@rollup/rollup-win32-x64-msvc@4.49.0': optional: true '@shikijs/engine-oniguruma@3.12.0': @@ -3671,6 +3682,10 @@ snapshots: dependencies: '@tauri-apps/api': 2.8.0 + '@tauri-apps/plugin-opener@2.5.0': + dependencies: + '@tauri-apps/api': 2.8.0 + '@tauri-apps/plugin-window-state@2.4.0': dependencies: '@tauri-apps/api': 2.8.0 @@ -3758,11 +3773,11 @@ snapshots: '@types/parse-json@4.0.2': {} - '@types/react-dom@19.1.8(@types/react@19.1.11)': + '@types/react-dom@19.1.8(@types/react@19.1.12)': dependencies: - '@types/react': 19.1.11 + '@types/react': 19.1.12 - '@types/react@19.1.11': + '@types/react@19.1.12': dependencies: csstype: 3.1.3 @@ -3789,12 +3804,12 @@ snapshots: transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@5.0.1(vite@7.1.3(@types/node@24.3.0)(sass@1.70.0)(yaml@2.8.1))': + '@vitejs/plugin-react@5.0.2(vite@7.1.3(@types/node@24.3.0)(sass@1.70.0)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.3 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.3) '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.3) - '@rolldown/pluginutils': 1.0.0-beta.32 + '@rolldown/pluginutils': 1.0.0-beta.34 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 vite: 7.1.3(@types/node@24.3.0)(sass@1.70.0)(yaml@2.8.1) @@ -3879,7 +3894,7 @@ snapshots: browserslist@4.25.3: dependencies: caniuse-lite: 1.0.30001737 - electron-to-chromium: 1.5.209 + electron-to-chromium: 1.5.211 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.25.3) @@ -4086,7 +4101,7 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 - dayjs@1.11.14: {} + dayjs@1.11.15: {} debug@4.4.1: dependencies: @@ -4151,7 +4166,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.209: {} + electron-to-chromium@1.5.211: {} emoji-regex@8.0.0: {} @@ -4448,7 +4463,7 @@ snapshots: domhandler: 5.0.3 htmlparser2: 10.0.0 - html-react-parser@5.2.6(@types/react@19.1.11)(react@19.1.1): + html-react-parser@5.2.6(@types/react@19.1.12)(react@19.1.1): dependencies: domhandler: 5.0.3 html-dom-parser: 5.1.1 @@ -4456,7 +4471,7 @@ snapshots: react-property: 2.0.2 style-to-js: 1.1.17 optionalDependencies: - '@types/react': 19.1.11 + '@types/react': 19.1.12 html-url-attributes@3.0.1: {} @@ -4788,9 +4803,9 @@ snapshots: memorystream@0.3.1: {} - merge-refs@2.0.0(@types/react@19.1.11): + merge-refs@2.0.0(@types/react@19.1.12): optionalDependencies: - '@types/react': 19.1.11 + '@types/react': 19.1.12 micromark-core-commonmark@2.0.3: dependencies: @@ -5123,11 +5138,11 @@ snapshots: dependencies: react: 19.1.1 - react-markdown@10.1.0(@types/react@19.1.11)(react@19.1.1): + react-markdown@10.1.0(@types/react@19.1.12)(react@19.1.1): dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@types/react': 19.1.11 + '@types/react': 19.1.12 devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 @@ -5149,13 +5164,13 @@ snapshots: qr.js: 0.0.0 react: 19.1.1 - react-redux@9.2.0(@types/react@19.1.11)(react@19.1.1)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.1.12)(react@19.1.1)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 react: 19.1.1 use-sync-external-store: 1.5.0(react@19.1.1) optionalDependencies: - '@types/react': 19.1.11 + '@types/react': 19.1.12 redux: 5.0.1 react-refresh@0.17.0: {} @@ -5195,9 +5210,9 @@ snapshots: dependencies: picomatch: 2.3.1 - recharts@3.1.2(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react-is@18.3.1)(react@19.1.1)(redux@5.0.1): + recharts@3.1.2(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react-is@18.3.1)(react@19.1.1)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.8.2(react-redux@9.2.0(@types/react@19.1.11)(react@19.1.1)(redux@5.0.1))(react@19.1.1) + '@reduxjs/toolkit': 2.8.2(react-redux@9.2.0(@types/react@19.1.12)(react@19.1.1)(redux@5.0.1))(react@19.1.1) clsx: 2.1.1 decimal.js-light: 2.5.1 es-toolkit: 1.39.10 @@ -5206,7 +5221,7 @@ snapshots: react: 19.1.1 react-dom: 19.1.1(react@19.1.1) react-is: 18.3.1 - react-redux: 9.2.0(@types/react@19.1.11)(react@19.1.1)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.1.12)(react@19.1.1)(redux@5.0.1) reselect: 5.1.1 tiny-invariant: 1.3.3 use-sync-external-store: 1.5.0(react@19.1.1) @@ -5275,30 +5290,30 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - rollup@4.48.1: + rollup@4.49.0: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.48.1 - '@rollup/rollup-android-arm64': 4.48.1 - '@rollup/rollup-darwin-arm64': 4.48.1 - '@rollup/rollup-darwin-x64': 4.48.1 - '@rollup/rollup-freebsd-arm64': 4.48.1 - '@rollup/rollup-freebsd-x64': 4.48.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.48.1 - '@rollup/rollup-linux-arm-musleabihf': 4.48.1 - '@rollup/rollup-linux-arm64-gnu': 4.48.1 - '@rollup/rollup-linux-arm64-musl': 4.48.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.48.1 - '@rollup/rollup-linux-ppc64-gnu': 4.48.1 - '@rollup/rollup-linux-riscv64-gnu': 4.48.1 - '@rollup/rollup-linux-riscv64-musl': 4.48.1 - '@rollup/rollup-linux-s390x-gnu': 4.48.1 - '@rollup/rollup-linux-x64-gnu': 4.48.1 - '@rollup/rollup-linux-x64-musl': 4.48.1 - '@rollup/rollup-win32-arm64-msvc': 4.48.1 - '@rollup/rollup-win32-ia32-msvc': 4.48.1 - '@rollup/rollup-win32-x64-msvc': 4.48.1 + '@rollup/rollup-android-arm-eabi': 4.49.0 + '@rollup/rollup-android-arm64': 4.49.0 + '@rollup/rollup-darwin-arm64': 4.49.0 + '@rollup/rollup-darwin-x64': 4.49.0 + '@rollup/rollup-freebsd-arm64': 4.49.0 + '@rollup/rollup-freebsd-x64': 4.49.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.49.0 + '@rollup/rollup-linux-arm-musleabihf': 4.49.0 + '@rollup/rollup-linux-arm64-gnu': 4.49.0 + '@rollup/rollup-linux-arm64-musl': 4.49.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.49.0 + '@rollup/rollup-linux-ppc64-gnu': 4.49.0 + '@rollup/rollup-linux-riscv64-gnu': 4.49.0 + '@rollup/rollup-linux-riscv64-musl': 4.49.0 + '@rollup/rollup-linux-s390x-gnu': 4.49.0 + '@rollup/rollup-linux-x64-gnu': 4.49.0 + '@rollup/rollup-linux-x64-musl': 4.49.0 + '@rollup/rollup-win32-arm64-msvc': 4.49.0 + '@rollup/rollup-win32-ia32-msvc': 4.49.0 + '@rollup/rollup-win32-x64-msvc': 4.49.0 fsevents: 2.3.3 rxjs@7.8.2: @@ -5557,7 +5572,7 @@ snapshots: typedoc@0.28.11(typescript@5.9.2): dependencies: - '@gerrit0/mini-shiki': 3.11.0 + '@gerrit0/mini-shiki': 3.12.0 lunr: 2.3.9 markdown-it: 14.1.0 minimatch: 9.0.5 @@ -5675,7 +5690,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.48.1 + rollup: 4.49.0 tinyglobby: 0.2.14 optionalDependencies: '@types/node': 24.3.0 @@ -5758,9 +5773,9 @@ snapshots: zod@3.25.76: {} - zustand@5.0.8(@types/react@19.1.11)(immer@10.1.1)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)): + zustand@5.0.8(@types/react@19.1.12)(immer@10.1.1)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)): optionalDependencies: - '@types/react': 19.1.11 + '@types/react': 19.1.12 immer: 10.1.1 react: 19.1.1 use-sync-external-store: 1.5.0(react@19.1.1) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d719f8e7..ae66fa66 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1265,6 +1265,7 @@ dependencies = [ "tauri-plugin-http", "tauri-plugin-log", "tauri-plugin-notification", + "tauri-plugin-opener", "tauri-plugin-single-instance", "tauri-plugin-window-state", "thiserror 2.0.16", @@ -2787,6 +2788,25 @@ dependencies = [ "serde", ] +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -3766,6 +3786,18 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +[[package]] +name = "open" +version = "5.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" +dependencies = [ + "dunce", + "is-wsl", + "libc", + "pathdiff", +] + [[package]] name = "openssl" version = "0.10.73" @@ -3922,6 +3954,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -6215,6 +6253,28 @@ dependencies = [ "url", ] +[[package]] +name = "tauri-plugin-opener" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786156aa8e89e03d271fbd3fe642207da8e65f3c961baa9e2930f332bf80a1f5" +dependencies = [ + "dunce", + "glob", + "objc2-app-kit", + "objc2-foundation 0.3.1", + "open", + "schemars 0.8.22", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.16", + "url", + "windows", + "zbus", +] + [[package]] name = "tauri-plugin-single-instance" version = "2.3.3" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 2d8f35f0..9c507f93 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -94,6 +94,7 @@ x25519-dalek = { version = "2", features = [ "serde", "static_secrets", ] } +tauri-plugin-opener = "2.5.0" [target.'cfg(unix)'.dependencies] tokio-stream = "0.1" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index f3da2f08..7f69045c 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -59,6 +59,14 @@ "url": "http://*:*" } ] + }, + { + "identifier": "opener:allow-open-url", + "allow": [ + { + "url": "https://*" + } + ] } ] } diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index e1ceaae5..a6ddd269 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -187,6 +187,7 @@ fn main() { .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_notification::init()) .plugin(tauri_plugin_window_state::Builder::new().build()) + .plugin(tauri_plugin_opener::init()) .setup(|app| { // Handle deep-links. let app_handle = app.app_handle().clone(); diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs index e2ba9868..e2a03b6a 100644 --- a/src-tauri/src/database/mod.rs +++ b/src-tauri/src/database/mod.rs @@ -19,6 +19,7 @@ pub static DB_POOL: LazyLock = LazyLock::new(|| { let db_url = prepare_db_url().expect("Wrong database URL."); let opts = SqliteConnectOptions::from_str(&db_url) .expect("Failed to set database connenction options.") + .create_if_missing(true) .auto_vacuum(SqliteAutoVacuum::Incremental) .journal_mode(SqliteJournalMode::Wal); debug!("Connecting to database: {db_url} with options: {opts:?}"); diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx index 2c569e17..a4cbc185 100644 --- a/src/components/App/App.tsx +++ b/src/components/App/App.tsx @@ -5,6 +5,7 @@ import '../../shared/scss/index.scss'; import { QueryClient } from '@tanstack/query-core'; import { QueryClientProvider } from '@tanstack/react-query'; import { debug } from '@tauri-apps/plugin-log'; +import { openUrl } from '@tauri-apps/plugin-opener'; import dayjs from 'dayjs'; import customParseData from 'dayjs/plugin/customParseFormat'; import duration from 'dayjs/plugin/duration'; @@ -166,6 +167,26 @@ export const App = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + useEffect(() => { + const handler = (e: MouseEvent) => { + const target = e.target as HTMLElement | undefined; + if (target) { + const link = target.closest('a'); + if ( + link instanceof HTMLAnchorElement && + link.target === '_blank' && + link.href.startsWith('https') + ) { + void openUrl(link.href); + } + } + }; + document.addEventListener('click', handler); + return () => { + document.removeEventListener('click', handler); + }; + }, []); + if (!appLoaded) return null; return ( diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts index 82640aa2..3f8e0e5e 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -491,6 +491,9 @@ If this will not change, please contact your administrator.`, vpn: 'Configure VPN', finish: 'Finish', mfa: 'Configure MFA', + mfaChoice: 'Choose method', + mfaSetup: 'Complete method', + mfaRecovery: 'Recovery codes', }, appVersion: 'Application version', }, diff --git a/src/i18n/i18n-types.ts b/src/i18n/i18n-types.ts index a2809126..78a251c1 100644 --- a/src/i18n/i18n-types.ts +++ b/src/i18n/i18n-types.ts @@ -1130,6 +1130,18 @@ type RootTranslation = { * C​o​n​f​i​g​u​r​e​ ​M​F​A */ mfa: string + /** + * C​h​o​o​s​e​ ​m​e​t​h​o​d + */ + mfaChoice: string + /** + * C​o​m​p​l​e​t​e​ ​m​e​t​h​o​d + */ + mfaSetup: string + /** + * R​e​c​o​v​e​r​y​ ​c​o​d​e​s + */ + mfaRecovery: string } /** * A​p​p​l​i​c​a​t​i​o​n​ ​v​e​r​s​i​o​n @@ -2798,6 +2810,18 @@ export type TranslationFunctions = { * Configure MFA */ mfa: () => LocalizedString + /** + * Choose method + */ + mfaChoice: () => LocalizedString + /** + * Complete method + */ + mfaSetup: () => LocalizedString + /** + * Recovery codes + */ + mfaRecovery: () => LocalizedString } /** * Application version diff --git a/src/pages/client/components/ClientSideBar/ClientSideBar.tsx b/src/pages/client/components/ClientSideBar/ClientSideBar.tsx index 9e7161c5..88543ce9 100644 --- a/src/pages/client/components/ClientSideBar/ClientSideBar.tsx +++ b/src/pages/client/components/ClientSideBar/ClientSideBar.tsx @@ -16,14 +16,11 @@ import { IconContainer } from '../../../../shared/defguard-ui/components/Layout/ import SvgIconPlus from '../../../../shared/defguard-ui/components/svg/IconPlus'; import SvgIconSettings from '../../../../shared/defguard-ui/components/svg/IconSettings'; import { routes } from '../../../../shared/routes'; -import { clientApi } from '../../clientAPI/clientApi'; import { useClientStore } from '../../hooks/useClientStore'; import { WireguardInstanceType } from '../../types'; import { ClientBarItem } from './components/ClientBarItem/ClientBarItem'; import { NewApplicationVersionAvailableInfo } from './components/NewApplicationVersionAvailableInfo/NewApplicationVersionAvailableInfo'; -const { openLink } = clientApi; - export const ClientSideBar = () => { const navigate = useNavigate(); const { LL } = useI18nContext(); @@ -133,13 +130,19 @@ const FooterApplicationInfo = () => { ); diff --git a/src/pages/client/components/ClientSideBar/style.scss b/src/pages/client/components/ClientSideBar/style.scss index 8f6aacb2..ad97b195 100644 --- a/src/pages/client/components/ClientSideBar/style.scss +++ b/src/pages/client/components/ClientSideBar/style.scss @@ -281,7 +281,8 @@ padding-right: 5px; } - & > span { + & > a { + color: inherit; cursor: pointer; } } diff --git a/src/pages/enrollment/EnrollmentPage.tsx b/src/pages/enrollment/EnrollmentPage.tsx index a4a94d8c..d0cc4a5a 100644 --- a/src/pages/enrollment/EnrollmentPage.tsx +++ b/src/pages/enrollment/EnrollmentPage.tsx @@ -2,7 +2,7 @@ import './style.scss'; import { debug, error } from '@tauri-apps/plugin-log'; import dayjs from 'dayjs'; -import { type ReactNode, useEffect, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { useBreakpoint } from 'use-breakpoint'; import { shallow } from 'zustand/shallow'; @@ -24,14 +24,8 @@ import { import { routes } from '../../shared/routes'; import { EnrollmentSideBar } from './components/EnrollmentSideBar/EnrollmentSideBar'; import { EnrollmentStepControls } from './components/EnrollmentStepControls/EnrollmentStepControls'; +import { EnrollmentStepKey, enrollmentSteps, flattenEnrollConf } from './const'; import { useEnrollmentStore } from './hooks/store/useEnrollmentStore'; -import { DataVerificationStep } from './steps/DataVerificationStep/DataVerificationStep'; -import { DeviceStep } from './steps/DeviceStep/DeviceStep'; -import { FinishStep } from './steps/FinishStep/FinishStep'; -import { PasswordStep } from './steps/PasswordStep/PasswordStep'; -import { SendFinishStep } from './steps/SendFinishStep/SendFinishStep'; -import { TotpEnrollmentStep } from './steps/Totp/TotpEnrollmentStep'; -import { WelcomeStep } from './steps/WelcomeStep/WelcomeStep'; export const EnrollmentPage = () => { const enrollmentFinished = useRef(false); @@ -40,30 +34,16 @@ export const EnrollmentPage = () => { const { breakpoint } = useBreakpoint(deviceBreakpoints); const sessionEnd = useEnrollmentStore((state) => state.sessionEnd); const currentStep = useEnrollmentStore((state) => state.step); - const stepsMax = useEnrollmentStore((state) => state.stepsMax); const loading = useEnrollmentStore((state) => state.loading); - const [setEnrollmentState, back, _reset, nextSubject] = useEnrollmentStore( - (state) => [state.setState, state.perviousStep, state.reset, state.nextSubject], - shallow, - ); + const [back, next] = useEnrollmentStore((state) => [state.back, state.next], shallow); const controlsSize: ButtonSize = breakpoint !== 'desktop' ? ButtonSize.SMALL : ButtonSize.LARGE; - // ensure number of steps is correct - useEffect(() => { - const stepsIgnored: number[] = []; - steps.forEach((step, index) => { - if (step.ignoreCount) { - stepsIgnored.push(index); - } - }); - setEnrollmentState({ - stepsIgnored, - stepsMax: steps.length - 1, - }); - }, [setEnrollmentState]); + const flatConf = useMemo(() => flattenEnrollConf(), []); + + const currentStepConfig = flatConf[currentStep]; useEffect(() => { if (!enrollmentFinished.current) { @@ -92,8 +72,12 @@ export const EnrollmentPage = () => { }, [sessionEnd, navigate]); useEffect(() => { - enrollmentFinished.current = stepsMax === currentStep; - }, [currentStep, stepsMax]); + enrollmentFinished.current = currentStep === EnrollmentStepKey.FINISH; + }, [currentStep]); + + useEffect(() => { + console.log(currentStepConfig); + }, [currentStepConfig]); return ( @@ -105,7 +89,7 @@ export const EnrollmentPage = () => { size={controlsSize} styleVariant={ButtonStyleVariant.STANDARD} onClick={() => back()} - disabled={(steps[currentStep].backDisabled ?? false) || loading} + disabled={!currentStepConfig?.backEnabled || loading} icon={ { />