Browse Source
Add PKI backup dialog, add reminder toast to suggest backing up private key.pull/384/head
committed by
GitHub
17 changed files with 730 additions and 300 deletions
@ -89,6 +89,9 @@ importers: |
|||||
immer: |
immer: |
||||
specifier: ^10.1.1 |
specifier: ^10.1.1 |
||||
version: 10.1.1 |
version: 10.1.1 |
||||
|
js-cookie: |
||||
|
specifier: ^3.0.5 |
||||
|
version: 3.0.5 |
||||
lucide-react: |
lucide-react: |
||||
specifier: ^0.363.0 |
specifier: ^0.363.0 |
||||
version: 0.363.0([email protected]) |
version: 0.363.0([email protected]) |
||||
@ -127,7 +130,7 @@ importers: |
|||||
version: 3.0.6([email protected]) |
version: 3.0.6([email protected]) |
||||
vite-plugin-node-polyfills: |
vite-plugin-node-polyfills: |
||||
specifier: ^0.22.0 |
specifier: ^0.22.0 |
||||
version: 0.22.0([email protected]4.0)([email protected](@types/[email protected])) |
version: 0.22.0([email protected]9.1)([email protected](@types/[email protected])) |
||||
zustand: |
zustand: |
||||
specifier: 4.5.2 |
specifier: 4.5.2 |
||||
version: 4.5.2(@types/[email protected])([email protected])([email protected]) |
version: 4.5.2(@types/[email protected])([email protected])([email protected]) |
||||
@ -147,6 +150,9 @@ importers: |
|||||
'@types/chrome': |
'@types/chrome': |
||||
specifier: ^0.0.263 |
specifier: ^0.0.263 |
||||
version: 0.0.263 |
version: 0.0.263 |
||||
|
'@types/js-cookie': |
||||
|
specifier: ^3.0.6 |
||||
|
version: 3.0.6 |
||||
'@types/node': |
'@types/node': |
||||
specifier: ^20.14.9 |
specifier: ^20.14.9 |
||||
version: 20.14.9 |
version: 20.14.9 |
||||
@ -173,7 +179,7 @@ importers: |
|||||
version: 8.4.38 |
version: 8.4.38 |
||||
rollup-plugin-visualizer: |
rollup-plugin-visualizer: |
||||
specifier: ^5.12.0 |
specifier: ^5.12.0 |
||||
version: 5.12.0([email protected]4.0) |
version: 5.12.0([email protected]9.1) |
||||
tailwindcss: |
tailwindcss: |
||||
specifier: ^3.4.4 |
specifier: ^3.4.4 |
||||
version: 3.4.4 |
version: 3.4.4 |
||||
@ -1165,83 +1171,98 @@ packages: |
|||||
rollup: |
rollup: |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} |
resolution: {integrity: sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==} |
||||
cpu: [arm] |
cpu: [arm] |
||||
os: [android] |
os: [android] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} |
resolution: {integrity: sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==} |
||||
cpu: [arm64] |
cpu: [arm64] |
||||
os: [android] |
os: [android] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} |
resolution: {integrity: sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==} |
||||
cpu: [arm64] |
cpu: [arm64] |
||||
os: [darwin] |
os: [darwin] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} |
resolution: {integrity: sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==} |
||||
cpu: [x64] |
cpu: [x64] |
||||
os: [darwin] |
os: [darwin] |
||||
|
|
||||
'@rollup/[email protected]': |
'@rollup/[email protected]': |
||||
resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} |
resolution: {integrity: sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==} |
||||
|
cpu: [arm64] |
||||
|
os: [freebsd] |
||||
|
|
||||
|
'@rollup/[email protected]': |
||||
|
resolution: {integrity: sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==} |
||||
|
cpu: [x64] |
||||
|
os: [freebsd] |
||||
|
|
||||
|
'@rollup/[email protected]': |
||||
|
resolution: {integrity: sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==} |
||||
cpu: [arm] |
cpu: [arm] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} |
resolution: {integrity: sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==} |
||||
cpu: [arm] |
cpu: [arm] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} |
resolution: {integrity: sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==} |
||||
cpu: [arm64] |
cpu: [arm64] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} |
resolution: {integrity: sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==} |
||||
cpu: [arm64] |
cpu: [arm64] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]': |
'@rollup/[email protected]': |
||||
resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} |
resolution: {integrity: sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==} |
||||
|
cpu: [loong64] |
||||
|
os: [linux] |
||||
|
|
||||
|
'@rollup/[email protected]': |
||||
|
resolution: {integrity: sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==} |
||||
cpu: [ppc64] |
cpu: [ppc64] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} |
resolution: {integrity: sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==} |
||||
cpu: [riscv64] |
cpu: [riscv64] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} |
resolution: {integrity: sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==} |
||||
cpu: [s390x] |
cpu: [s390x] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} |
resolution: {integrity: sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==} |
||||
cpu: [x64] |
cpu: [x64] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} |
resolution: {integrity: sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==} |
||||
cpu: [x64] |
cpu: [x64] |
||||
os: [linux] |
os: [linux] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} |
resolution: {integrity: sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==} |
||||
cpu: [arm64] |
cpu: [arm64] |
||||
os: [win32] |
os: [win32] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} |
resolution: {integrity: sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==} |
||||
cpu: [ia32] |
cpu: [ia32] |
||||
os: [win32] |
os: [win32] |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} |
resolution: {integrity: sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==} |
||||
cpu: [x64] |
cpu: [x64] |
||||
os: [win32] |
os: [win32] |
||||
|
|
||||
@ -1690,6 +1711,9 @@ packages: |
|||||
'@types/[email protected]': |
'@types/[email protected]': |
||||
resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==} |
resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==} |
||||
|
|
||||
|
'@types/[email protected]': |
||||
|
resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} |
||||
|
|
||||
'@types/[email protected]': |
'@types/[email protected]': |
||||
resolution: {integrity: sha512-hI6cQDjw1bkJw7MC/eHMqq5TWUamLwsujnUUeiIX2KDRjxRNSYMjnHz07+LATz9I9XIsKumOtUz4gRYnZOJ/FA==} |
resolution: {integrity: sha512-hI6cQDjw1bkJw7MC/eHMqq5TWUamLwsujnUUeiIX2KDRjxRNSYMjnHz07+LATz9I9XIsKumOtUz4gRYnZOJ/FA==} |
||||
|
|
||||
@ -1864,8 +1888,8 @@ packages: |
|||||
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} |
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} |
||||
engines: {node: '>= 6'} |
engines: {node: '>= 6'} |
||||
|
|
||||
[email protected]38: |
[email protected]90: |
||||
resolution: {integrity: sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ==} |
resolution: {integrity: sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==} |
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
resolution: {integrity: sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==} |
resolution: {integrity: sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==} |
||||
@ -2417,6 +2441,10 @@ packages: |
|||||
resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} |
resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} |
||||
hasBin: true |
hasBin: true |
||||
|
|
||||
|
[email protected]: |
||||
|
resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} |
||||
|
engines: {node: '>=14'} |
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} |
resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} |
||||
|
|
||||
@ -2923,8 +2951,8 @@ packages: |
|||||
rollup: |
rollup: |
||||
optional: true |
optional: true |
||||
|
|
||||
[email protected]4.0: |
[email protected]9.1: |
||||
resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} |
resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==} |
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'} |
engines: {node: '>=18.0.0', npm: '>=8.0.0'} |
||||
hasBin: true |
hasBin: true |
||||
|
|
||||
@ -4258,68 +4286,77 @@ snapshots: |
|||||
|
|
||||
'@radix-ui/[email protected]': {} |
'@radix-ui/[email protected]': {} |
||||
|
|
||||
'@rollup/[email protected]([email protected]4.0)': |
'@rollup/[email protected]([email protected]9.1)': |
||||
dependencies: |
dependencies: |
||||
'@rollup/pluginutils': 5.1.0([email protected]4.0) |
'@rollup/pluginutils': 5.1.0([email protected]9.1) |
||||
estree-walker: 2.0.2 |
estree-walker: 2.0.2 |
||||
magic-string: 0.30.11 |
magic-string: 0.30.11 |
||||
optionalDependencies: |
optionalDependencies: |
||||
rollup: 4.24.0 |
rollup: 4.29.1 |
||||
|
|
||||
'@rollup/[email protected]([email protected]4.0)': |
'@rollup/[email protected]([email protected]9.1)': |
||||
dependencies: |
dependencies: |
||||
'@types/estree': 1.0.5 |
'@types/estree': 1.0.5 |
||||
estree-walker: 2.0.2 |
estree-walker: 2.0.2 |
||||
picomatch: 2.3.1 |
picomatch: 2.3.1 |
||||
optionalDependencies: |
optionalDependencies: |
||||
rollup: 4.24.0 |
rollup: 4.29.1 |
||||
|
|
||||
|
'@rollup/[email protected]': |
||||
|
optional: true |
||||
|
|
||||
|
'@rollup/[email protected]': |
||||
|
optional: true |
||||
|
|
||||
|
'@rollup/[email protected]': |
||||
|
optional: true |
||||
|
|
||||
'@rollup/[email protected]': |
'@rollup/rollup-[email protected]': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]': |
'@rollup/rollup-[email protected]': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]': |
'@rollup/rollup-[email protected]': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/rollup-[email protected]': |
'@rollup/rollup-[email protected]': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/rollup-linux-arm-[email protected]': |
'@rollup/rollup-linux-arm-[email protected]': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/rollup-linux-arm[email protected]': |
'@rollup/rollup-linux-arm[email protected]': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/rollup-linux-arm64-[email protected]': |
'@rollup/rollup-linux-arm64-[email protected]': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/rollup-linux-[email protected]': |
'@rollup/rollup-linux-[email protected]': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rollup/[email protected]4.0': |
'@rollup/[email protected]9.1': |
||||
optional: true |
optional: true |
||||
|
|
||||
'@rsbuild/[email protected]': |
'@rsbuild/[email protected]': |
||||
@ -4381,7 +4418,7 @@ snapshots: |
|||||
'@module-federation/runtime-tools': 0.5.1 |
'@module-federation/runtime-tools': 0.5.1 |
||||
'@rspack/binding': 1.0.8 |
'@rspack/binding': 1.0.8 |
||||
'@rspack/lite-tapable': 1.0.1 |
'@rspack/lite-tapable': 1.0.1 |
||||
caniuse-lite: 1.0.30001638 |
caniuse-lite: 1.0.30001690 |
||||
optionalDependencies: |
optionalDependencies: |
||||
'@swc/helpers': 0.5.13 |
'@swc/helpers': 0.5.13 |
||||
|
|
||||
@ -5255,6 +5292,8 @@ snapshots: |
|||||
|
|
||||
'@types/[email protected]': {} |
'@types/[email protected]': {} |
||||
|
|
||||
|
'@types/[email protected]': {} |
||||
|
|
||||
'@types/[email protected]': |
'@types/[email protected]': |
||||
dependencies: |
dependencies: |
||||
'@types/geojson': 7946.0.14 |
'@types/geojson': 7946.0.14 |
||||
@ -5343,7 +5382,7 @@ snapshots: |
|||||
[email protected]([email protected]): |
[email protected]([email protected]): |
||||
dependencies: |
dependencies: |
||||
browserslist: 4.23.1 |
browserslist: 4.23.1 |
||||
caniuse-lite: 1.0.30001638 |
caniuse-lite: 1.0.30001690 |
||||
fraction.js: 4.3.7 |
fraction.js: 4.3.7 |
||||
normalize-range: 0.1.2 |
normalize-range: 0.1.2 |
||||
picocolors: 1.0.1 |
picocolors: 1.0.1 |
||||
@ -5424,7 +5463,7 @@ snapshots: |
|||||
|
|
||||
[email protected]: |
[email protected]: |
||||
dependencies: |
dependencies: |
||||
caniuse-lite: 1.0.30001638 |
caniuse-lite: 1.0.30001690 |
||||
electron-to-chromium: 1.4.812 |
electron-to-chromium: 1.4.812 |
||||
node-releases: 2.0.14 |
node-releases: 2.0.14 |
||||
update-browserslist-db: 1.0.16([email protected]) |
update-browserslist-db: 1.0.16([email protected]) |
||||
@ -5459,7 +5498,7 @@ snapshots: |
|||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
[email protected]38: {} |
[email protected]90: {} |
||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
@ -6075,6 +6114,8 @@ snapshots: |
|||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
|
[email protected]: {} |
||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
@ -6620,35 +6661,38 @@ snapshots: |
|||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
[email protected]([email protected]4.0): |
[email protected]([email protected]9.1): |
||||
dependencies: |
dependencies: |
||||
open: 8.4.2 |
open: 8.4.2 |
||||
picomatch: 2.3.1 |
picomatch: 2.3.1 |
||||
source-map: 0.7.4 |
source-map: 0.7.4 |
||||
yargs: 17.7.2 |
yargs: 17.7.2 |
||||
optionalDependencies: |
optionalDependencies: |
||||
rollup: 4.24.0 |
rollup: 4.29.1 |
||||
|
|
||||
[email protected]4.0: |
[email protected]9.1: |
||||
dependencies: |
dependencies: |
||||
'@types/estree': 1.0.6 |
'@types/estree': 1.0.6 |
||||
optionalDependencies: |
optionalDependencies: |
||||
'@rollup/rollup-android-arm-eabi': 4.24.0 |
'@rollup/rollup-android-arm-eabi': 4.29.1 |
||||
'@rollup/rollup-android-arm64': 4.24.0 |
'@rollup/rollup-android-arm64': 4.29.1 |
||||
'@rollup/rollup-darwin-arm64': 4.24.0 |
'@rollup/rollup-darwin-arm64': 4.29.1 |
||||
'@rollup/rollup-darwin-x64': 4.24.0 |
'@rollup/rollup-darwin-x64': 4.29.1 |
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.24.0 |
'@rollup/rollup-freebsd-arm64': 4.29.1 |
||||
'@rollup/rollup-linux-arm-musleabihf': 4.24.0 |
'@rollup/rollup-freebsd-x64': 4.29.1 |
||||
'@rollup/rollup-linux-arm64-gnu': 4.24.0 |
'@rollup/rollup-linux-arm-gnueabihf': 4.29.1 |
||||
'@rollup/rollup-linux-arm64-musl': 4.24.0 |
'@rollup/rollup-linux-arm-musleabihf': 4.29.1 |
||||
'@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 |
'@rollup/rollup-linux-arm64-gnu': 4.29.1 |
||||
'@rollup/rollup-linux-riscv64-gnu': 4.24.0 |
'@rollup/rollup-linux-arm64-musl': 4.29.1 |
||||
'@rollup/rollup-linux-s390x-gnu': 4.24.0 |
'@rollup/rollup-linux-loongarch64-gnu': 4.29.1 |
||||
'@rollup/rollup-linux-x64-gnu': 4.24.0 |
'@rollup/rollup-linux-powerpc64le-gnu': 4.29.1 |
||||
'@rollup/rollup-linux-x64-musl': 4.24.0 |
'@rollup/rollup-linux-riscv64-gnu': 4.29.1 |
||||
'@rollup/rollup-win32-arm64-msvc': 4.24.0 |
'@rollup/rollup-linux-s390x-gnu': 4.29.1 |
||||
'@rollup/rollup-win32-ia32-msvc': 4.24.0 |
'@rollup/rollup-linux-x64-gnu': 4.29.1 |
||||
'@rollup/rollup-win32-x64-msvc': 4.24.0 |
'@rollup/rollup-linux-x64-musl': 4.29.1 |
||||
|
'@rollup/rollup-win32-arm64-msvc': 4.29.1 |
||||
|
'@rollup/rollup-win32-ia32-msvc': 4.29.1 |
||||
|
'@rollup/rollup-win32-x64-msvc': 4.29.1 |
||||
fsevents: 2.3.3 |
fsevents: 2.3.3 |
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
@ -6986,9 +7030,9 @@ snapshots: |
|||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
[email protected]([email protected]4.0)([email protected](@types/[email protected])): |
[email protected]([email protected]9.1)([email protected](@types/[email protected])): |
||||
dependencies: |
dependencies: |
||||
'@rollup/plugin-inject': 5.0.5([email protected]4.0) |
'@rollup/plugin-inject': 5.0.5([email protected]9.1) |
||||
node-stdlib-browser: 1.2.0 |
node-stdlib-browser: 1.2.0 |
||||
vite: 5.3.6(@types/[email protected]) |
vite: 5.3.6(@types/[email protected]) |
||||
transitivePeerDependencies: |
transitivePeerDependencies: |
||||
@ -6998,7 +7042,7 @@ snapshots: |
|||||
dependencies: |
dependencies: |
||||
esbuild: 0.21.5 |
esbuild: 0.21.5 |
||||
postcss: 8.4.49 |
postcss: 8.4.49 |
||||
rollup: 4.24.0 |
rollup: 4.29.1 |
||||
optionalDependencies: |
optionalDependencies: |
||||
'@types/node': 20.14.9 |
'@types/node': 20.14.9 |
||||
fsevents: 2.3.3 |
fsevents: 2.3.3 |
||||
|
|||||
@ -0,0 +1,134 @@ |
|||||
|
import { useDevice } from "@app/core/stores/deviceStore"; |
||||
|
import { Button } from "@components/UI/Button"; |
||||
|
import { |
||||
|
Dialog, |
||||
|
DialogContent, |
||||
|
DialogDescription, |
||||
|
DialogFooter, |
||||
|
DialogHeader, |
||||
|
DialogTitle, |
||||
|
} from "@components/UI/Dialog.tsx"; |
||||
|
import { fromByteArray } from "base64-js"; |
||||
|
import { DownloadIcon, PrinterIcon } from "lucide-react"; |
||||
|
import React from "react"; |
||||
|
|
||||
|
export interface PkiBackupDialogProps { |
||||
|
open: boolean; |
||||
|
onOpenChange: (open: boolean) => void; |
||||
|
} |
||||
|
|
||||
|
export const PkiBackupDialog = ({ |
||||
|
open, |
||||
|
onOpenChange, |
||||
|
}: PkiBackupDialogProps) => { |
||||
|
const { config, setDialogOpen } = useDevice(); |
||||
|
const privateKey = config.security?.privateKey; |
||||
|
const publicKey = config.security?.publicKey; |
||||
|
|
||||
|
const decodeKeyData = React.useCallback( |
||||
|
(key: Uint8Array<ArrayBufferLike>) => { |
||||
|
if (!key) return ""; |
||||
|
return fromByteArray(key ?? new Uint8Array(0)); |
||||
|
}, |
||||
|
[], |
||||
|
); |
||||
|
|
||||
|
const closeDialog = React.useCallback(() => { |
||||
|
setDialogOpen("pkiBackup", false); |
||||
|
}, [setDialogOpen]); |
||||
|
|
||||
|
const renderPrintWindow = React.useCallback(() => { |
||||
|
if (!privateKey || !publicKey) return; |
||||
|
|
||||
|
const printWindow = window.open("", "_blank"); |
||||
|
if (printWindow) { |
||||
|
printWindow.document.write(` |
||||
|
<html> |
||||
|
<head> |
||||
|
<title>=== MESHTASTIC KEYS ===</title> |
||||
|
<style> |
||||
|
body { font-family: Arial, sans-serif; padding: 20px; } |
||||
|
h1 { font-size: 18px; } |
||||
|
p { font-size: 14px; word-break: break-all; } |
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<h1>=== MESHTASTIC KEYS ===</h1> |
||||
|
<br> |
||||
|
<h2>Public Key:</h2> |
||||
|
<p>${decodeKeyData(publicKey)}</p> |
||||
|
<h2>Private Key:</h2> |
||||
|
<p>${decodeKeyData(privateKey)}</p> |
||||
|
<br> |
||||
|
<p>=== END OF KEYS ===</p> |
||||
|
</body> |
||||
|
</html> |
||||
|
`);
|
||||
|
printWindow.document.close(); |
||||
|
printWindow.print(); |
||||
|
closeDialog(); |
||||
|
} |
||||
|
}, [decodeKeyData, privateKey, publicKey, closeDialog]); |
||||
|
|
||||
|
const createDownloadKeyFile = React.useCallback(() => { |
||||
|
if (!privateKey || !publicKey) return; |
||||
|
|
||||
|
const decodedPrivateKey = decodeKeyData(privateKey); |
||||
|
const decodedPublicKey = decodeKeyData(publicKey); |
||||
|
|
||||
|
const formattedContent = [ |
||||
|
"=== MESHTASTIC KEYS ===\n\n", |
||||
|
"Private Key:\n", |
||||
|
decodedPrivateKey, |
||||
|
"\n\nPublic Key:\n", |
||||
|
decodedPublicKey, |
||||
|
"\n\n=== END OF KEYS ===", |
||||
|
].join(""); |
||||
|
|
||||
|
const blob = new Blob([formattedContent], { type: "text/plain" }); |
||||
|
const url = URL.createObjectURL(blob); |
||||
|
|
||||
|
const link = document.createElement("a"); |
||||
|
link.href = url; |
||||
|
link.download = "meshtastic_keys.txt"; |
||||
|
link.style.display = "none"; |
||||
|
document.body.appendChild(link); |
||||
|
link.click(); |
||||
|
document.body.removeChild(link); |
||||
|
closeDialog(); |
||||
|
URL.revokeObjectURL(url); |
||||
|
}, [decodeKeyData, privateKey, publicKey, closeDialog]); |
||||
|
|
||||
|
return ( |
||||
|
<Dialog open={open} onOpenChange={onOpenChange}> |
||||
|
<DialogContent> |
||||
|
<DialogHeader> |
||||
|
<DialogTitle>Backup Keys</DialogTitle> |
||||
|
<DialogDescription> |
||||
|
Its important to backup your public and private keys and store your |
||||
|
backup securely! |
||||
|
</DialogDescription> |
||||
|
<DialogDescription> |
||||
|
<span className="font-bold break-before-auto"> |
||||
|
If you lose your keys, you will need to reset your device. |
||||
|
</span> |
||||
|
</DialogDescription> |
||||
|
</DialogHeader> |
||||
|
<DialogFooter className="mt-6"> |
||||
|
<Button |
||||
|
variant={"default"} |
||||
|
onClick={() => createDownloadKeyFile()} |
||||
|
className="" |
||||
|
> |
||||
|
<DownloadIcon size={20} className="mr-2" /> |
||||
|
Download |
||||
|
</Button> |
||||
|
<Button variant={"default"} onClick={() => renderPrintWindow()}> |
||||
|
<PrinterIcon size={20} className="mr-2" /> |
||||
|
Print |
||||
|
</Button> |
||||
|
</DialogFooter> |
||||
|
</DialogContent> |
||||
|
</Dialog> |
||||
|
); |
||||
|
}; |
||||
@ -0,0 +1,19 @@ |
|||||
|
import { useBackupReminder } from "@app/core/hooks/useKeyBackupReminder"; |
||||
|
import { useDevice } from "@app/core/stores/deviceStore"; |
||||
|
|
||||
|
export const KeyBackupReminder = (): JSX.Element => { |
||||
|
const { setDialogOpen } = useDevice(); |
||||
|
|
||||
|
useBackupReminder({ |
||||
|
reminderInDays: 7, |
||||
|
message: |
||||
|
"We recommend backing up your key data regularly. Would you like to back up now?", |
||||
|
onAccept: () => setDialogOpen("pkiBackup", true), |
||||
|
enabled: true, |
||||
|
cookieOptions: { |
||||
|
secure: true, |
||||
|
sameSite: "strict", |
||||
|
}, |
||||
|
}); |
||||
|
return <></>; |
||||
|
}; |
||||
@ -0,0 +1,52 @@ |
|||||
|
import Cookies, { type CookieAttributes } from "js-cookie"; |
||||
|
import { useCallback, useState } from "react"; |
||||
|
|
||||
|
interface CookieHookResult<T> { |
||||
|
value: T | undefined; |
||||
|
setCookie: (value: T, options?: CookieAttributes) => void; |
||||
|
removeCookie: () => void; |
||||
|
} |
||||
|
|
||||
|
function useCookie<T extends object>( |
||||
|
cookieName: string, |
||||
|
initialValue?: T, |
||||
|
): CookieHookResult<T> { |
||||
|
const [cookieValue, setCookieValue] = useState<T | undefined>(() => { |
||||
|
try { |
||||
|
const cookie = Cookies.get(cookieName); |
||||
|
return cookie ? (JSON.parse(cookie) as T) : initialValue; |
||||
|
} catch (error) { |
||||
|
console.error(`Error parsing cookie ${cookieName}:`, error); |
||||
|
return initialValue; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const setCookie = useCallback( |
||||
|
(value: T, options?: CookieAttributes) => { |
||||
|
try { |
||||
|
Cookies.set(cookieName, JSON.stringify(value), options); |
||||
|
setCookieValue(value); |
||||
|
} catch (error) { |
||||
|
console.error(`Error setting cookie ${cookieName}:`, error); |
||||
|
} |
||||
|
}, |
||||
|
[cookieName], |
||||
|
); |
||||
|
|
||||
|
const removeCookie = useCallback(() => { |
||||
|
try { |
||||
|
Cookies.remove(cookieName); |
||||
|
setCookieValue(undefined); |
||||
|
} catch (error) { |
||||
|
console.error(`Error removing cookie ${cookieName}:`, error); |
||||
|
} |
||||
|
}, [cookieName]); |
||||
|
|
||||
|
return { |
||||
|
value: cookieValue, |
||||
|
setCookie, |
||||
|
removeCookie, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default useCookie; |
||||
@ -0,0 +1,120 @@ |
|||||
|
import { Button } from "@app/components/UI/Button"; |
||||
|
import type { CookieAttributes } from "js-cookie"; |
||||
|
import { useCallback, useEffect, useRef } from "react"; |
||||
|
import useCookie from "./useCookie"; |
||||
|
import { useToast } from "./useToast"; |
||||
|
|
||||
|
interface UseBackupReminderOptions { |
||||
|
reminderInDays?: number; |
||||
|
message: string; |
||||
|
onAccept?: () => void | Promise<void>; |
||||
|
enabled: boolean; |
||||
|
cookieOptions?: CookieAttributes; |
||||
|
} |
||||
|
|
||||
|
interface ReminderState { |
||||
|
suppressed: boolean; |
||||
|
lastShown: string; |
||||
|
} |
||||
|
|
||||
|
const TOAST_APPEAR_DELAY = 10_000 // 10 seconds;
|
||||
|
const TOAST_DURATION = 30_000 // 30 seconds;:
|
||||
|
|
||||
|
// remind user in 1 year to backup keys again, if they accept the reminder;
|
||||
|
const ON_ACCEPT_REMINDER_DAYS = 365 |
||||
|
|
||||
|
function isReminderExpired(lastShown: string): boolean { |
||||
|
const lastShownDate = new Date(lastShown); |
||||
|
const now = new Date(); |
||||
|
const daysSinceLastShown = |
||||
|
(now.getTime() - lastShownDate.getTime()) / (1000 * 60 * 60 * 24); |
||||
|
return daysSinceLastShown >= 7; |
||||
|
} |
||||
|
|
||||
|
export function useBackupReminder({ |
||||
|
reminderInDays = 7, |
||||
|
enabled, |
||||
|
message, |
||||
|
onAccept = () => { }, |
||||
|
cookieOptions, |
||||
|
}: UseBackupReminderOptions) { |
||||
|
const { toast } = useToast(); |
||||
|
const toastShownRef = useRef(false); |
||||
|
const { value: reminderCookie, setCookie } = |
||||
|
useCookie<ReminderState>("key_backup_reminder"); |
||||
|
|
||||
|
const suppressReminder = useCallback( |
||||
|
(days: number) => { |
||||
|
const expiryDate = new Date(); |
||||
|
expiryDate.setDate(expiryDate.getDate() + days); |
||||
|
|
||||
|
setCookie( |
||||
|
{ |
||||
|
suppressed: true, |
||||
|
lastShown: new Date().toISOString(), |
||||
|
}, |
||||
|
{ ...cookieOptions, expires: expiryDate }, |
||||
|
); |
||||
|
}, |
||||
|
[setCookie, cookieOptions], |
||||
|
); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (!enabled || toastShownRef.current) return; |
||||
|
|
||||
|
const shouldShowReminder = |
||||
|
!reminderCookie?.suppressed || |
||||
|
isReminderExpired(reminderCookie.lastShown); |
||||
|
if (!shouldShowReminder) return; |
||||
|
|
||||
|
toastShownRef.current = true; |
||||
|
|
||||
|
const { dismiss } = toast( |
||||
|
{ |
||||
|
title: "Backup Reminder", |
||||
|
duration: TOAST_DURATION, |
||||
|
delay: TOAST_APPEAR_DELAY, |
||||
|
description: message, |
||||
|
action: ( |
||||
|
<div className="flex gap-2"> |
||||
|
<Button |
||||
|
type="button" |
||||
|
variant="default" |
||||
|
onClick={() => { |
||||
|
onAccept(); |
||||
|
dismiss(); |
||||
|
suppressReminder(ON_ACCEPT_REMINDER_DAYS); |
||||
|
}} |
||||
|
> |
||||
|
Back up now |
||||
|
</Button> |
||||
|
<Button |
||||
|
type="button" |
||||
|
variant="outline" |
||||
|
onClick={() => { |
||||
|
dismiss(); |
||||
|
suppressReminder(reminderInDays); |
||||
|
}} |
||||
|
> |
||||
|
Remind me in {reminderInDays} days |
||||
|
</Button> |
||||
|
</div> |
||||
|
), |
||||
|
}, |
||||
|
); |
||||
|
|
||||
|
return () => { |
||||
|
if (!toastShownRef.current) { |
||||
|
dismiss(); |
||||
|
} |
||||
|
}; |
||||
|
}, [ |
||||
|
enabled, |
||||
|
message, |
||||
|
onAccept, |
||||
|
reminderInDays, |
||||
|
suppressReminder, |
||||
|
toast, |
||||
|
reminderCookie, |
||||
|
]); |
||||
|
} |
||||
Loading…
Reference in new issue