From 13c669b4ea83be54f709d66cc364b2598d3dcb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sat, 17 May 2025 05:59:39 +0900 Subject: [PATCH] refactor: batch 1 --- .vscode/extensions.json | 3 +- package.json | 5 +- pnpm-lock.yaml | 535 +++++++++++++++--- src/App.css | 17 + src/components/AddKey.tsx | 52 +- src/components/AppRoot.tsx | 57 +- src/components/Dialog.tsx | 40 ++ src/components/ExtLink.tsx | 15 +- src/components/FileInput.tsx | 33 +- src/components/FilePathBlock.tsx | 7 +- src/components/Footer.tsx | 47 +- src/components/ImportSecretModal.tsx | 59 +- src/components/SDKVersion.tsx | 48 +- src/components/SelectFile.tsx | 23 +- src/features/file-listing/FileListing.tsx | 6 +- src/features/file-listing/FileRow.tsx | 130 ++--- src/features/settings/Settings.tsx | 7 +- .../settings/panels/PanelQMCv2Key.tsx | 140 ++--- .../settings/panels/QMCv2/QMCv2EKeyItem.tsx | 83 ++- src/main.tsx | 1 + src/tabs/MainTab.tsx | 41 +- src/tabs/SettingsTab.tsx | 10 +- vite.config.ts | 2 + 23 files changed, 828 insertions(+), 533 deletions(-) create mode 100644 src/App.css create mode 100644 src/components/Dialog.tsx diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 32beddf..73c80c4 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,8 @@ { "recommendations": [ - "editorconfig.editorconfig", + "bradlc.vscode-tailwindcss", "dbaeumer.vscode-eslint", + "editorconfig.editorconfig", "esbenp.prettier-vscode", "foxundermoon.shell-format" ] diff --git a/package.json b/package.json index aa754bb..7a11b27 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@emotion/styled": "^11.14.0", "@reduxjs/toolkit": "^2.8.2", "@unlock-music/crypto": "0.1.10", + "classnames": "^2.5.1", "framer-motion": "^12.12.1", "nanoid": "^5.1.5", "next-themes": "^0.4.6", @@ -32,8 +33,8 @@ "react-dom": "^19.1.0", "react-dropzone": "^14.3.8", "react-icons": "^5.5.0", - "react-promise-suspense": "^0.3.4", "react-redux": "^9.2.0", + "react-router": "^7.6.0", "react-syntax-highlighter": "^15.6.1", "sass": "^1.89.0", "sql.js": "^1.13.0", @@ -42,6 +43,7 @@ "devDependencies": { "@eslint/js": "^9.26.0", "@rollup/plugin-replace": "^6.0.2", + "@tailwindcss/vite": "^4.1.7", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", @@ -67,6 +69,7 @@ "prettier": "^3.5.3", "rollup": "^4.40.2", "simple-git-hooks": "^2.13.0", + "tailwindcss": "^4.1.7", "terser": "^5.39.2", "typescript": "^5.8.3", "typescript-eslint": "^8.32.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b29ac5..38c01d4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: '@unlock-music/crypto': specifier: 0.1.10 version: 0.1.10 + classnames: + specifier: ^2.5.1 + version: 2.5.1 framer-motion: specifier: ^12.12.1 version: 12.12.1(@emotion/is-prop-valid@1.3.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -65,12 +68,12 @@ importers: react-icons: specifier: ^5.5.0 version: 5.5.0(react@19.1.0) - react-promise-suspense: - specifier: ^0.3.4 - version: 0.3.4 react-redux: specifier: ^9.2.0 version: 9.2.0(@types/react@19.1.4)(react@19.1.0)(redux@5.0.1) + react-router: + specifier: ^7.6.0 + version: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-syntax-highlighter: specifier: ^15.6.1 version: 15.6.1(react@19.1.0) @@ -90,6 +93,9 @@ importers: '@rollup/plugin-replace': specifier: ^6.0.2 version: 6.0.2(rollup@4.40.2) + '@tailwindcss/vite': + specifier: ^4.1.7 + version: 4.1.7(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) '@testing-library/jest-dom': specifier: ^6.6.3 version: 6.6.3 @@ -116,13 +122,13 @@ importers: version: 1.4.9 '@typescript-eslint/eslint-plugin': specifier: ^8.32.1 - version: 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3) + version: 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.32.1 - version: 8.32.1(eslint@9.26.0)(typescript@5.8.3) + version: 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) '@vitejs/plugin-react': specifier: ^4.4.1 - version: 4.4.1(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) + version: 4.4.1(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) '@vitest/coverage-v8': specifier: ^3.1.3 version: 3.1.3(vitest@3.1.3) @@ -134,16 +140,16 @@ importers: version: 5.0.35 eslint: specifier: ^9.26.0 - version: 9.26.0 + version: 9.26.0(jiti@2.4.2) eslint-config-prettier: specifier: ^10.1.5 - version: 10.1.5(eslint@9.26.0) + version: 10.1.5(eslint@9.26.0(jiti@2.4.2)) eslint-plugin-react-hooks: specifier: ^5.2.0 - version: 5.2.0(eslint@9.26.0) + version: 5.2.0(eslint@9.26.0(jiti@2.4.2)) eslint-plugin-react-refresh: specifier: ^0.4.20 - version: 0.4.20(eslint@9.26.0) + version: 0.4.20(eslint@9.26.0(jiti@2.4.2)) globals: specifier: ^16.1.0 version: 16.1.0 @@ -165,6 +171,9 @@ importers: simple-git-hooks: specifier: ^2.13.0 version: 2.13.0 + tailwindcss: + specifier: ^4.1.7 + version: 4.1.7 terser: specifier: ^5.39.2 version: 5.39.2 @@ -173,22 +182,22 @@ importers: version: 5.8.3 typescript-eslint: specifier: ^8.32.1 - version: 8.32.1(eslint@9.26.0)(typescript@5.8.3) + version: 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) vite: specifier: ^6.3.5 - version: 6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + version: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) vite-plugin-pwa: specifier: ^1.0.0 - version: 1.0.0(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0) + version: 1.0.0(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0) vite-plugin-top-level-await: specifier: ^1.5.0 - version: 1.5.0(@swc/helpers@0.5.17)(rollup@4.40.2)(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) + version: 1.5.0(@swc/helpers@0.5.17)(rollup@4.40.2)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) vite-plugin-wasm: specifier: ^3.4.1 - version: 3.4.1(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) + version: 3.4.1(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) vitest: specifier: ^3.1.3 - version: 3.1.3(@types/node@22.15.18)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.18)(@vitest/ui@3.1.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) workbox-window: specifier: ^7.3.0 version: 7.3.0 @@ -1050,6 +1059,10 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + '@istanbuljs/schema@0.1.3': resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} @@ -1451,6 +1464,96 @@ packages: '@swc/types@0.1.21': resolution: {integrity: sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==} + '@tailwindcss/node@4.1.7': + resolution: {integrity: sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==} + + '@tailwindcss/oxide-android-arm64@4.1.7': + resolution: {integrity: sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.7': + resolution: {integrity: sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.7': + resolution: {integrity: sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.7': + resolution: {integrity: sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.7': + resolution: {integrity: sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.7': + resolution: {integrity: sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.7': + resolution: {integrity: sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.7': + resolution: {integrity: sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.7': + resolution: {integrity: sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.7': + resolution: {integrity: sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.7': + resolution: {integrity: sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.7': + resolution: {integrity: sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.7': + resolution: {integrity: sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==} + engines: {node: '>= 10'} + + '@tailwindcss/vite@4.1.7': + resolution: {integrity: sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==} + peerDependencies: + vite: ^5.2.0 || ^6 + '@testing-library/dom@10.4.0': resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} @@ -1853,6 +1956,13 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -1913,6 +2023,10 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} @@ -2008,6 +2122,10 @@ packages: engines: {node: '>=0.10'} hasBin: true + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + engines: {node: '>=8'} + detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} @@ -2048,6 +2166,10 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + entities@6.0.0: resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} engines: {node: '>=0.12'} @@ -2199,9 +2321,6 @@ packages: resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} engines: {node: '>= 18'} - fast-deep-equal@2.0.1: - resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2688,6 +2807,10 @@ packages: engines: {node: '>=10'} hasBin: true + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2755,6 +2878,70 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lightningcss-darwin-arm64@1.30.1: + resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.1: + resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.1: + resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.1: + resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.1: + resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.1: + resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.1: + resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.1: + resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.1: + resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.1: + resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.1: + resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} + engines: {node: '>= 12.0.0'} + lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} @@ -2878,6 +3065,15 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + minizlib@3.0.2: + resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==} + engines: {node: '>= 18'} + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + motion-dom@12.12.1: resolution: {integrity: sha512-GXq/uUbZBEiFFE+K1Z/sxdPdadMdfJ/jmBALDfIuHGi0NmtealLOfH9FqT+6aNPgVx8ilq0DtYmyQlo6Uj9LKQ==} @@ -3157,9 +3353,6 @@ packages: react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - react-promise-suspense@0.3.4: - resolution: {integrity: sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==} - react-redux@9.2.0: resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==} peerDependencies: @@ -3196,6 +3389,16 @@ packages: '@types/react': optional: true + react-router@7.6.0: + resolution: {integrity: sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + react-style-singleton@2.2.3: resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} @@ -3357,6 +3560,9 @@ packages: resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} engines: {node: '>= 18'} + set-cookie-parser@2.7.1: + resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -3527,6 +3733,17 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tailwindcss@4.1.7: + resolution: {integrity: sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} + temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} @@ -3973,6 +4190,10 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} @@ -4913,9 +5134,9 @@ snapshots: '@esbuild/win32-x64@0.25.4': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.26.0)': + '@eslint-community/eslint-utils@4.7.0(eslint@9.26.0(jiti@2.4.2))': dependencies: - eslint: 9.26.0 + eslint: 9.26.0(jiti@2.4.2) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -4979,6 +5200,10 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + '@istanbuljs/schema@0.1.3': {} '@jridgewell/gen-mapping@0.3.8': @@ -5310,6 +5535,77 @@ snapshots: dependencies: '@swc/counter': 0.1.3 + '@tailwindcss/node@4.1.7': + dependencies: + '@ampproject/remapping': 2.3.0 + enhanced-resolve: 5.18.1 + jiti: 2.4.2 + lightningcss: 1.30.1 + magic-string: 0.30.17 + source-map-js: 1.2.1 + tailwindcss: 4.1.7 + + '@tailwindcss/oxide-android-arm64@4.1.7': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.7': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.7': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.7': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.7': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.7': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.7': + optional: true + + '@tailwindcss/oxide@4.1.7': + dependencies: + detect-libc: 2.0.4 + tar: 7.4.3 + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.7 + '@tailwindcss/oxide-darwin-arm64': 4.1.7 + '@tailwindcss/oxide-darwin-x64': 4.1.7 + '@tailwindcss/oxide-freebsd-x64': 4.1.7 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.7 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.7 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.7 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.7 + '@tailwindcss/oxide-linux-x64-musl': 4.1.7 + '@tailwindcss/oxide-wasm32-wasi': 4.1.7 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.7 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.7 + + '@tailwindcss/vite@4.1.7(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))': + dependencies: + '@tailwindcss/node': 4.1.7 + '@tailwindcss/oxide': 4.1.7 + tailwindcss: 4.1.7 + vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + '@testing-library/dom@10.4.0': dependencies: '@babel/code-frame': 7.27.1 @@ -5417,15 +5713,15 @@ snapshots: '@types/use-sync-external-store@0.0.6': {} - '@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.32.1(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/scope-manager': 8.32.1 - '@typescript-eslint/type-utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - '@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/type-utils': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.32.1 - eslint: 9.26.0 + eslint: 9.26.0(jiti@2.4.2) graphemer: 1.4.0 ignore: 7.0.4 natural-compare: 1.4.0 @@ -5434,14 +5730,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3)': + '@typescript-eslint/parser@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@typescript-eslint/scope-manager': 8.32.1 '@typescript-eslint/types': 8.32.1 '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.32.1 debug: 4.4.1 - eslint: 9.26.0 + eslint: 9.26.0(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -5451,12 +5747,12 @@ snapshots: '@typescript-eslint/types': 8.32.1 '@typescript-eslint/visitor-keys': 8.32.1 - '@typescript-eslint/type-utils@8.32.1(eslint@9.26.0)(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) debug: 4.4.1 - eslint: 9.26.0 + eslint: 9.26.0(jiti@2.4.2) ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: @@ -5478,13 +5774,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.32.1(eslint@9.26.0)(typescript@5.8.3)': + '@typescript-eslint/utils@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2)) '@typescript-eslint/scope-manager': 8.32.1 '@typescript-eslint/types': 8.32.1 '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) - eslint: 9.26.0 + eslint: 9.26.0(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -5496,14 +5792,14 @@ snapshots: '@unlock-music/crypto@0.1.10': {} - '@vitejs/plugin-react@4.4.1(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))': + '@vitejs/plugin-react@4.4.1(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))': dependencies: '@babel/core': 7.27.1 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.1) '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.1) '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) transitivePeerDependencies: - supports-color @@ -5521,7 +5817,7 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.3(@types/node@22.15.18)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vitest: 3.1.3(@types/node@22.15.18)(@vitest/ui@3.1.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) transitivePeerDependencies: - supports-color @@ -5532,13 +5828,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.3(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))': + '@vitest/mocker@3.1.3(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.1.3 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) '@vitest/pretty-format@3.1.3': dependencies: @@ -5568,7 +5864,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.13 tinyrainbow: 2.0.0 - vitest: 3.1.3(@types/node@22.15.18)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vitest: 3.1.3(@types/node@22.15.18)(@vitest/ui@3.1.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) '@vitest/utils@3.1.3': dependencies: @@ -5793,6 +6089,10 @@ snapshots: dependencies: readdirp: 4.1.2 + chownr@3.0.0: {} + + classnames@2.5.1: {} + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -5836,6 +6136,8 @@ snapshots: cookie@0.7.2: {} + cookie@1.0.2: {} + copy-to-clipboard@3.3.3: dependencies: toggle-selection: 1.0.6 @@ -5930,6 +6232,8 @@ snapshots: detect-libc@1.0.3: optional: true + detect-libc@2.0.4: {} + detect-node-es@1.1.0: {} dom-accessibility-api@0.5.16: {} @@ -5960,6 +6264,11 @@ snapshots: encodeurl@2.0.0: {} + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + entities@6.0.0: {} environment@1.1.0: {} @@ -6079,17 +6388,17 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.5(eslint@9.26.0): + eslint-config-prettier@10.1.5(eslint@9.26.0(jiti@2.4.2)): dependencies: - eslint: 9.26.0 + eslint: 9.26.0(jiti@2.4.2) - eslint-plugin-react-hooks@5.2.0(eslint@9.26.0): + eslint-plugin-react-hooks@5.2.0(eslint@9.26.0(jiti@2.4.2)): dependencies: - eslint: 9.26.0 + eslint: 9.26.0(jiti@2.4.2) - eslint-plugin-react-refresh@0.4.20(eslint@9.26.0): + eslint-plugin-react-refresh@0.4.20(eslint@9.26.0(jiti@2.4.2)): dependencies: - eslint: 9.26.0 + eslint: 9.26.0(jiti@2.4.2) eslint-scope@8.3.0: dependencies: @@ -6100,9 +6409,9 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.26.0: + eslint@9.26.0(jiti@2.4.2): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.20.0 '@eslint/config-helpers': 0.2.2 @@ -6139,6 +6448,8 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 zod: 3.24.4 + optionalDependencies: + jiti: 2.4.2 transitivePeerDependencies: - supports-color @@ -6216,8 +6527,6 @@ snapshots: transitivePeerDependencies: - supports-color - fast-deep-equal@2.0.1: {} - fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -6706,6 +7015,8 @@ snapshots: filelist: 1.0.4 minimatch: 3.1.2 + jiti@2.4.2: {} + js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -6776,6 +7087,51 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lightningcss-darwin-arm64@1.30.1: + optional: true + + lightningcss-darwin-x64@1.30.1: + optional: true + + lightningcss-freebsd-x64@1.30.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.1: + optional: true + + lightningcss-linux-arm64-gnu@1.30.1: + optional: true + + lightningcss-linux-arm64-musl@1.30.1: + optional: true + + lightningcss-linux-x64-gnu@1.30.1: + optional: true + + lightningcss-linux-x64-musl@1.30.1: + optional: true + + lightningcss-win32-arm64-msvc@1.30.1: + optional: true + + lightningcss-win32-x64-msvc@1.30.1: + optional: true + + lightningcss@1.30.1: + dependencies: + detect-libc: 2.0.4 + optionalDependencies: + lightningcss-darwin-arm64: 1.30.1 + lightningcss-darwin-x64: 1.30.1 + lightningcss-freebsd-x64: 1.30.1 + lightningcss-linux-arm-gnueabihf: 1.30.1 + lightningcss-linux-arm64-gnu: 1.30.1 + lightningcss-linux-arm64-musl: 1.30.1 + lightningcss-linux-x64-gnu: 1.30.1 + lightningcss-linux-x64-musl: 1.30.1 + lightningcss-win32-arm64-msvc: 1.30.1 + lightningcss-win32-x64-msvc: 1.30.1 + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -6900,6 +7256,12 @@ snapshots: minipass@7.1.2: {} + minizlib@3.0.2: + dependencies: + minipass: 7.1.2 + + mkdirp@3.0.1: {} + motion-dom@12.12.1: dependencies: motion-utils: 12.12.1 @@ -7144,10 +7506,6 @@ snapshots: react-is@17.0.2: {} - react-promise-suspense@0.3.4: - dependencies: - fast-deep-equal: 2.0.1 - react-redux@9.2.0(@types/react@19.1.4)(react@19.1.0)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 @@ -7178,6 +7536,14 @@ snapshots: optionalDependencies: '@types/react': 19.1.4 + react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + cookie: 1.0.2 + react: 19.1.0 + set-cookie-parser: 2.7.1 + optionalDependencies: + react-dom: 19.1.0(react@19.1.0) + react-style-singleton@2.2.3(@types/react@19.1.4)(react@19.1.0): dependencies: get-nonce: 1.0.1 @@ -7395,6 +7761,8 @@ snapshots: transitivePeerDependencies: - supports-color + set-cookie-parser@2.7.1: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -7593,6 +7961,19 @@ snapshots: symbol-tree@3.2.4: {} + tailwindcss@4.1.7: {} + + tapable@2.2.1: {} + + tar@7.4.3: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.2 + mkdirp: 3.0.1 + yallist: 5.0.0 + temp-dir@2.0.0: {} tempy@0.6.0: @@ -7711,12 +8092,12 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.32.1(eslint@9.26.0)(typescript@5.8.3): + typescript-eslint@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3) - '@typescript-eslint/parser': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - '@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - eslint: 9.26.0 + '@typescript-eslint/eslint-plugin': 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/parser': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + eslint: 9.26.0(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -7786,13 +8167,13 @@ snapshots: vary@1.1.2: {} - vite-node@3.1.3(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0): + vite-node@3.1.3(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -7807,32 +8188,32 @@ snapshots: - tsx - yaml - vite-plugin-pwa@1.0.0(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0): + vite-plugin-pwa@1.0.0(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0): dependencies: debug: 4.4.1 pretty-bytes: 6.1.1 tinyglobby: 0.2.13 - vite: 6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) workbox-build: 7.3.0(@types/babel__core@7.20.5) workbox-window: 7.3.0 transitivePeerDependencies: - supports-color - vite-plugin-top-level-await@1.5.0(@swc/helpers@0.5.17)(rollup@4.40.2)(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)): + vite-plugin-top-level-await@1.5.0(@swc/helpers@0.5.17)(rollup@4.40.2)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)): dependencies: '@rollup/plugin-virtual': 3.0.2(rollup@4.40.2) '@swc/core': 1.11.24(@swc/helpers@0.5.17) uuid: 10.0.0 - vite: 6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) transitivePeerDependencies: - '@swc/helpers' - rollup - vite-plugin-wasm@3.4.1(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)): + vite-plugin-wasm@3.4.1(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)): dependencies: - vite: 6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) - vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0): + vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0): dependencies: esbuild: 0.25.4 fdir: 6.4.4(picomatch@4.0.2) @@ -7843,14 +8224,16 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 fsevents: 2.3.3 + jiti: 2.4.2 + lightningcss: 1.30.1 sass: 1.89.0 terser: 5.39.2 yaml: 2.8.0 - vitest@3.1.3(@types/node@22.15.18)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0): + vitest@3.1.3(@types/node@22.15.18)(@vitest/ui@3.1.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0): dependencies: '@vitest/expect': 3.1.3 - '@vitest/mocker': 3.1.3(vite@6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) + '@vitest/mocker': 3.1.3(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0)) '@vitest/pretty-format': 3.1.3 '@vitest/runner': 3.1.3 '@vitest/snapshot': 3.1.3 @@ -7867,8 +8250,8 @@ snapshots: tinyglobby: 0.2.13 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) - vite-node: 3.1.3(@types/node@22.15.18)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) + vite-node: 3.1.3(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(terser@5.39.2)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.15.18 @@ -8108,6 +8491,8 @@ snapshots: yallist@3.1.1: {} + yallist@5.0.0: {} + yaml@1.10.2: {} yaml@2.8.0: {} diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..0199195 --- /dev/null +++ b/src/App.css @@ -0,0 +1,17 @@ +@import 'tailwindcss'; +@plugin "daisyui"; +@theme { + --font-display: + system-ui, Sarasa UI SC, Source Han Sans CN, Noto Sans CJK SC, sans-serif, Apple Color Emoji, Segoe UI Emoji; + --font-mono: + ui-monospace, Consolas, Sarasa Mono CJK SC, Sarasa UI SC, Source Han Sans CN, Noto Sans CJK SC, Microsoft YaHei UI, + monospace, Apple Color Emoji, Segoe UI Emoji; +} + +#root { + display: flex; + flex-direction: column; + height: 100vh; + display: flex; + flex-direction: column; +} diff --git a/src/components/AddKey.tsx b/src/components/AddKey.tsx index 0088f77..8f504d3 100644 --- a/src/components/AddKey.tsx +++ b/src/components/AddKey.tsx @@ -1,16 +1,4 @@ -import { - Button, - ButtonGroup, - HStack, - Icon, - IconButton, - Menu, - MenuButton, - MenuDivider, - MenuItem, - MenuList, -} from '@chakra-ui/react'; -import { MdAdd, MdDeleteForever, MdExpandMore, MdFileUpload } from 'react-icons/md'; +import { MdAdd, MdDeleteForever, MdFileUpload } from 'react-icons/md'; export interface AddKeyProps { addKey: () => void; @@ -20,28 +8,20 @@ export interface AddKeyProps { export function AddKey({ addKey, importKeyFromFile, clearKeys }: AddKeyProps) { return ( - - - - - }> - - {importKeyFromFile && ( - }> - 从文件导入密钥… - - )} - {importKeyFromFile && clearKeys && } - {clearKeys && ( - }> - 清空密钥 - - )} - - - - +
+
+ + + +
+
); } diff --git a/src/components/AppRoot.tsx b/src/components/AppRoot.tsx index 7a9de6b..2b571e1 100644 --- a/src/components/AppRoot.tsx +++ b/src/components/AppRoot.tsx @@ -1,12 +1,11 @@ import { useEffect } from 'react'; +import { BrowserRouter, NavLink, Route, Routes } from 'react-router'; import { MdSettings, MdHome, MdQuestionAnswer } from 'react-icons/md'; -import { ChakraProvider, Tabs, TabList, TabPanels, Tab, TabPanel, Icon, chakra } from '@chakra-ui/react'; import { MainTab } from '~/tabs/MainTab'; import { SettingsTab } from '~/tabs/SettingsTab'; import { Provider } from 'react-redux'; -import { theme } from '~/theme'; import { persistSettings } from '~/features/settings/persistSettings'; import { setupStore } from '~/store'; import { Footer } from '~/components/Footer'; @@ -15,43 +14,39 @@ import { FaqTab } from '~/tabs/FaqTab'; // Private to this file only. const store = setupStore(); +const tabClassNames = ({ isActive }: { isActive: boolean }) => `tab ${isActive ? 'tab-active' : ''}`; + export function AppRoot() { useEffect(() => persistSettings(store), []); return ( - + - - - - - 应用 - - - - 设置 - - - - 答疑 - - +
+ + + 应用 + + + + 设置 + + + + 答疑 + +
- - - - - - - - - - - -
+
+ + + + + +
- + ); } diff --git a/src/components/Dialog.tsx b/src/components/Dialog.tsx new file mode 100644 index 0000000..4bc1e25 --- /dev/null +++ b/src/components/Dialog.tsx @@ -0,0 +1,40 @@ +import { useEffect, useRef } from 'react'; + +export interface DialogProps { + closeButton?: boolean; + backdropClose?: boolean; + title?: React.ReactNode; + children: React.ReactNode; + show: boolean; + onClose: () => void; +} + +export function Dialog({ closeButton, backdropClose, title, children, show, onClose }: DialogProps) { + const refModel = useRef(null); + useEffect(() => { + if (show) { + refModel.current?.showModal(); + } else { + refModel.current?.close(); + } + }, [show]); + + return ( + +
+ {closeButton && ( +
+ +
+ )} +

{title}

+ {children} +
+ {backdropClose && ( +
+ +
+ )} +
+ ); +} diff --git a/src/components/ExtLink.tsx b/src/components/ExtLink.tsx index 88cf76d..edd9da1 100644 --- a/src/components/ExtLink.tsx +++ b/src/components/ExtLink.tsx @@ -1,12 +1,15 @@ import type { AnchorHTMLAttributes } from 'react'; -import { ExternalLinkIcon } from '@chakra-ui/icons'; -import { Link } from '@chakra-ui/react'; +import { FiExternalLink } from 'react-icons/fi'; -export function ExtLink({ children, ...props }: AnchorHTMLAttributes) { +export type ExtLinkProps = AnchorHTMLAttributes & { + icon?: boolean; +}; + +export function ExtLink({ className, icon = true, children, ...props }: ExtLinkProps) { return ( - + {children} - - + {icon && } + ); } diff --git a/src/components/FileInput.tsx b/src/components/FileInput.tsx index 8891d54..e80038c 100644 --- a/src/components/FileInput.tsx +++ b/src/components/FileInput.tsx @@ -1,5 +1,5 @@ +import classnames from 'classnames'; import { useDropzone } from 'react-dropzone'; -import { Box } from '@chakra-ui/react'; export interface FileInputProps { onReceiveFiles: (files: File[]) => void; @@ -14,30 +14,19 @@ export function FileInput({ children, onReceiveFiles }: FileInputProps) { }); return ( - - {children} - + ); } diff --git a/src/components/FilePathBlock.tsx b/src/components/FilePathBlock.tsx index 83339c2..753ff98 100644 --- a/src/components/FilePathBlock.tsx +++ b/src/components/FilePathBlock.tsx @@ -1,10 +1,9 @@ -import { Code, Text } from '@chakra-ui/react'; import React from 'react'; export function FilePathBlock({ children }: { children: React.ReactNode }) { return ( - - {children} - +
+      {children}
+    
); } diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index c551375..ec1126c 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,45 +1,28 @@ -import { Center, Flex, Link, Text } from '@chakra-ui/react'; -import { Suspense } from 'react'; import { SDKVersion } from './SDKVersion'; import { CurrentYear } from './CurrentYear'; export function Footer() { + const appVersionShort = '__APP_VERSION_SHORT__'; return ( -
- - +
+ +

+
); } diff --git a/src/components/ImportSecretModal.tsx b/src/components/ImportSecretModal.tsx index d79932b..1af16a3 100644 --- a/src/components/ImportSecretModal.tsx +++ b/src/components/ImportSecretModal.tsx @@ -1,15 +1,4 @@ -import { - Center, - Flex, - Modal, - ModalBody, - ModalCloseButton, - ModalContent, - ModalHeader, - ModalOverlay, - Tabs, - Text, -} from '@chakra-ui/react'; +import { useEffect, useRef } from 'react'; import { FileInput } from '~/components/FileInput'; @@ -18,39 +7,43 @@ export interface ImportSecretModalProps { children: React.ReactNode; show: boolean; onClose: () => void; - onImport: (file: File) => void|Promise; + onImport: (file: File) => void | Promise; } export function ImportSecretModal({ clientName, children, show, onClose, onImport }: ImportSecretModalProps) { const handleFileReceived = (files: File[]) => { const promise = onImport(files[0]); if (promise instanceof Promise) { - promise.catch(err => { + promise.catch((err) => { console.error('could not import: ', err); }); } return promise; }; - return ( - - - - 从文件导入密钥 - - -
- 拖放或点我选择含有密钥的数据库文件 -
+ const refModel = useRef(null); + useEffect(() => { + if (show) { + refModel.current?.showModal(); + } else { + refModel.current?.close(); + } + }, [show]); - - 选择你的{clientName && <>「{clientName}」}客户端平台以查看对应说明: - - - {children} - -
-
-
+ return ( + +
+
onClose()}> + +
+

从文件导入密钥

+
+ 拖放或点我选择含有密钥的数据库文件 + +
选择你的{clientName && <>「{clientName}」}客户端平台以查看对应说明:
+
{children}
+
+
+
); } diff --git a/src/components/SDKVersion.tsx b/src/components/SDKVersion.tsx index 5ee234b..dcc2b69 100644 --- a/src/components/SDKVersion.tsx +++ b/src/components/SDKVersion.tsx @@ -1,33 +1,39 @@ -import { InfoOutlineIcon } from '@chakra-ui/icons'; -import { Tooltip, VStack, Text, Flex } from '@chakra-ui/react'; +import { MdInfoOutline } from 'react-icons/md'; import { workerClientBus } from '~/decrypt-worker/client'; import { DECRYPTION_WORKER_ACTION_NAME } from '~/decrypt-worker/constants'; - -import usePromise from 'react-promise-suspense'; +import { useEffect, useRef, useState } from 'react'; const getSDKVersion = async (): Promise => { return workerClientBus.request(DECRYPTION_WORKER_ACTION_NAME.VERSION, null); }; export function SDKVersion() { - const sdkVersion = usePromise(getSDKVersion, []); + const refDialog = useRef(null); + const [sdkVersion, setSdkVersion] = useState('...'); + useEffect(() => { + getSDKVersion().then(setSdkVersion); + }, []); return ( - - - App: __APP_VERSION__ - SDK: {sdkVersion} - - } - bg="gray.300" - color="black" - > - - - + <> + refDialog.current?.showModal()}> + + + + +
+
+ +
+

详细信息

+ +

App: __APP_VERSION__

+

SDK: {sdkVersion}

+
+
+ +
+
+ ); } diff --git a/src/components/SelectFile.tsx b/src/components/SelectFile.tsx index 971f395..0e5e87c 100644 --- a/src/components/SelectFile.tsx +++ b/src/components/SelectFile.tsx @@ -1,5 +1,4 @@ -import { Box, Text } from '@chakra-ui/react'; -import { UnlockIcon } from '@chakra-ui/icons'; +import { FiUnlock } from 'react-icons/fi'; import { useAppDispatch } from '~/hooks'; import { addNewFile, processFile } from '~/features/file-listing/fileListingSlice'; @@ -12,7 +11,7 @@ export function SelectFile() { console.debug( 'react-dropzone/onDropAccepted(%o, %o)', files.length, - files.map((x) => x.name) + files.map((x) => x.name), ); for (const file of files) { @@ -26,7 +25,7 @@ export function SelectFile() { id: fileId, blobURI, fileName, - }) + }), ); dispatch(processFile({ fileId })); } @@ -34,19 +33,13 @@ export function SelectFile() { return ( - - - - + +

拖放或 - - 点我选择 - + 点我选择 需要解密的文件 - - 在浏览器内对文件进行解锁,零上传 - - +

+

在浏览器内对文件进行解锁,零上传

); } diff --git a/src/features/file-listing/FileListing.tsx b/src/features/file-listing/FileListing.tsx index 09bec14..88ffa7d 100644 --- a/src/features/file-listing/FileListing.tsx +++ b/src/features/file-listing/FileListing.tsx @@ -1,5 +1,3 @@ -import { VStack } from '@chakra-ui/react'; - import { selectFiles } from './fileListingSlice'; import { useAppSelector } from '~/hooks'; import { FileRow } from './FileRow'; @@ -8,10 +6,10 @@ export function FileListing() { const files = useAppSelector(selectFiles); return ( - +
{Object.entries(files).map(([id, file]) => ( ))} - +
); } diff --git a/src/features/file-listing/FileRow.tsx b/src/features/file-listing/FileRow.tsx index 294144f..e5dd489 100644 --- a/src/features/file-listing/FileRow.tsx +++ b/src/features/file-listing/FileRow.tsx @@ -1,24 +1,9 @@ import { useRef } from 'react'; -import { - Box, - Button, - Card, - CardBody, - Collapse, - GridItem, - Link, - VStack, - Wrap, - WrapItem, - useDisclosure, -} from '@chakra-ui/react'; -import { FileRowResponsiveGrid } from './FileRowResponsiveGrid'; import { DecryptedAudioFile, deleteFile, ProcessState } from './fileListingSlice'; import { useAppDispatch } from '~/hooks'; import { AnimationDefinition } from 'framer-motion'; -import { AlbumImage } from './AlbumImage'; -import { SongMetadata } from './SongMetadata'; import { FileError } from './FileError'; +import classNames from 'classnames'; interface FileRowProps { id: string; @@ -26,7 +11,7 @@ interface FileRowProps { } export function FileRow({ id, file }: FileRowProps) { - const { isOpen, onClose } = useDisclosure({ defaultIsOpen: true }); + // const { isOpen, onClose } = useDisclosure({ defaultIsOpen: true }); const dispatch = useAppDispatch(); const isDecrypted = file.state === ProcessState.COMPLETE; const metadata = file.metadata; @@ -35,81 +20,54 @@ export function FileRow({ id, file }: FileRowProps) { const decryptedName = nameWithoutExt + '.' + file.ext; const audioPlayerRef = useRef(null); - const togglePlay = () => { - const player = audioPlayerRef.current; - if (!player) { - return; - } - - if (player.paused) { - player.play(); - } else { - player.pause(); - } - }; - - const onCollapseAnimationComplete = (definition: AnimationDefinition) => { + const _onCollapseAnimationComplete = (definition: AnimationDefinition) => { if (definition === 'exit') { dispatch(deleteFile({ id })); } }; return ( - - - - - - - - - - {metadata?.name ?? nameWithoutExt} - - - - {isDecrypted && metadata && } - {file.state === ProcessState.ERROR && } - - - - {file.decrypted &&