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 (
-
-
- }>
- 添加一条密钥
-
-
-
-
+
+
+
+
+
+
+
);
}
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 (
+
+ {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 (
-
-
-
+
-
+
+ (v{appVersionShort}
+ ) - 移除已购音乐的加密保护。
+
+
{'© 2019 - '}
{' '}
-
+
UnlockMusic 团队
-
+
{' | '}
-
+
使用 MIT 授权协议
-
-
-
+
+
+
);
}
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 (
+
);
}
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()}>
+
+
+
+
+ >
);
}
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 && }
+
+
+
+ {metadata?.name ?? nameWithoutExt}
+
-
- {isDecrypted && (
- <>
-
-
-
-
- {file.decrypted && (
-
-
-
- )}
-
- >
- )}
-
-
-
-
-
-
-
-
-
-
+
+ {file.state === ProcessState.ERROR &&
}
+ {isDecrypted && (
+
+ )}
+
+
+
+
+ 下载
+
+
+
+
+
);
}
diff --git a/src/features/settings/Settings.tsx b/src/features/settings/Settings.tsx
index b4de13b..b30c254 100644
--- a/src/features/settings/Settings.tsx
+++ b/src/features/settings/Settings.tsx
@@ -19,7 +19,6 @@ import {
TabPanels,
Tabs,
Text,
- useBreakpointValue,
useToast,
VStack,
} from '@chakra-ui/react';
@@ -47,11 +46,7 @@ const TABS: { name: string; Tab: FC }[] = [
export function Settings() {
const toast = useToast();
const dispatch = useAppDispatch();
- const isLargeWidthDevice =
- useBreakpointValue({
- base: false,
- lg: true,
- }) ?? false;
+ const isLargeWidthDevice = false;
const [tabIndex, setTabIndex] = useState(0);
const handleTabChange = (idx: number) => {
diff --git a/src/features/settings/panels/PanelQMCv2Key.tsx b/src/features/settings/panels/PanelQMCv2Key.tsx
index 9291a53..2e6c3ad 100644
--- a/src/features/settings/panels/PanelQMCv2Key.tsx
+++ b/src/features/settings/panels/PanelQMCv2Key.tsx
@@ -1,31 +1,9 @@
-import {
- Box,
- Button,
- ButtonGroup,
- Checkbox,
- Flex,
- Heading,
- HStack,
- Icon,
- IconButton,
- List,
- Menu,
- MenuButton,
- MenuDivider,
- MenuItem,
- MenuList,
- Select,
- Text,
- Tooltip,
- useToast,
-} from '@chakra-ui/react';
+import { Select, useToast } from '@chakra-ui/react';
import { useDispatch, useSelector } from 'react-redux';
import { qmc2AddKey, qmc2AllowFuzzyNameSearch, qmc2ClearKeys, qmc2ImportKeys } from '../settingsSlice';
import { selectStagingQMCv2Settings } from '../settingsSelector';
import React, { useState } from 'react';
-import { MdAdd, MdDeleteForever, MdExpandMore, MdFileUpload } from 'react-icons/md';
import { QMCv2EKeyItem } from './QMCv2/QMCv2EKeyItem';
-import { InfoOutlineIcon } from '@chakra-ui/icons';
import { ImportSecretModal } from '~/components/ImportSecretModal';
import { StagingQMCv2Key } from '../keyFormats';
import { DatabaseKeyExtractor } from '~/util/DatabaseKeyExtractor';
@@ -33,8 +11,11 @@ import { parseAndroidQmEKey } from '~/util/mmkv/qm';
import { getFileName } from '~/util/pathHelper';
import { QMCv2QQMusicAllInstructions } from './QMCv2/QMCv2QQMusicAllInstructions';
import { QMCv2DoubanAllInstructions } from './QMCv2/QMCv2DoubanAllInstructions';
+import { AddKey } from '~/components/AddKey';
+import { Dialog } from '~/components/Dialog';
export function PanelQMCv2Key() {
+ const [showFuzzyNameSearchInfo, setShowFuzzyNameSearchInfo] = useState(false);
const toast = useToast();
const dispatch = useDispatch();
const { keys: qmc2Keys, allowFuzzyNameSearch } = useSelector(selectStagingQMCv2Settings);
@@ -93,73 +74,64 @@ export function PanelQMCv2Key() {
};
return (
-
-
- QMCv2 解密密钥
-
+
+
QMCv2 解密密钥
-
- QQ 音乐、豆瓣 FM 目前采用的加密方案(QMCv2)。在使用「QQ 音乐」安卓、Mac 或 iOS 客户端,以及在使用「豆瓣
- FM」安卓客户端的情况下,其「离线加密文件」对应的「密钥」储存在独立的数据库文件内。
-
+
+ QQ 音乐、豆瓣 FM 目前采用的加密方案(QMCv2)。
+
+ 在使用「QQ 音乐」安卓、Mac 或 iOS 客户端,以及在使用「豆瓣 FM」安卓客户端的情况下,
+ 其「离线加密文件」对应的「密钥」储存在独立的数据库文件内。
+
+
-
-
- }>
- 添加一条密钥
-
-
-
+
+
+
+
+
-
-
- 匹配相似文件名
-
-
- 若文件名匹配失败,则使用相似文件名的密钥。
-
- 使用「
-
- 莱文斯坦距离
-
-
-
-
- 」算法计算相似程度。
-
- 若密钥数量过多,匹配时可能会造成浏览器卡顿或无响应一段时间。
- 若不确定,请勾选该项。
-
- }
- >
-
-
-
-
+
密钥管理
+
setShowImportModal(true)} clearKeys={clearAll} />
-
-
+
+
{qmc2Keys.map(({ id, ekey, name }, i) => (
))}
-
- {qmc2Keys.length === 0 && 还没有密钥。}
-
+
+ {qmc2Keys.length === 0 &&
还没有密钥。
}
+
}
{secretType === 'douban' && }
-
+
);
}
diff --git a/src/features/settings/panels/QMCv2/QMCv2EKeyItem.tsx b/src/features/settings/panels/QMCv2/QMCv2EKeyItem.tsx
index 305e4de..a5a742e 100644
--- a/src/features/settings/panels/QMCv2/QMCv2EKeyItem.tsx
+++ b/src/features/settings/panels/QMCv2/QMCv2EKeyItem.tsx
@@ -1,15 +1,3 @@
-import {
- HStack,
- Icon,
- IconButton,
- Input,
- InputGroup,
- InputLeftElement,
- InputRightElement,
- ListItem,
- Text,
- VStack,
-} from '@chakra-ui/react';
import { MdDelete, MdVpnKey } from 'react-icons/md';
import { qmc2DeleteKey, qmc2UpdateKey } from '../../settingsSlice';
import { useAppDispatch } from '~/hooks';
@@ -22,48 +10,45 @@ export const QMCv2EKeyItem = memo(({ id, name, ekey, i }: { id: string; name: st
dispatch(qmc2UpdateKey({ id, field: prop, value: e.target.value }));
const deleteKey = () => dispatch(qmc2DeleteKey({ id }));
- return (
-
-
-
- {i + 1}
-
+ const isValidEKey = [364, 704].includes(ekey.length);
-
-
+
+ {i + 1}
+
+
+
+
+
+
-
-
-
-
- updateKey('ekey', e)}
- />
-
-
- {ekey.length || '?'}
-
-
-
-
-
- }
- variant="ghost"
- colorScheme="red"
- type="button"
- onClick={deleteKey}
- />
-
-
+
+
);
});
diff --git a/src/main.tsx b/src/main.tsx
index f5e600c..e15df44 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,4 +1,5 @@
import './pwa';
+import './App.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
diff --git a/src/tabs/MainTab.tsx b/src/tabs/MainTab.tsx
index e6dc61d..3491ce1 100644
--- a/src/tabs/MainTab.tsx
+++ b/src/tabs/MainTab.tsx
@@ -1,4 +1,4 @@
-import { Alert, AlertIcon, Box, Button, Flex, Text, VStack } from '@chakra-ui/react';
+import { RiErrorWarningLine } from 'react-icons/ri';
import { SelectFile } from '../components/SelectFile';
import { FileListing } from '~/features/file-listing/FileListing';
@@ -14,29 +14,32 @@ export function MainTab() {
};
return (
-
-
+
+
{isSettingsNotSaved && (
-
-
-
-
- 有尚未储存的设置,
-
- 设定将在保存后生效
-
-
+
);
}
diff --git a/src/tabs/SettingsTab.tsx b/src/tabs/SettingsTab.tsx
index 2642feb..ad63ec0 100644
--- a/src/tabs/SettingsTab.tsx
+++ b/src/tabs/SettingsTab.tsx
@@ -1,15 +1,9 @@
-import { Container, Flex, useBreakpointValue } from '@chakra-ui/react';
import { Settings } from '~/features/settings/Settings';
export function SettingsTab() {
- const containerProps = useBreakpointValue({
- base: { p: '0' },
- lg: { p: undefined },
- });
-
return (
-
+
-
+
);
}
diff --git a/vite.config.ts b/vite.config.ts
index a2a040b..6e11373 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -8,6 +8,7 @@ import wasm from 'vite-plugin-wasm';
import replace from '@rollup/plugin-replace';
import topLevelAwait from 'vite-plugin-top-level-await';
import { VitePWA } from 'vite-plugin-pwa';
+import tailwindcss from '@tailwindcss/vite';
import { tryCommand } from './support/command';
@@ -43,6 +44,7 @@ export default defineConfig({
exclude: ['@unlock-music/crypto', 'sql.js'],
},
plugins: [
+ tailwindcss(),
replace({
preventAssignment: true,
values: {